refactor: Change name of files and add some comments for them

This commit is contained in:
Behnamrhp74 2025-03-08 21:54:24 +03:00
parent 38f0d0a596
commit 7d9a6e77bd
70 changed files with 196 additions and 108 deletions

View File

@ -5,6 +5,9 @@ import CreateRandomInvoiceButtonVM from "@/app/[lang]/dashboard/vm/create-random
import { useDI } from "@/bootstrap/di/di-context"; import { useDI } from "@/bootstrap/di/di-context";
import { useRef } from "react"; import { useRef } from "react";
/**
* From a parent component Vm and view will be connected together.
*/
export default function CreateRandomInvoiceContainer() { export default function CreateRandomInvoiceContainer() {
const di = useDI(); const di = useDI();
const vm = useRef(di.resolve(CreateRandomInvoiceButtonVM)); const vm = useRef(di.resolve(CreateRandomInvoiceButtonVM));

View File

@ -2,17 +2,26 @@ import { DocumentIcon } from "@/app/components/icons/document";
import HomeIcon from "@/app/components/icons/home"; import HomeIcon from "@/app/components/icons/home";
import { UserIcon } from "@/app/components/icons/user"; import { UserIcon } from "@/app/components/icons/user";
import { usePathname } from "next/navigation"; import { usePathname } from "next/navigation";
import { useRef } from "react";
type LinkItem = { type LinkItem = {
name: string; name: string;
href: string; href: string;
icon: (props: { className?: string }) => JSX.Element; icon: (props: { className?: string }) => JSX.Element;
}; };
/**
* Beside of reusable vm each View can have it's own personal vm to handle it's ownlogics.
* Difference between personal vm and other vms which extends BaseVM, is that
* personal vm directly will be called inside of view and instinctly connected to the view,
* so they come together always and there is no need to be connected with interface for reusable
* vms.
*/
export default function navLinkPersonalVM() { export default function navLinkPersonalVM() {
const pathname = usePathname(); const pathname = usePathname();
// Map of links to display in the side navigation. // Map of links to display in the side navigation.
// Depending on the size of the application, this would be stored in a database. // Depending on the size of the application, this would be stored in a database.
const links: LinkItem[] = [ const links = useRef<LinkItem[]>([
{ name: "Home", href: "/dashboard", icon: HomeIcon }, { name: "Home", href: "/dashboard", icon: HomeIcon },
{ {
name: "Invoices", name: "Invoices",
@ -20,7 +29,7 @@ export default function navLinkPersonalVM() {
icon: DocumentIcon, icon: DocumentIcon,
}, },
{ name: "Customers", href: "/dashboard/customers", icon: UserIcon }, { name: "Customers", href: "/dashboard/customers", icon: UserIcon },
]; ]).current;
return { return {
links, links,
isLinkActive: (link: LinkItem) => pathname === link.href, isLinkActive: (link: LinkItem) => pathname === link.href,

View File

@ -1,6 +1,6 @@
"use client"; "use client";
import navLinkPersonalVM from "@/app/[lang]/dashboard/components/client/nav-links/nav-link-vm"; import navLinkPersonalVM from "@/app/[lang]/dashboard/components/client/nav-links/nav-link.personal-vm";
import clsx from "clsx"; import clsx from "clsx";
import Link from "next/link"; import Link from "next/link";

View File

@ -1,11 +1,13 @@
"use client" /* eslint-disable react/jsx-props-no-spreading */
import * as React from "react" "use client";
import { ThemeProvider as NextThemesProvider } from "next-themes"
import * as React from "react";
import { ThemeProvider as NextThemesProvider } from "next-themes";
export function ThemeProvider({ export function ThemeProvider({
children, children,
...props ...props
}: React.ComponentProps<typeof NextThemesProvider>) { }: React.ComponentProps<typeof NextThemesProvider>) {
return <NextThemesProvider {...props}>{children}</NextThemesProvider> return <NextThemesProvider {...props}>{children}</NextThemesProvider>;
} }

View File

@ -5,6 +5,9 @@ import {
InboxIcon, InboxIcon,
} from "@heroicons/react/24/outline"; } from "@heroicons/react/24/outline";
/**
* Controllers are bridge between feature layer and application layer.
*/
export default function cardController(props: { export default function cardController(props: {
type: "invoices" | "customers" | "pending" | "collected"; type: "invoices" | "customers" | "pending" | "collected";
}) { }) {

View File

@ -1,4 +1,4 @@
import cardController from "@/app/[lang]/dashboard/components/server/card/card-controller"; import cardController from "@/app/[lang]/dashboard/components/server/card/card.controller";
export function Card({ export function Card({
title, title,

View File

@ -1,6 +1,9 @@
import fetchSummaryInfoUsecase from "@/feature/core/summary-info/domain/usecase/fetch-summary-info-usecase"; import fetchSummaryInfoUsecase from "@/feature/core/summary-info/domain/usecase/fetch-summary-info.usecase";
import { connection } from "next/server"; import { connection } from "next/server";
/**
* Controllers are bridge between feature layer and application layer.
*/
export default function cardsController() { export default function cardsController() {
connection(); connection();
return fetchSummaryInfoUsecase(); return fetchSummaryInfoUsecase();

View File

@ -1,5 +1,5 @@
import { Card } from "@/app/[lang]/dashboard/components/server/card/card"; import { Card } from "@/app/[lang]/dashboard/components/server/card/card";
import cardsController from "@/app/[lang]/dashboard/components/server/cards/cards-controller"; import cardsController from "@/app/[lang]/dashboard/components/server/cards/cards.controller";
export default async function CardWrapper() { export default async function CardWrapper() {
const { customersNumber, invoicesNumber, invoicesSummary } = const { customersNumber, invoicesNumber, invoicesSummary } =

View File

@ -1,6 +1,9 @@
import fetchCustomerInvoicesUsecase from "@/feature/core/customer-invoice/domain/usecase/fetch-customer-invoices-usecase"; import fetchCustomerInvoicesUsecase from "@/feature/core/customer-invoice/domain/usecase/fetch-customer-invoices.usecase";
import { connection } from "next/server"; import { connection } from "next/server";
/**
* Controllers are bridge between feature layer and application layer.
*/
export default function latestInvoicesController() { export default function latestInvoicesController() {
connection(); connection();
return fetchCustomerInvoicesUsecase(); return fetchCustomerInvoicesUsecase();

View File

@ -1,5 +1,5 @@
import CreateRandomInvoiceContainer from "@/app/[lang]/dashboard/components/client/create-random-invoice/create-random-invoice"; import CreateRandomInvoiceContainer from "@/app/[lang]/dashboard/components/client/create-random-invoice/create-random-invoice";
import latestInvoicesController from "@/app/[lang]/dashboard/components/server/latest-invoices/latest-invoices-controller"; import latestInvoicesController from "@/app/[lang]/dashboard/components/server/latest-invoices/latest-invoices.controller";
import { ArrowPathIcon } from "@heroicons/react/24/outline"; import { ArrowPathIcon } from "@heroicons/react/24/outline";
import clsx from "clsx"; import clsx from "clsx";
import { isLeft } from "fp-ts/lib/Either"; import { isLeft } from "fp-ts/lib/Either";

View File

@ -1,6 +1,9 @@
import Revenue from "@/feature/core/revenue/domain/entity/revenue"; import Revenue from "@/feature/core/revenue/domain/entity/revenue.entity";
import fetchRevenuesUsecase from "@/feature/core/revenue/domain/usecase/fetch-revenues-usecase"; import fetchRevenuesUsecase from "@/feature/core/revenue/domain/usecase/fetch-revenues.usecase";
/**
* Controllers are bridge between feature layer and application layer.
*/
export default async function revenueChartController() { export default async function revenueChartController() {
const revenue = await fetchRevenuesUsecase(); const revenue = await fetchRevenuesUsecase();
const chartHeight = 350; const chartHeight = 350;

View File

@ -1,4 +1,4 @@
import revenueChartController from "@/app/[lang]/dashboard/components/server/revenue-chart/revenue-chart-controller"; import revenueChartController from "@/app/[lang]/dashboard/components/server/revenue-chart/revenue-chart.controller";
import { CalendarIcon } from "@heroicons/react/24/outline"; import { CalendarIcon } from "@heroicons/react/24/outline";
export default async function RevenueChart() { export default async function RevenueChart() {

View File

@ -1,7 +1,7 @@
"use client"; "use client";
import SideNav from "@/app/[lang]/dashboard/components/server/sidenav"; import SideNav from "@/app/[lang]/dashboard/components/server/sidenav";
import dashboardAppModule from "@/app/[lang]/dashboard/module/dashboard-app-module"; import dashboardAppModule from "@/app/[lang]/dashboard/module/dashboard.app-module";
import { DiContext } from "@/bootstrap/di/di-context"; import { DiContext } from "@/bootstrap/di/di-context";
import { useRef } from "react"; import { useRef } from "react";

View File

@ -1,7 +1,10 @@
import CreateRandomInvoiceButtonVM from "@/app/[lang]/dashboard/vm/create-random-invoice-button-vm"; import CreateRandomInvoiceButtonVM from "@/app/[lang]/dashboard/vm/create-random-invoice-button-vm";
import di from "@/bootstrap/di/init-di"; import di from "@/bootstrap/di/init-di";
import createInvoiceUsecase from "@/feature/core/invoice/domain/usecase/create-invoice-usecase"; import createInvoiceUsecase from "@/feature/core/invoice/domain/usecase/create-invoice.usecase";
/**
* Each page can have its own di to connect all vms, usecases or controllers
*/
export default function dashboardAppModule() { export default function dashboardAppModule() {
const dashboardDi = di.createChildContainer(); const dashboardDi = di.createChildContainer();

View File

@ -1,14 +1,19 @@
import ButtonVm from "@/app/components/button/button-vm"; import ButtonVm from "@/app/components/button/button.i-vm";
import { useServerAction } from "@/bootstrap/helpers/hooks/use-server-action"; import { useServerAction } from "@/bootstrap/helpers/hooks/use-server-action";
import useThrottle from "@/bootstrap/helpers/hooks/use-throttle"; import useThrottle from "@/bootstrap/helpers/hooks/use-throttle";
import BaseVM from "@/bootstrap/helpers/vm/base-vm"; import BaseVM from "@/bootstrap/helpers/vm/base-vm";
import langKey from "@/bootstrap/i18n/dictionaries/lang-key"; import langKey from "@/bootstrap/i18n/dictionaries/lang-key";
import { InvoiceParam } from "@/feature/core/invoice/domain/param/invoice-param"; import { InvoiceParam } from "@/feature/core/invoice/domain/param/invoice.param";
import createInvoiceUsecase from "@/feature/core/invoice/domain/usecase/create-invoice-usecase"; import createInvoiceUsecase from "@/feature/core/invoice/domain/usecase/create-invoice.usecase";
import { faker } from "@faker-js/faker"; import { faker } from "@faker-js/faker";
import { useRouter } from "next/navigation"; import { useRouter } from "next/navigation";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
/**
* Viewmodel for the button view to connect to business logics and all UI logics
* For UI logics, all translations, states, sideeffects and events will be handled
* in this layer.
*/
export default class CreateRandomInvoiceButtonVM extends BaseVM<ButtonVm> { export default class CreateRandomInvoiceButtonVM extends BaseVM<ButtonVm> {
private createInvoice: typeof createInvoiceUsecase; private createInvoice: typeof createInvoiceUsecase;

View File

@ -1,5 +1,5 @@
import { ThemeProvider } from "@/app/[lang]/dashboard/components/client/theme-provider/theme-provider"; import { ThemeProvider } from "@/app/[lang]/dashboard/components/client/theme-provider/theme-provider";
import { initI18next, LANGS } from "@/bootstrap/i18n/i18n"; import { getI18n, LANGS } from "@/bootstrap/i18n/i18n";
import TranslationsProvider from "@/bootstrap/i18n/i18n-provider"; import TranslationsProvider from "@/bootstrap/i18n/i18n-provider";
import localFont from "next/font/local"; import localFont from "next/font/local";
import { PropsWithChildren } from "react"; import { PropsWithChildren } from "react";
@ -20,7 +20,7 @@ export default async function layout(
) { ) {
const { params, children } = props; const { params, children } = props;
const { lang } = await params; const { lang } = await params;
const { resources } = await initI18next({ lng: lang }); const { resources } = await getI18n({ lng: lang });
return ( return (
<html lang={lang} suppressHydrationWarning> <html lang={lang} suppressHydrationWarning>
<body <body

View File

@ -1,7 +0,0 @@
export default interface ButtonVm {
props: {
title: string;
isDisable: boolean;
};
onClick(): void;
}

View File

@ -0,0 +1,11 @@
/**
* Interface for viewmodel of button. this is bridge between view and viewmodel.
* With this interface, view is adapter and vms will be implementations in bridge pattern
*/
export default interface ButtonVm {
props: {
title: string;
isDisable: boolean;
};
onClick(): void;
}

View File

@ -1,7 +1,7 @@
"use client"; "use client";
import BaseView, { BuildProps } from "@/bootstrap/helpers/view/base-view"; import BaseView, { BuildProps } from "@/bootstrap/helpers/view/base-view";
import ButtonVm from "@/app/components/button/button-vm"; import ButtonVm from "@/app/components/button/button.i-vm";
import { ReactNode } from "react"; import { ReactNode } from "react";
import * as React from "react"; import * as React from "react";
import { Slot } from "@radix-ui/react-slot"; import { Slot } from "@radix-ui/react-slot";

View File

@ -4,7 +4,7 @@ import { DiContext, useDI } from "@/bootstrap/di/di-context";
import mockedModuleDi from "@/bootstrap/di/mocked-module-di"; import mockedModuleDi from "@/bootstrap/di/mocked-module-di";
import Story from "@/bootstrap/helpers/view/storybook-base-template-type"; import Story from "@/bootstrap/helpers/view/storybook-base-template-type";
import getArgVM from "@/bootstrap/helpers/view/storybook-with-arg-vm"; import getArgVM from "@/bootstrap/helpers/view/storybook-with-arg-vm";
import createInvoiceUsecase from "@/feature/core/invoice/domain/usecase/create-invoice-usecase"; import createInvoiceUsecase from "@/feature/core/invoice/domain/usecase/create-invoice.usecase";
import type { Meta } from "@storybook/react"; import type { Meta } from "@storybook/react";
import { useRef } from "react"; import { useRef } from "react";

View File

@ -2,6 +2,9 @@ import { constructor } from "tsyringe/dist/typings/types";
export const isServer = typeof window === "undefined"; export const isServer = typeof window === "undefined";
/**
* Checks if the given value is a class
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any
export function isClass(fn: any): fn is constructor<unknown> { export function isClass(fn: any): fn is constructor<unknown> {
return typeof fn === "function" && /^(class|function [A-Z])/.test(fn); return typeof fn === "function" && /^(class|function [A-Z])/.test(fn);

View File

@ -1,6 +1,10 @@
import { clsx, type ClassValue } from "clsx"; import { clsx, type ClassValue } from "clsx";
import { twMerge } from "tailwind-merge"; import { twMerge } from "tailwind-merge";
/**
* To connect tailwind classes.
* @param inputs Tailwind classes
*/
export function cn(...inputs: ClassValue[]) { export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs)); return twMerge(clsx(inputs));
} }

View File

@ -66,6 +66,11 @@ export type BuildProps<
children?: ReactNode; children?: ReactNode;
}; };
/**
* Base view is base component for all views in mvvm architecture which gets
* vm as props and connect it to the view and memoize the component by default
* to just render just on changes of its vm.
*/
export default abstract class BaseView< export default abstract class BaseView<
IVM extends IVMParent, IVM extends IVMParent,
PROPS extends IPropParent = undefined, PROPS extends IPropParent = undefined,

View File

@ -1,5 +1,12 @@
import IBaseVM from "@/bootstrap/helpers/vm/i-base-vm"; import IBaseVM from "@/bootstrap/helpers/vm/i-base-vm";
/**
* To use with mvvm library to make a vm based on props so you can pass the result to the view
* @param vmObj All properties which view needs to get from vm.
* @returns Vm which is suitable to be passed to the view
* @example const vm = getArgVM(globalData.parsedProps.vm);
return <Button vm={vm} memoizedByVM={false} />;
*/
const getArgVM = <IVM>(vmObj: IVM) => { const getArgVM = <IVM>(vmObj: IVM) => {
class VM implements IBaseVM<IVM> { class VM implements IBaseVM<IVM> {
useVM(): IVM { useVM(): IVM {

View File

@ -5,6 +5,12 @@ import { NoOverride } from "@/bootstrap/helpers/type-helper";
import IBaseVM from "@/bootstrap/helpers/vm/i-base-vm"; import IBaseVM from "@/bootstrap/helpers/vm/i-base-vm";
import { useState } from "react"; import { useState } from "react";
/**
* Base class for all viewmodels. It provides
* - dependency injection: To get closes di which serves from di provider
* - rerender method: to rerender your component manually
* - produce method: to produce your vm dynamically by passing and attaching dependencies to it
*/
export default abstract class BaseVM< export default abstract class BaseVM<
IVM, IVM,
DEP extends object | undefined = undefined, DEP extends object | undefined = undefined,

View File

@ -1,3 +1,6 @@
/**
* All viewmodels should implement this interface.
*/
export default interface IBaseVM<VM> { export default interface IBaseVM<VM> {
useVM(): VM; useVM(): VM;
} }

View File

@ -1,3 +1,8 @@
/**
* main language keys which will be used for translation to avoid using strings directly and be
* a single source of truth in all changes between all languages dictionaries.
* All languages dictionaries should have the same keys by having this object type.
*/
const langKey = { const langKey = {
global: { global: {
home: "global.home", home: "global.home",

View File

@ -1,7 +1,7 @@
"use client"; "use client";
import { I18nextProvider } from "react-i18next"; import { I18nextProvider } from "react-i18next";
import { i18nInstance, initI18next, LANGS } from "@/bootstrap/i18n/i18n"; import { i18nInstance, getI18n, LANGS } from "@/bootstrap/i18n/i18n";
import { Resource } from "i18next"; import { Resource } from "i18next";
import { PropsWithChildren } from "react"; import { PropsWithChildren } from "react";
@ -11,7 +11,7 @@ export default function TranslationsProvider({
resources, resources,
}: PropsWithChildren & { lng: LANGS; resources: Resource }) { }: PropsWithChildren & { lng: LANGS; resources: Resource }) {
if (!resources) return children; if (!resources) return children;
initI18next({ lng, resources }); getI18n({ lng, resources });
return <I18nextProvider i18n={i18nInstance}>{children}</I18nextProvider>; return <I18nextProvider i18n={i18nInstance}>{children}</I18nextProvider>;
} }

View File

@ -1,6 +1,6 @@
import { Either } from "fp-ts/lib/Either"; import { Either } from "fp-ts/lib/Either";
import { TaskEither } from "fp-ts/lib/TaskEither"; import { TaskEither } from "fp-ts/lib/TaskEither";
import BaseFailure from "@/feature/common/failures/base-failure"; import BaseFailure from "@/feature/common/failures/base.failure";
type ApiTask<ResponseType> = TaskEither<BaseFailure<unknown>, ResponseType>; type ApiTask<ResponseType> = TaskEither<BaseFailure<unknown>, ResponseType>;
export type ApiEither<ResponseType> = Either< export type ApiEither<ResponseType> = Either<

View File

@ -1,8 +1,14 @@
import { makeFailureMessage } from "@/feature/common/failures/failure-helpers"; import { makeFailureMessage } from "@/feature/common/failures/failure-helpers";
/** /**
* This is a class called BaseFailure that extends the Error class. It is * This class can be used as a base class for creating custom failure classes.
* used as a base class for creating custom failure classes. * With this class you can set message and metadata, with messages and extending
* you can create your failure messages hierarchy and automatically by syncing langKey
* with the hirerarchy of failure messages.
* For example if you pass a key of `user` to the constructor of `UserCreationFailure`
* so in langKey you can have failure message `faiure.user` so automatically,
* you can show translated error message everywhere in the app.
* Also you can use this failure message to have grained control over failures.
*/ */
export default abstract class BaseFailure<META_DATA> { export default abstract class BaseFailure<META_DATA> {
/* ------------------------------- Attributes ------------------------------- */ /* ------------------------------- Attributes ------------------------------- */

View File

@ -1,4 +1,4 @@
import BaseDevFailure from "@/feature/common/failures/dev/base-dev-failure"; import BaseDevFailure from "@/feature/common/failures/dev/base-dev.failure";
/** /**
* Failure for needed arguments in a method but sent wrong one * Failure for needed arguments in a method but sent wrong one

View File

@ -1,5 +0,0 @@
import BaseFailure from "@/feature/common/failures/base-failure";
export default abstract class BaseDevFailure<
META_DATA,
> extends BaseFailure<META_DATA> {}

View File

@ -0,0 +1,10 @@
import BaseFailure from "@/feature/common/failures/base.failure";
/**
* This is a base class for development failures. All dev failures means we as a developer
* made a mistake in the process and we should fix it and can be used in monitoring and
* should be handled in hotfix ASAP.
*/
export default abstract class BaseDevFailure<
META_DATA,
> extends BaseFailure<META_DATA> {}

View File

@ -1,7 +1,7 @@
import BaseDevFailure from "@/feature/common/failures/dev/base-dev-failure"; import BaseDevFailure from "@/feature/common/failures/dev/base-dev.failure";
/** /**
* This is a failure of not having specific dependency * This is a failure when we didn't provice specific dependency.
*/ */
export default class DependencyFailure< export default class DependencyFailure<
META_DATA, META_DATA,

View File

@ -1,5 +1,5 @@
/* eslint-disable @typescript-eslint/no-explicit-any */ /* eslint-disable @typescript-eslint/no-explicit-any */
import BaseFailure from "@/feature/common/failures/base-failure"; import BaseFailure from "@/feature/common/failures/base.failure";
/** /**
* This method is supposed to save previous failure of TaskEither * This method is supposed to save previous failure of TaskEither

View File

@ -1,4 +1,4 @@
import BaseFailure from "./base-failure"; import BaseFailure from "./base.failure";
/** /**
* Failure for HTTP response when response dosn't have base structure * Failure for HTTP response when response dosn't have base structure

View File

@ -1,7 +1,7 @@
import BaseFailure from "./base-failure"; import BaseFailure from "./base.failure";
/** /**
* Failure for params failure * Failure for params failure. which means some params are missing or not valid
*/ */
export default class ParamsFailure<META_DATA> extends BaseFailure<META_DATA> { export default class ParamsFailure<META_DATA> extends BaseFailure<META_DATA> {
/* ------------------------------- Constructor ------------------------------ */ /* ------------------------------- Constructor ------------------------------ */

View File

@ -1,14 +1,14 @@
import getCustomerInvoiceDi from "@/feature/core/customer-invoice/data/module/customer-invoice-di"; import getCustomerInvoiceDi from "@/feature/core/customer-invoice/data/module/customer-invoice.di";
import { customerInvoiceModuleKey } from "@/feature/core/customer-invoice/invoice-module-key"; import { customerInvoiceModuleKey } from "@/feature/core/customer-invoice/invoice.module-key";
import { customerKey } from "@/feature/core/customer/customer-key"; import { customerKey } from "@/feature/core/customer/customer-key";
import getCustomerDi from "@/feature/core/customer/data/module/customer-di"; import getCustomerDi from "@/feature/core/customer/data/module/customer-di";
import getInvoiceDi from "@/feature/core/invoice/data/module/invoice-di"; import getInvoiceDi from "@/feature/core/invoice/data/module/invoice.di";
import { invoiceModuleKey } from "@/feature/core/invoice/invoice-module-key"; import { invoiceModuleKey } from "@/feature/core/invoice/invoice.module-key";
import { DependencyContainer } from "tsyringe"; import { DependencyContainer } from "tsyringe";
import { summaryInfoModuleKey } from "@/feature/core/summary-info/domain/summary-info-module-key"; import { summaryInfoModuleKey } from "@/feature/core/summary-info/domain/summary-info.module-key";
import getSummaryInfoDi from "@/feature/core/summary-info/data/module/summary-info-di"; import getSummaryInfoDi from "@/feature/core/summary-info/data/module/summary-info.di";
import { revenueModuleKey } from "@/feature/core/revenue/domain/revenue-module-key"; import { revenueModuleKey } from "@/feature/core/revenue/domain/revenue.module-key";
import getRevenueDi from "@/feature/core/revenue/data/module/revenue-di"; import getRevenueDi from "@/feature/core/revenue/data/module/revenue.di";
const memoizedDis: Record<string, DependencyContainer> = {}; const memoizedDis: Record<string, DependencyContainer> = {};

View File

@ -1,6 +1,6 @@
import di from "@/bootstrap/di/init-di"; import di from "@/bootstrap/di/init-di";
import CustomerInvoiceDbRepo from "@/feature/core/customer-invoice/data/repo/customer-invoice-db-repo"; import CustomerInvoiceDbRepo from "@/feature/core/customer-invoice/data/repo/customer-invoice-db.repo";
import { customerInvoiceRepoKey } from "@/feature/core/customer-invoice/domain/i-repo/customer-invoice-repo"; import { customerInvoiceRepoKey } from "@/feature/core/customer-invoice/domain/i-repo/customer-invoice.repo";
import { DependencyContainer } from "tsyringe"; import { DependencyContainer } from "tsyringe";
export default function getCustomerInvoiceDi(): DependencyContainer { export default function getCustomerInvoiceDi(): DependencyContainer {

View File

@ -1,10 +1,10 @@
import { sql } from "@/bootstrap/boundaries/db/db"; import { sql } from "@/bootstrap/boundaries/db/db";
import ApiTask from "@/feature/common/data/api-task"; import ApiTask from "@/feature/common/data/api-task";
import { failureOr } from "@/feature/common/failures/failure-helpers"; import { failureOr } from "@/feature/common/failures/failure-helpers";
import NetworkFailure from "@/feature/common/failures/network-failure"; import NetworkFailure from "@/feature/common/failures/network.failure";
import { formatCurrency } from "@/feature/common/feature-helpers"; import { formatCurrency } from "@/feature/common/feature-helpers";
import CustomerInvoice from "@/feature/core/customer-invoice/domain/entity/customer-invoice"; import CustomerInvoice from "@/feature/core/customer-invoice/domain/entity/customer-invoice.entity";
import CustomerInvoiceRepo from "@/feature/core/customer-invoice/domain/i-repo/customer-invoice-repo"; import CustomerInvoiceRepo from "@/feature/core/customer-invoice/domain/i-repo/customer-invoice.repo";
import { pipe } from "fp-ts/lib/function"; import { pipe } from "fp-ts/lib/function";
import { tryCatch } from "fp-ts/lib/TaskEither"; import { tryCatch } from "fp-ts/lib/TaskEither";
import postgres from "postgres"; import postgres from "postgres";

View File

@ -1,5 +1,5 @@
import ApiTask from "@/feature/common/data/api-task"; import ApiTask from "@/feature/common/data/api-task";
import CustomerInvoice from "@/feature/core/customer-invoice/domain/entity/customer-invoice"; import CustomerInvoice from "@/feature/core/customer-invoice/domain/entity/customer-invoice.entity";
export default interface CustomerInvoiceRepo { export default interface CustomerInvoiceRepo {
fetchList(): ApiTask<CustomerInvoice[]>; fetchList(): ApiTask<CustomerInvoice[]>;

View File

@ -1,11 +1,11 @@
import "server-only"; import "server-only";
import { ApiEither } from "@/feature/common/data/api-task"; import { ApiEither } from "@/feature/common/data/api-task";
import serverDi from "@/feature/common/server-di"; import serverDi from "@/feature/common/server.di";
import CustomerInvoice from "@/feature/core/customer-invoice/domain/entity/customer-invoice"; import CustomerInvoice from "@/feature/core/customer-invoice/domain/entity/customer-invoice.entity";
import CustomerInvoiceRepo, { import CustomerInvoiceRepo, {
customerInvoiceRepoKey, customerInvoiceRepoKey,
} from "@/feature/core/customer-invoice/domain/i-repo/customer-invoice-repo"; } from "@/feature/core/customer-invoice/domain/i-repo/customer-invoice.repo";
import { customerInvoiceModuleKey } from "@/feature/core/customer-invoice/invoice-module-key"; import { customerInvoiceModuleKey } from "@/feature/core/customer-invoice/invoice.module-key";
export default function fetchCustomerInvoicesUsecase(): Promise< export default function fetchCustomerInvoicesUsecase(): Promise<
ApiEither<CustomerInvoice[]> ApiEither<CustomerInvoice[]>

View File

@ -1,7 +1,7 @@
import { sql } from "@/bootstrap/boundaries/db/db"; import { sql } from "@/bootstrap/boundaries/db/db";
import ApiTask from "@/feature/common/data/api-task"; import ApiTask from "@/feature/common/data/api-task";
import { failureOr } from "@/feature/common/failures/failure-helpers"; import { failureOr } from "@/feature/common/failures/failure-helpers";
import NetworkFailure from "@/feature/common/failures/network-failure"; import NetworkFailure from "@/feature/common/failures/network.failure";
import { formatCurrency } from "@/feature/common/feature-helpers"; import { formatCurrency } from "@/feature/common/feature-helpers";
import Customer from "@/feature/core/customer/domain/entity/customer"; import Customer from "@/feature/core/customer/domain/entity/customer";
import CustomerRepo from "@/feature/core/customer/domain/i-repo/customer-repo"; import CustomerRepo from "@/feature/core/customer/domain/i-repo/customer-repo";

View File

@ -1,5 +1,5 @@
import "server-only"; import "server-only";
import serverDi from "@/feature/common/server-di"; import serverDi from "@/feature/common/server.di";
import { customerKey } from "@/feature/core/customer/customer-key"; import { customerKey } from "@/feature/core/customer/customer-key";
import CustomerRepo, { import CustomerRepo, {
customerRepoKey, customerRepoKey,

View File

@ -1,6 +1,6 @@
import "server-only"; import "server-only";
import { ApiEither } from "@/feature/common/data/api-task"; import { ApiEither } from "@/feature/common/data/api-task";
import serverDi from "@/feature/common/server-di"; import serverDi from "@/feature/common/server.di";
import { customerKey } from "@/feature/core/customer/customer-key"; import { customerKey } from "@/feature/core/customer/customer-key";
import Customer from "@/feature/core/customer/domain/entity/customer"; import Customer from "@/feature/core/customer/domain/entity/customer";
import CustomerRepo, { import CustomerRepo, {

View File

@ -1,6 +1,6 @@
import di from "@/bootstrap/di/init-di"; import di from "@/bootstrap/di/init-di";
import invoiceDbRepo from "@/feature/core/invoice/data/repo/invoice-db-repo"; import invoiceDbRepo from "@/feature/core/invoice/data/repo/invoice-db.repo";
import { invoiceRepoKey } from "@/feature/core/invoice/domain/i-repo/invoice-repo"; import { invoiceRepoKey } from "@/feature/core/invoice/domain/i-repo/invoice.i-repo";
import { DependencyContainer } from "tsyringe"; import { DependencyContainer } from "tsyringe";
export default function getInvoiceDi(): DependencyContainer { export default function getInvoiceDi(): DependencyContainer {

View File

@ -1,11 +1,11 @@
import { sql } from "@/bootstrap/boundaries/db/db"; import { sql } from "@/bootstrap/boundaries/db/db";
import ApiTask from "@/feature/common/data/api-task"; import ApiTask from "@/feature/common/data/api-task";
import { failureOr } from "@/feature/common/failures/failure-helpers"; import { failureOr } from "@/feature/common/failures/failure-helpers";
import NetworkFailure from "@/feature/common/failures/network-failure"; import NetworkFailure from "@/feature/common/failures/network.failure";
import { formatCurrency } from "@/feature/common/feature-helpers"; import { formatCurrency } from "@/feature/common/feature-helpers";
import InvoiceRepo from "@/feature/core/invoice/domain/i-repo/invoice-repo"; import InvoiceRepo from "@/feature/core/invoice/domain/i-repo/invoice.i-repo";
import { InvoiceParam } from "@/feature/core/invoice/domain/param/invoice-param"; import { InvoiceParam } from "@/feature/core/invoice/domain/param/invoice.param";
import InvoiceStatusSummary from "@/feature/core/invoice/domain/value-object/invoice-status"; import InvoiceStatusSummary from "@/feature/core/invoice/domain/value-object/invoice-status.value-object";
import { pipe } from "fp-ts/lib/function"; import { pipe } from "fp-ts/lib/function";
import { tryCatch } from "fp-ts/lib/TaskEither"; import { tryCatch } from "fp-ts/lib/TaskEither";
import postgres from "postgres"; import postgres from "postgres";

View File

@ -1,6 +1,6 @@
import ApiTask from "@/feature/common/data/api-task"; import ApiTask from "@/feature/common/data/api-task";
import { InvoiceParam } from "@/feature/core/invoice/domain/param/invoice-param"; import { InvoiceParam } from "@/feature/core/invoice/domain/param/invoice.param";
import InvoiceStatusSummary from "@/feature/core/invoice/domain/value-object/invoice-status"; import InvoiceStatusSummary from "@/feature/core/invoice/domain/value-object/invoice-status.value-object";
export default interface InvoiceRepo { export default interface InvoiceRepo {
fetchAllInvoicesAmount(): Promise<number>; fetchAllInvoicesAmount(): Promise<number>;

View File

@ -1,16 +1,16 @@
"use server"; "use server";
import { ApiEither } from "@/feature/common/data/api-task"; import { ApiEither } from "@/feature/common/data/api-task";
import ParamsFailure from "@/feature/common/failures/params-failure"; import ParamsFailure from "@/feature/common/failures/params.failure";
import serverDi from "@/feature/common/server-di"; import serverDi from "@/feature/common/server.di";
import InvoiceRepo, { import InvoiceRepo, {
invoiceRepoKey, invoiceRepoKey,
} from "@/feature/core/invoice/domain/i-repo/invoice-repo"; } from "@/feature/core/invoice/domain/i-repo/invoice.i-repo";
import { import {
InvoiceParam, InvoiceParam,
invoiceSchema, invoiceSchema,
} from "@/feature/core/invoice/domain/param/invoice-param"; } from "@/feature/core/invoice/domain/param/invoice.param";
import { invoiceModuleKey } from "@/feature/core/invoice/invoice-module-key"; import { invoiceModuleKey } from "@/feature/core/invoice/invoice.module-key";
import { pipe } from "fp-ts/lib/function"; import { pipe } from "fp-ts/lib/function";
import { chain, fromNullable, left, map, right } from "fp-ts/lib/TaskEither"; import { chain, fromNullable, left, map, right } from "fp-ts/lib/TaskEither";

View File

@ -1,9 +1,9 @@
import "server-only"; import "server-only";
import serverDi from "@/feature/common/server-di"; import serverDi from "@/feature/common/server.di";
import InvoiceRepo, { import InvoiceRepo, {
invoiceRepoKey, invoiceRepoKey,
} from "@/feature/core/invoice/domain/i-repo/invoice-repo"; } from "@/feature/core/invoice/domain/i-repo/invoice.i-repo";
import { invoiceModuleKey } from "@/feature/core/invoice/invoice-module-key"; import { invoiceModuleKey } from "@/feature/core/invoice/invoice.module-key";
export default function fetchAllInvoicesAmountUsecase(): Promise<number> { export default function fetchAllInvoicesAmountUsecase(): Promise<number> {
const repo = serverDi(invoiceModuleKey).resolve<InvoiceRepo>(invoiceRepoKey); const repo = serverDi(invoiceModuleKey).resolve<InvoiceRepo>(invoiceRepoKey);

View File

@ -1,10 +1,10 @@
import "server-only"; import "server-only";
import serverDi from "@/feature/common/server-di"; import serverDi from "@/feature/common/server.di";
import InvoiceRepo, { import InvoiceRepo, {
invoiceRepoKey, invoiceRepoKey,
} from "@/feature/core/invoice/domain/i-repo/invoice-repo"; } from "@/feature/core/invoice/domain/i-repo/invoice.i-repo";
import InvoiceStatusSummary from "@/feature/core/invoice/domain/value-object/invoice-status"; import InvoiceStatusSummary from "@/feature/core/invoice/domain/value-object/invoice-status.value-object";
import { invoiceModuleKey } from "@/feature/core/invoice/invoice-module-key"; import { invoiceModuleKey } from "@/feature/core/invoice/invoice.module-key";
export default function fetchInvoicesStatusSummary(): Promise<InvoiceStatusSummary> { export default function fetchInvoicesStatusSummary(): Promise<InvoiceStatusSummary> {
const repo = serverDi(invoiceModuleKey).resolve<InvoiceRepo>(invoiceRepoKey); const repo = serverDi(invoiceModuleKey).resolve<InvoiceRepo>(invoiceRepoKey);

View File

@ -1,6 +1,6 @@
import di from "@/bootstrap/di/init-di"; import di from "@/bootstrap/di/init-di";
import RevenueDbRepo from "@/feature/core/revenue/data/repo/revenue-db-repo"; import RevenueDbRepo from "@/feature/core/revenue/data/repo/revenue-db.repo";
import { revenueRepoKey } from "@/feature/core/revenue/domain/i-repo/revenue-repo"; import { revenueRepoKey } from "@/feature/core/revenue/domain/i-repo/revenue.i-repo";
export default function getRevenueDi() { export default function getRevenueDi() {
const revenueDi = di.createChildContainer(); const revenueDi = di.createChildContainer();

View File

@ -1,6 +1,6 @@
import { sql } from "@/bootstrap/boundaries/db/db"; import { sql } from "@/bootstrap/boundaries/db/db";
import Revenue from "@/feature/core/revenue/domain/entity/revenue"; import Revenue from "@/feature/core/revenue/domain/entity/revenue.entity";
import RevenueRepo from "@/feature/core/revenue/domain/i-repo/revenue-repo"; import RevenueRepo from "@/feature/core/revenue/domain/i-repo/revenue.i-repo";
import postgres from "postgres"; import postgres from "postgres";
export type RevenueDbResponse = { export type RevenueDbResponse = {

View File

@ -1,4 +1,4 @@
import Revenue from "@/feature/core/revenue/domain/entity/revenue"; import Revenue from "@/feature/core/revenue/domain/entity/revenue.entity";
export default interface RevenueRepo { export default interface RevenueRepo {
fetchRevenues(): Promise<Revenue[]>; fetchRevenues(): Promise<Revenue[]>;

View File

@ -1,10 +1,10 @@
import "server-only"; import "server-only";
import serverDi from "@/feature/common/server-di"; import serverDi from "@/feature/common/server.di";
import Revenue from "@/feature/core/revenue/domain/entity/revenue"; import Revenue from "@/feature/core/revenue/domain/entity/revenue.entity";
import RevenueRepo, { import RevenueRepo, {
revenueRepoKey, revenueRepoKey,
} from "@/feature/core/revenue/domain/i-repo/revenue-repo"; } from "@/feature/core/revenue/domain/i-repo/revenue.i-repo";
import { revenueModuleKey } from "@/feature/core/revenue/domain/revenue-module-key"; import { revenueModuleKey } from "@/feature/core/revenue/domain/revenue.module-key";
export default function fetchRevenuesUsecase(): Promise<Revenue[]> { export default function fetchRevenuesUsecase(): Promise<Revenue[]> {
const repo = serverDi(revenueModuleKey).resolve<RevenueRepo>(revenueRepoKey); const repo = serverDi(revenueModuleKey).resolve<RevenueRepo>(revenueRepoKey);

View File

@ -1,6 +1,6 @@
import fetchCustomersAmountUsecase from "@/feature/core/customer/domain/usecase/fetch-customers-amount-usecase"; import fetchCustomersAmountUsecase from "@/feature/core/customer/domain/usecase/fetch-customers-amount-usecase";
import fetchAllInvoicesAmountUsecase from "@/feature/core/invoice/domain/usecase/fetch-all-invoices-amount-usecase"; import fetchAllInvoicesAmountUsecase from "@/feature/core/invoice/domain/usecase/fetch-all-invoices-amount.usecase";
import fetchInvoicesStatusSummary from "@/feature/core/invoice/domain/usecase/fetch-invoices-status-summary"; import fetchInvoicesStatusSummary from "@/feature/core/invoice/domain/usecase/fetch-invoices-status-summary.usecase";
import di from "@/bootstrap/di/init-di"; import di from "@/bootstrap/di/init-di";
export default function getSummaryInfoDi() { export default function getSummaryInfoDi() {

View File

@ -1,10 +1,10 @@
import "server-only"; import "server-only";
import serverDi from "@/feature/common/server-di"; import serverDi from "@/feature/common/server.di";
import fetchCustomersAmountUsecase from "@/feature/core/customer/domain/usecase/fetch-customers-amount-usecase"; import fetchCustomersAmountUsecase from "@/feature/core/customer/domain/usecase/fetch-customers-amount-usecase";
import fetchAllInvoicesAmountUsecase from "@/feature/core/invoice/domain/usecase/fetch-all-invoices-amount-usecase"; import fetchAllInvoicesAmountUsecase from "@/feature/core/invoice/domain/usecase/fetch-all-invoices-amount.usecase";
import fetchInvoicesStatusSummary from "@/feature/core/invoice/domain/usecase/fetch-invoices-status-summary"; import fetchInvoicesStatusSummary from "@/feature/core/invoice/domain/usecase/fetch-invoices-status-summary.usecase";
import { summaryInfoModuleKey } from "@/feature/core/summary-info/domain/summary-info-module-key"; import { summaryInfoModuleKey } from "@/feature/core/summary-info/domain/summary-info.module-key";
import SummaryInfo from "@/feature/core/summary-info/domain/value-object/summary-info"; import SummaryInfo from "@/feature/core/summary-info/domain/value-object/summary-info.value-object";
export default async function fetchSummaryInfoUsecase(): Promise<SummaryInfo> { export default async function fetchSummaryInfoUsecase(): Promise<SummaryInfo> {
try { try {

View File

@ -1,4 +1,4 @@
import InvoiceStatusSummary from "@/feature/core/invoice/domain/value-object/invoice-status"; import InvoiceStatusSummary from "@/feature/core/invoice/domain/value-object/invoice-status.value-object";
export default class SummaryInfo { export default class SummaryInfo {
customersNumber: number; customersNumber: number;

View File

@ -1,6 +1,9 @@
import di from "@/bootstrap/di/init-di"; import di from "@/bootstrap/di/init-di";
import * as serverDi from "@/feature/common/server-di"; import * as serverDi from "@/feature/common/server.di";
/**
* To mock and get server di
*/
export default function mockDi() { export default function mockDi() {
vi.spyOn(serverDi, "default").mockReturnValue(di); vi.spyOn(serverDi, "default").mockReturnValue(di);
return di; return di;

View File

@ -1,5 +1,8 @@
import { Mock } from "moq.ts"; import { Mock } from "moq.ts";
/**
* To get mock object to mock objects and classes
*/
export function getMock<T>() { export function getMock<T>() {
return new Mock<T>(); return new Mock<T>();
} }

View File

@ -4,7 +4,7 @@ import CustomerRepo, {
import { getMock } from "@/test/common/mock/mock-factory"; import { getMock } from "@/test/common/mock/mock-factory";
import { describe } from "vitest"; import { describe } from "vitest";
import { faker } from "@faker-js/faker"; import { faker } from "@faker-js/faker";
import CustomerFakeFactory from "@/test/common/fake-factory/customer/customer-fake-factory"; import CustomerFakeFactory from "@/test/common/fake-factory/customer/customer.fake-factory";
import fetchCustomersUsecase from "@/feature/core/customer/domain/usecase/fetch-customers-usecase"; import fetchCustomersUsecase from "@/feature/core/customer/domain/usecase/fetch-customers-usecase";
import mockDi from "@/test/common/mock/mock-di"; import mockDi from "@/test/common/mock/mock-di";
import { right } from "fp-ts/lib/TaskEither"; import { right } from "fp-ts/lib/TaskEither";