From 69640da28ec3da1412353a7f37e48797831615aa Mon Sep 17 00:00:00 2001 From: behnam <behnamrahimpour74@gmail.com> Date: Tue, 29 Oct 2024 19:53:28 +0300 Subject: [PATCH 01/37] Add basic di in client side --- .eslintrc.json | 10 + package.json | 12 +- src/app/layout.tsx | 2 +- src/app/test/page.tsx | 8 + src/app/test/vm/test-button-vm.ts | 17 + src/bootstrap/di/init-di.ts | 18 + src/bootstrap/helpers/type-helper.ts | 8 + src/bootstrap/helpers/view/base-view.tsx | 95 + src/bootstrap/helpers/vm/base-vm.ts | 46 + src/bootstrap/helpers/vm/i-base-vm.ts | 3 + src/bootstrap/helpers/vm/vm-decorator.ts | 9 + src/components/button/button-vm.ts | 6 + src/components/button/button.tsx | 10 + tsconfig.json | 2 + yarn.lock | 2879 ++++++++++++++++++++++ 15 files changed, 3119 insertions(+), 6 deletions(-) create mode 100644 src/app/test/page.tsx create mode 100644 src/app/test/vm/test-button-vm.ts create mode 100644 src/bootstrap/di/init-di.ts create mode 100644 src/bootstrap/helpers/type-helper.ts create mode 100644 src/bootstrap/helpers/view/base-view.tsx create mode 100644 src/bootstrap/helpers/vm/base-vm.ts create mode 100644 src/bootstrap/helpers/vm/i-base-vm.ts create mode 100644 src/bootstrap/helpers/vm/vm-decorator.ts create mode 100644 src/components/button/button-vm.ts create mode 100644 src/components/button/button.tsx create mode 100644 yarn.lock diff --git a/.eslintrc.json b/.eslintrc.json index 3722418..60d067f 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -1,3 +1,13 @@ { + "overrides": [ + { + "files": [ + "src/**/*-vm.ts" + ], + "rules": { + "react-hooks/rules-of-hooks": "off" + } + } + ], "extends": ["next/core-web-vitals", "next/typescript"] } diff --git a/package.json b/package.json index d10c385..2db330d 100644 --- a/package.json +++ b/package.json @@ -5,22 +5,24 @@ "scripts": { "dev": "next dev --turbopack", "build": "next build", - "start": "next start", + "start": "next start --port 4000", "lint": "next lint" }, "dependencies": { + "next": "15.0.1", "react": "19.0.0-rc-69d4b800-20241021", "react-dom": "19.0.0-rc-69d4b800-20241021", - "next": "15.0.1" + "reflect-metadata": "^0.2.2", + "tsyringe": "^4.8.0" }, "devDependencies": { - "typescript": "^5", "@types/node": "^20", "@types/react": "^18", "@types/react-dom": "^18", + "eslint": "^8", + "eslint-config-next": "15.0.1", "postcss": "^8", "tailwindcss": "^3.4.1", - "eslint": "^8", - "eslint-config-next": "15.0.1" + "typescript": "^5" } } diff --git a/src/app/layout.tsx b/src/app/layout.tsx index a36cde0..1cd9211 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -1,7 +1,7 @@ +import "reflect-metadata" import type { Metadata } from "next"; import localFont from "next/font/local"; import "./globals.css"; - const geistSans = localFont({ src: "./fonts/GeistVF.woff", variable: "--font-geist-sans", diff --git a/src/app/test/page.tsx b/src/app/test/page.tsx new file mode 100644 index 0000000..f08fc5e --- /dev/null +++ b/src/app/test/page.tsx @@ -0,0 +1,8 @@ +"use client" +import "reflect-metadata" +import TestButtonVM from "@/app/test/vm/test-button-vm"; +import Button from "@/components/button/button"; + +export default function Page() { + return <Button vmName={TestButtonVM.name} /> +} \ No newline at end of file diff --git a/src/app/test/vm/test-button-vm.ts b/src/app/test/vm/test-button-vm.ts new file mode 100644 index 0000000..414d5ce --- /dev/null +++ b/src/app/test/vm/test-button-vm.ts @@ -0,0 +1,17 @@ +import BaseVM from "@/bootstrap/helpers/vm/base-vm"; +import injectableVm from "@/bootstrap/helpers/vm/vm-decorator"; +import ButtonVm from "@/components/button/button-vm"; + +@injectableVm() +export default class TestButtonVM extends BaseVM<ButtonVm> { + useVM(): ButtonVm { + return { + props: { + title: "Test Button" + }, + onClick: () => { + console.log("clicked on the button"); + } + } + } +} \ No newline at end of file diff --git a/src/bootstrap/di/init-di.ts b/src/bootstrap/di/init-di.ts new file mode 100644 index 0000000..79281ec --- /dev/null +++ b/src/bootstrap/di/init-di.ts @@ -0,0 +1,18 @@ +import "reflect-metadata" + +import { container, DependencyContainer } from "tsyringe"; + +/** + * Serves as a central point for initializing and configuring + * the DI container, ensuring that all necessary dependencies + * are registered and available for injection throughout the application. + */ +const InitDI = (): DependencyContainer => { + const di = container; + + return di; +}; + +const di = InitDI(); + +export default di; \ No newline at end of file diff --git a/src/bootstrap/helpers/type-helper.ts b/src/bootstrap/helpers/type-helper.ts new file mode 100644 index 0000000..c484e86 --- /dev/null +++ b/src/bootstrap/helpers/type-helper.ts @@ -0,0 +1,8 @@ +declare const _: unique symbol; + +type Forbidden = { [_]: typeof _ }; + +/** + * You can use this type to make your parent class method forbidden to overwrite + */ +export type NoOverride<T = void> = T & Forbidden; \ No newline at end of file diff --git a/src/bootstrap/helpers/view/base-view.tsx b/src/bootstrap/helpers/view/base-view.tsx new file mode 100644 index 0000000..a7498cf --- /dev/null +++ b/src/bootstrap/helpers/view/base-view.tsx @@ -0,0 +1,95 @@ +"use client" +/* eslint-disable react/display-name */ +/* eslint-disable @typescript-eslint/no-explicit-any */ +/* eslint-disable react/jsx-props-no-spreading */ +import di from "@/bootstrap/di/init-di"; +import BaseVM from "@/bootstrap/helpers/vm/base-vm"; +import { Component, ReactNode, FC, PropsWithChildren, memo, MemoExoticComponent } from "react"; + +/* -------------------------------------------------------------------------- */ +/* Connector Component */ +/* -------------------------------------------------------------------------- */ +interface IVvmConnector<IVM, PROPS> extends PropsWithChildren { + View: FC<any & { vm: IVM }>; + vmName: string; + restProps?: PROPS; + memoizedByVM?: boolean; +} + +/** + * This function is just will be used in + */ +const VvmConnector = memo( + <IVM, PROPS>(props: IVvmConnector<IVM, PROPS>) => { + const { View, vmName, restProps, children } = props; + const VmInstance = di.resolve(vmName) as new () => BaseVM<IVM>; + if (!VmInstance) throw new Error(`Provided vm as ${vmName} is not exists`) + + const vm = new VmInstance().useVM() + + const allProps = { + restProps, + vm, + }; + + return <View {...allProps}>{children}</View>; + }, + (prevProps) => { + if (prevProps.memoizedByVM) return true; + return false; + }, +); + +/* -------------------------------------------------------------------------- */ +/* BaseView */ +/* -------------------------------------------------------------------------- */ +type IVMParent = Record<string, any>; +type IPropParent = Record<string, any> | undefined; + +type BaseProps<PROPS extends IPropParent = undefined> = { + vmName: string; + restProps?: PROPS; + /** + * By default it's true. + * If you pass true this view will update just by changes of vm not rest props + * + */ + memoizedByVM?: boolean; + children?: ReactNode; +}; + +export type BuildProps< + IVM extends IVMParent, + PROPS extends IPropParent = undefined, +> = { + vm: IVM; + restProps: PROPS; + children?: ReactNode; +}; + +export default abstract class BaseView< + IVM extends IVMParent, + PROPS extends IPropParent = undefined, +> extends Component<BaseProps<PROPS>> { + /* -------------------------------- Abstracts ------------------------------- */ + protected abstract Build(props: BuildProps<IVM, PROPS>): ReactNode; + + /* -------------------------------- Renderer -------------------------------- */ + render(): ReactNode { + const { vmName, restProps, memoizedByVM, children, ...rest } = this.props; + + const Connector = VvmConnector as MemoExoticComponent<((props: IVvmConnector<IVM, PROPS>) => JSX.Element)>; + + return ( + <Connector + View={this.Build} + vmName={vmName} + memoizedByVM={typeof memoizedByVM === "undefined" ? true : memoizedByVM} + restProps={{ ...restProps, ...rest } as PROPS} + > + {children} + </Connector> + ); + } + /* -------------------------------------------------------------------------- */ +} diff --git a/src/bootstrap/helpers/vm/base-vm.ts b/src/bootstrap/helpers/vm/base-vm.ts new file mode 100644 index 0000000..e82a80e --- /dev/null +++ b/src/bootstrap/helpers/vm/base-vm.ts @@ -0,0 +1,46 @@ +"use client" +import { NoOverride } from "@/bootstrap/helpers/type-helper"; +import IBaseVM from "@/bootstrap/helpers/vm/i-base-vm"; +import { useState } from "react"; + +export default abstract class BaseVM< + IVM, + DEP extends object | undefined = undefined, +> implements IBaseVM<IVM> +{ + /* ------------------------------ Dependencies ------------------------------ */ + protected deps!: DEP; + + /* -------------------------------- Abstracts ------------------------------- */ + abstract useVM(): IVM; + + /* -------------------------------------------------------------------------- */ + produce(dep?: DEP) { + if (dep) this.deps = dep; + + return this; + } + + /* --------------------------------- Getters -------------------------------- */ + /** + * You can pass your rerender method after calling useRerender on your vm + * so you can access to it in any method + */ + protected rerender?: () => void; + + /* -------------------------------------------------------------------------- */ + /** + * You can use this hook in your useVm method to get rerender method + * @returns Rerender Method that when ever you call it you can rerender your component + * for showing new values + */ + protected useRerender(): NoOverride<() => void> { + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const [_, reState] = useState(false); + + const rerender = () => reState((prev) => !prev); + return rerender as NoOverride<() => void>; + } + + /* -------------------------------------------------------------------------- */ +} diff --git a/src/bootstrap/helpers/vm/i-base-vm.ts b/src/bootstrap/helpers/vm/i-base-vm.ts new file mode 100644 index 0000000..0e474fa --- /dev/null +++ b/src/bootstrap/helpers/vm/i-base-vm.ts @@ -0,0 +1,3 @@ +export default interface IBaseVM<VM> { + useVM(): VM; +} diff --git a/src/bootstrap/helpers/vm/vm-decorator.ts b/src/bootstrap/helpers/vm/vm-decorator.ts new file mode 100644 index 0000000..2092738 --- /dev/null +++ b/src/bootstrap/helpers/vm/vm-decorator.ts @@ -0,0 +1,9 @@ +"use client" +import di from "@/bootstrap/di/init-di"; +import IBaseVM from "@/bootstrap/helpers/vm/i-base-vm"; + +export default function injectableVm() { + return function (target: new (...args: unknown[]) => IBaseVM<object>) { + di.registerInstance(target.name, target); + }; +} \ No newline at end of file diff --git a/src/components/button/button-vm.ts b/src/components/button/button-vm.ts new file mode 100644 index 0000000..f9e8754 --- /dev/null +++ b/src/components/button/button-vm.ts @@ -0,0 +1,6 @@ +export default interface ButtonVm { + props: { + title: string + } + onClick(): void +} \ No newline at end of file diff --git a/src/components/button/button.tsx b/src/components/button/button.tsx new file mode 100644 index 0000000..6b0452b --- /dev/null +++ b/src/components/button/button.tsx @@ -0,0 +1,10 @@ +import BaseView, { BuildProps } from "@/bootstrap/helpers/view/base-view"; +import ButtonVm from "@/components/button/button-vm"; +import { ReactNode } from "react"; + +export default class Button extends BaseView<ButtonVm> { + protected Build(props: BuildProps<ButtonVm>): ReactNode { + const {vm} = props + return <button onClick={vm.onClick} >{vm.props.title}</button> + } +} \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index c133409..714376b 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -9,6 +9,8 @@ "esModuleInterop": true, "module": "esnext", "moduleResolution": "bundler", + "experimentalDecorators": true, + "emitDecoratorMetadata": true, "resolveJsonModule": true, "isolatedModules": true, "jsx": "preserve", diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 0000000..05b8294 --- /dev/null +++ b/yarn.lock @@ -0,0 +1,2879 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@alloc/quick-lru@^5.2.0": + version "5.2.0" + resolved "https://registry.yarnpkg.com/@alloc/quick-lru/-/quick-lru-5.2.0.tgz#7bf68b20c0a350f936915fcae06f58e32007ce30" + integrity sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw== + +"@emnapi/runtime@^1.2.0": + version "1.3.1" + resolved "https://registry.yarnpkg.com/@emnapi/runtime/-/runtime-1.3.1.tgz#0fcaa575afc31f455fd33534c19381cfce6c6f60" + integrity sha512-kEBmG8KyqtxJZv+ygbEim+KCGtIq1fC22Ms3S4ziXmYKm8uyoLX0MHONVKwp+9opg390VaKRNt4a7A9NwmpNhw== + dependencies: + tslib "^2.4.0" + +"@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0": + version "4.4.1" + resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz#d1145bf2c20132d6400495d6df4bf59362fd9d56" + integrity sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA== + dependencies: + eslint-visitor-keys "^3.4.3" + +"@eslint-community/regexpp@^4.10.0", "@eslint-community/regexpp@^4.6.1": + version "4.12.1" + resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.12.1.tgz#cfc6cffe39df390a3841cde2abccf92eaa7ae0e0" + integrity sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ== + +"@eslint/eslintrc@^2.1.4": + version "2.1.4" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-2.1.4.tgz#388a269f0f25c1b6adc317b5a2c55714894c70ad" + integrity sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ== + dependencies: + ajv "^6.12.4" + debug "^4.3.2" + espree "^9.6.0" + globals "^13.19.0" + ignore "^5.2.0" + import-fresh "^3.2.1" + js-yaml "^4.1.0" + minimatch "^3.1.2" + strip-json-comments "^3.1.1" + +"@eslint/js@8.57.1": + version "8.57.1" + resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.57.1.tgz#de633db3ec2ef6a3c89e2f19038063e8a122e2c2" + integrity sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q== + +"@humanwhocodes/config-array@^0.13.0": + version "0.13.0" + resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.13.0.tgz#fb907624df3256d04b9aa2df50d7aa97ec648748" + integrity sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw== + dependencies: + "@humanwhocodes/object-schema" "^2.0.3" + debug "^4.3.1" + minimatch "^3.0.5" + +"@humanwhocodes/module-importer@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c" + integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA== + +"@humanwhocodes/object-schema@^2.0.3": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz#4a2868d75d6d6963e423bcf90b7fd1be343409d3" + integrity sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA== + +"@img/sharp-darwin-arm64@0.33.5": + version "0.33.5" + resolved "https://registry.yarnpkg.com/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.33.5.tgz#ef5b5a07862805f1e8145a377c8ba6e98813ca08" + integrity sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ== + optionalDependencies: + "@img/sharp-libvips-darwin-arm64" "1.0.4" + +"@img/sharp-darwin-x64@0.33.5": + version "0.33.5" + resolved "https://registry.yarnpkg.com/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.33.5.tgz#e03d3451cd9e664faa72948cc70a403ea4063d61" + integrity sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q== + optionalDependencies: + "@img/sharp-libvips-darwin-x64" "1.0.4" + +"@img/sharp-libvips-darwin-arm64@1.0.4": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.0.4.tgz#447c5026700c01a993c7804eb8af5f6e9868c07f" + integrity sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg== + +"@img/sharp-libvips-darwin-x64@1.0.4": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.0.4.tgz#e0456f8f7c623f9dbfbdc77383caa72281d86062" + integrity sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ== + +"@img/sharp-libvips-linux-arm64@1.0.4": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.0.4.tgz#979b1c66c9a91f7ff2893556ef267f90ebe51704" + integrity sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA== + +"@img/sharp-libvips-linux-arm@1.0.5": + version "1.0.5" + resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.0.5.tgz#99f922d4e15216ec205dcb6891b721bfd2884197" + integrity sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g== + +"@img/sharp-libvips-linux-s390x@1.0.4": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.0.4.tgz#f8a5eb1f374a082f72b3f45e2fb25b8118a8a5ce" + integrity sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA== + +"@img/sharp-libvips-linux-x64@1.0.4": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.0.4.tgz#d4c4619cdd157774906e15770ee119931c7ef5e0" + integrity sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw== + +"@img/sharp-libvips-linuxmusl-arm64@1.0.4": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.0.4.tgz#166778da0f48dd2bded1fa3033cee6b588f0d5d5" + integrity sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA== + +"@img/sharp-libvips-linuxmusl-x64@1.0.4": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.0.4.tgz#93794e4d7720b077fcad3e02982f2f1c246751ff" + integrity sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw== + +"@img/sharp-linux-arm64@0.33.5": + version "0.33.5" + resolved "https://registry.yarnpkg.com/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.33.5.tgz#edb0697e7a8279c9fc829a60fc35644c4839bb22" + integrity sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA== + optionalDependencies: + "@img/sharp-libvips-linux-arm64" "1.0.4" + +"@img/sharp-linux-arm@0.33.5": + version "0.33.5" + resolved "https://registry.yarnpkg.com/@img/sharp-linux-arm/-/sharp-linux-arm-0.33.5.tgz#422c1a352e7b5832842577dc51602bcd5b6f5eff" + integrity sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ== + optionalDependencies: + "@img/sharp-libvips-linux-arm" "1.0.5" + +"@img/sharp-linux-s390x@0.33.5": + version "0.33.5" + resolved "https://registry.yarnpkg.com/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.33.5.tgz#f5c077926b48e97e4a04d004dfaf175972059667" + integrity sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q== + optionalDependencies: + "@img/sharp-libvips-linux-s390x" "1.0.4" + +"@img/sharp-linux-x64@0.33.5": + version "0.33.5" + resolved "https://registry.yarnpkg.com/@img/sharp-linux-x64/-/sharp-linux-x64-0.33.5.tgz#d806e0afd71ae6775cc87f0da8f2d03a7c2209cb" + integrity sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA== + optionalDependencies: + "@img/sharp-libvips-linux-x64" "1.0.4" + +"@img/sharp-linuxmusl-arm64@0.33.5": + version "0.33.5" + resolved "https://registry.yarnpkg.com/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.33.5.tgz#252975b915894fb315af5deea174651e208d3d6b" + integrity sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g== + optionalDependencies: + "@img/sharp-libvips-linuxmusl-arm64" "1.0.4" + +"@img/sharp-linuxmusl-x64@0.33.5": + version "0.33.5" + resolved "https://registry.yarnpkg.com/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.33.5.tgz#3f4609ac5d8ef8ec7dadee80b560961a60fd4f48" + integrity sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw== + optionalDependencies: + "@img/sharp-libvips-linuxmusl-x64" "1.0.4" + +"@img/sharp-wasm32@0.33.5": + version "0.33.5" + resolved "https://registry.yarnpkg.com/@img/sharp-wasm32/-/sharp-wasm32-0.33.5.tgz#6f44f3283069d935bb5ca5813153572f3e6f61a1" + integrity sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg== + dependencies: + "@emnapi/runtime" "^1.2.0" + +"@img/sharp-win32-ia32@0.33.5": + version "0.33.5" + resolved "https://registry.yarnpkg.com/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.33.5.tgz#1a0c839a40c5351e9885628c85f2e5dfd02b52a9" + integrity sha512-T36PblLaTwuVJ/zw/LaH0PdZkRz5rd3SmMHX8GSmR7vtNSP5Z6bQkExdSK7xGWyxLw4sUknBuugTelgw2faBbQ== + +"@img/sharp-win32-x64@0.33.5": + version "0.33.5" + resolved "https://registry.yarnpkg.com/@img/sharp-win32-x64/-/sharp-win32-x64-0.33.5.tgz#56f00962ff0c4e0eb93d34a047d29fa995e3e342" + integrity sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg== + +"@isaacs/cliui@^8.0.2": + version "8.0.2" + resolved "https://registry.yarnpkg.com/@isaacs/cliui/-/cliui-8.0.2.tgz#b37667b7bc181c168782259bab42474fbf52b550" + integrity sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA== + dependencies: + string-width "^5.1.2" + string-width-cjs "npm:string-width@^4.2.0" + strip-ansi "^7.0.1" + strip-ansi-cjs "npm:strip-ansi@^6.0.1" + wrap-ansi "^8.1.0" + wrap-ansi-cjs "npm:wrap-ansi@^7.0.0" + +"@jridgewell/gen-mapping@^0.3.2": + version "0.3.5" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz#dcce6aff74bdf6dad1a95802b69b04a2fcb1fb36" + integrity sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg== + dependencies: + "@jridgewell/set-array" "^1.2.1" + "@jridgewell/sourcemap-codec" "^1.4.10" + "@jridgewell/trace-mapping" "^0.3.24" + +"@jridgewell/resolve-uri@^3.1.0": + version "3.1.2" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6" + integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw== + +"@jridgewell/set-array@^1.2.1": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.2.1.tgz#558fb6472ed16a4c850b889530e6b36438c49280" + integrity sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A== + +"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz#3188bcb273a414b0d215fd22a58540b989b9409a" + integrity sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ== + +"@jridgewell/trace-mapping@^0.3.24": + version "0.3.25" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz#15f190e98895f3fc23276ee14bc76b675c2e50f0" + integrity sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ== + dependencies: + "@jridgewell/resolve-uri" "^3.1.0" + "@jridgewell/sourcemap-codec" "^1.4.14" + +"@next/env@15.0.1": + version "15.0.1" + resolved "https://registry.yarnpkg.com/@next/env/-/env-15.0.1.tgz#660fe9303e255cec112d3f4198d2897a24bc60b3" + integrity sha512-lc4HeDUKO9gxxlM5G2knTRifqhsY6yYpwuHspBZdboZe0Gp+rZHBNNSIjmQKDJIdRXiXGyVnSD6gafrbQPvILQ== + +"@next/eslint-plugin-next@15.0.1": + version "15.0.1" + resolved "https://registry.yarnpkg.com/@next/eslint-plugin-next/-/eslint-plugin-next-15.0.1.tgz#76117d88aadc52f6e04b1892d44654d05468d53c" + integrity sha512-bKWsMaGPbiFAaGqrDJvbE8b4Z0uKicGVcgOI77YM2ui3UfjHMr4emFPrZTLeZVchi7fT1mooG2LxREfUUClIKw== + dependencies: + fast-glob "3.3.1" + +"@next/swc-darwin-arm64@15.0.1": + version "15.0.1" + resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-15.0.1.tgz#b80a25f1569bd0ca03eca9473f7e93e64937e404" + integrity sha512-C9k/Xv4sxkQRTA37Z6MzNq3Yb1BJMmSqjmwowoWEpbXTkAdfOwnoKOpAb71ItSzoA26yUTIo6ZhN8rKGu4ExQw== + +"@next/swc-darwin-x64@15.0.1": + version "15.0.1" + resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-15.0.1.tgz#00dcf79ec7c638a85c3b9ff2e2de2bfb09c1c250" + integrity sha512-uHl13HXOuq1G7ovWFxCACDJHTSDVbn/sbLv8V1p+7KIvTrYQ5HNoSmKBdYeEKRRCbEmd+OohOgg9YOp8Ux3MBg== + +"@next/swc-linux-arm64-gnu@15.0.1": + version "15.0.1" + resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-15.0.1.tgz#faab5f7ffcc6d1a15e8dea1cb9953966658b39bf" + integrity sha512-LvyhvxHOihFTEIbb35KxOc3q8w8G4xAAAH/AQnsYDEnOvwawjL2eawsB59AX02ki6LJdgDaHoTEnC54Gw+82xw== + +"@next/swc-linux-arm64-musl@15.0.1": + version "15.0.1" + resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-15.0.1.tgz#97abada9a782ab5b3cb42cf0d4799cbc2e733351" + integrity sha512-vFmCGUFNyk/A5/BYcQNhAQqPIw01RJaK6dRO+ZEhz0DncoW+hJW1kZ8aH2UvTX27zPq3m85zN5waMSbZEmANcQ== + +"@next/swc-linux-x64-gnu@15.0.1": + version "15.0.1" + resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-15.0.1.tgz#548bd47c49fe6d819302139aff8766eb704322e2" + integrity sha512-5by7IYq0NCF8rouz6Qg9T97jYU68kaClHPfGpQG2lCZpSYHtSPQF1kjnqBTd34RIqPKMbCa4DqCufirgr8HM5w== + +"@next/swc-linux-x64-musl@15.0.1": + version "15.0.1" + resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-15.0.1.tgz#84423fbd3a058dd6ae8322e530878f0ec7a1027a" + integrity sha512-lmYr6H3JyDNBJLzklGXLfbehU3ay78a+b6UmBGlHls4xhDXBNZfgb0aI67sflrX+cGBnv1LgmWzFlYrAYxS1Qw== + +"@next/swc-win32-arm64-msvc@15.0.1": + version "15.0.1" + resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-15.0.1.tgz#723c2ced12a998fb40dc901b8faea9170e788c2f" + integrity sha512-DS8wQtl6diAj0eZTdH0sefykm4iXMbHT4MOvLwqZiIkeezKpkgPFcEdFlz3vKvXa2R/2UEgMh48z1nEpNhjeOQ== + +"@next/swc-win32-x64-msvc@15.0.1": + version "15.0.1" + resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.0.1.tgz#ec7e3befc0bcc47527537b1eda2b3745beb15a09" + integrity sha512-4Ho2ggvDdMKlZ/0e9HNdZ9ngeaBwtc+2VS5oCeqrbXqOgutX6I4U2X/42VBw0o+M5evn4/7v3zKgGHo+9v/VjA== + +"@nodelib/fs.scandir@2.1.5": + version "2.1.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" + integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== + dependencies: + "@nodelib/fs.stat" "2.0.5" + run-parallel "^1.1.9" + +"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" + integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== + +"@nodelib/fs.walk@^1.2.3", "@nodelib/fs.walk@^1.2.8": + version "1.2.8" + resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" + integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== + dependencies: + "@nodelib/fs.scandir" "2.1.5" + fastq "^1.6.0" + +"@nolyfill/is-core-module@1.0.39": + version "1.0.39" + resolved "https://registry.yarnpkg.com/@nolyfill/is-core-module/-/is-core-module-1.0.39.tgz#3dc35ba0f1e66b403c00b39344f870298ebb1c8e" + integrity sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA== + +"@pkgjs/parseargs@^0.11.0": + version "0.11.0" + resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33" + integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg== + +"@rtsao/scc@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@rtsao/scc/-/scc-1.1.0.tgz#927dd2fae9bc3361403ac2c7a00c32ddce9ad7e8" + integrity sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g== + +"@rushstack/eslint-patch@^1.10.3": + version "1.10.4" + resolved "https://registry.yarnpkg.com/@rushstack/eslint-patch/-/eslint-patch-1.10.4.tgz#427d5549943a9c6fce808e39ea64dbe60d4047f1" + integrity sha512-WJgX9nzTqknM393q1QJDJmoW28kUfEnybeTfVNcNAPnIx210RXm2DiXiHzfNPJNIUUb1tJnz/l4QGtJ30PgWmA== + +"@swc/counter@0.1.3": + version "0.1.3" + resolved "https://registry.yarnpkg.com/@swc/counter/-/counter-0.1.3.tgz#cc7463bd02949611c6329596fccd2b0ec782b0e9" + integrity sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ== + +"@swc/helpers@0.5.13": + version "0.5.13" + resolved "https://registry.yarnpkg.com/@swc/helpers/-/helpers-0.5.13.tgz#33e63ff3cd0cade557672bd7888a39ce7d115a8c" + integrity sha512-UoKGxQ3r5kYI9dALKJapMmuK+1zWM/H17Z1+iwnNmzcJRnfFuevZs375TA5rW31pu4BS4NoSy1fRsexDXfWn5w== + dependencies: + tslib "^2.4.0" + +"@types/json5@^0.0.29": + version "0.0.29" + resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" + integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ== + +"@types/node@^20": + version "20.17.2" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.17.2.tgz#3ca40ef7d776c85a1db3df23cbb5bfb3c384a92e" + integrity sha512-OOHK4sjXqkL7yQ7VEEHcf6+0jSvKjWqwnaCtY7AKD/VLEvRHMsxxu7eI8ErnjxHS8VwmekD4PeVCpu4qZEZSxg== + dependencies: + undici-types "~6.19.2" + +"@types/prop-types@*": + version "15.7.13" + resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.13.tgz#2af91918ee12d9d32914feb13f5326658461b451" + integrity sha512-hCZTSvwbzWGvhqxp/RqVqwU999pBf2vp7hzIjiYOsl8wqOmUxkQ6ddw1cV3l8811+kdUFus/q4d1Y3E3SyEifA== + +"@types/react-dom@^18": + version "18.3.1" + resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.3.1.tgz#1e4654c08a9cdcfb6594c780ac59b55aad42fe07" + integrity sha512-qW1Mfv8taImTthu4KoXgDfLuk4bydU6Q/TkADnDWWHwi4NX4BR+LWfTp2sVmTqRrsHvyDDTelgelxJ+SsejKKQ== + dependencies: + "@types/react" "*" + +"@types/react@*", "@types/react@^18": + version "18.3.12" + resolved "https://registry.yarnpkg.com/@types/react/-/react-18.3.12.tgz#99419f182ccd69151813b7ee24b792fe08774f60" + integrity sha512-D2wOSq/d6Agt28q7rSI3jhU7G6aiuzljDGZ2hTZHIkrTLUI+AF3WMeKkEZ9nN2fkBAlcktT6vcZjDFiIhMYEQw== + dependencies: + "@types/prop-types" "*" + csstype "^3.0.2" + +"@typescript-eslint/eslint-plugin@^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0": + version "8.12.2" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.12.2.tgz#c2ef660bb83fd1432368319312a2581fc92ccac1" + integrity sha512-gQxbxM8mcxBwaEmWdtLCIGLfixBMHhQjBqR8sVWNTPpcj45WlYL2IObS/DNMLH1DBP0n8qz+aiiLTGfopPEebw== + dependencies: + "@eslint-community/regexpp" "^4.10.0" + "@typescript-eslint/scope-manager" "8.12.2" + "@typescript-eslint/type-utils" "8.12.2" + "@typescript-eslint/utils" "8.12.2" + "@typescript-eslint/visitor-keys" "8.12.2" + graphemer "^1.4.0" + ignore "^5.3.1" + natural-compare "^1.4.0" + ts-api-utils "^1.3.0" + +"@typescript-eslint/parser@^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0": + version "8.12.2" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-8.12.2.tgz#2e8173b34e1685e918b2d571c16c906d3747bad2" + integrity sha512-MrvlXNfGPLH3Z+r7Tk+Z5moZAc0dzdVjTgUgwsdGweH7lydysQsnSww3nAmsq8blFuRD5VRlAr9YdEFw3e6PBw== + dependencies: + "@typescript-eslint/scope-manager" "8.12.2" + "@typescript-eslint/types" "8.12.2" + "@typescript-eslint/typescript-estree" "8.12.2" + "@typescript-eslint/visitor-keys" "8.12.2" + debug "^4.3.4" + +"@typescript-eslint/scope-manager@8.12.2": + version "8.12.2" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-8.12.2.tgz#6db0213745e6392c8e90fe9af5915e6da32eb94a" + integrity sha512-gPLpLtrj9aMHOvxJkSbDBmbRuYdtiEbnvO25bCMza3DhMjTQw0u7Y1M+YR5JPbMsXXnSPuCf5hfq0nEkQDL/JQ== + dependencies: + "@typescript-eslint/types" "8.12.2" + "@typescript-eslint/visitor-keys" "8.12.2" + +"@typescript-eslint/type-utils@8.12.2": + version "8.12.2" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-8.12.2.tgz#132b0c52d45f6814e6f2e32416c7951ed480b016" + integrity sha512-bwuU4TAogPI+1q/IJSKuD4shBLc/d2vGcRT588q+jzayQyjVK2X6v/fbR4InY2U2sgf8MEvVCqEWUzYzgBNcGQ== + dependencies: + "@typescript-eslint/typescript-estree" "8.12.2" + "@typescript-eslint/utils" "8.12.2" + debug "^4.3.4" + ts-api-utils "^1.3.0" + +"@typescript-eslint/types@8.12.2": + version "8.12.2" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.12.2.tgz#8d70098c0e90442495b53d0296acdca6d0f3f73c" + integrity sha512-VwDwMF1SZ7wPBUZwmMdnDJ6sIFk4K4s+ALKLP6aIQsISkPv8jhiw65sAK6SuWODN/ix+m+HgbYDkH+zLjrzvOA== + +"@typescript-eslint/typescript-estree@8.12.2": + version "8.12.2" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.12.2.tgz#206df9b1cbff212aaa9401985ef99f04daa84da5" + integrity sha512-mME5MDwGe30Pq9zKPvyduyU86PH7aixwqYR2grTglAdB+AN8xXQ1vFGpYaUSJ5o5P/5znsSBeNcs5g5/2aQwow== + dependencies: + "@typescript-eslint/types" "8.12.2" + "@typescript-eslint/visitor-keys" "8.12.2" + debug "^4.3.4" + fast-glob "^3.3.2" + is-glob "^4.0.3" + minimatch "^9.0.4" + semver "^7.6.0" + ts-api-utils "^1.3.0" + +"@typescript-eslint/utils@8.12.2": + version "8.12.2" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-8.12.2.tgz#726cc9f49f5866605bd15bbc1768ffc15637930e" + integrity sha512-UTTuDIX3fkfAz6iSVa5rTuSfWIYZ6ATtEocQ/umkRSyC9O919lbZ8dcH7mysshrCdrAM03skJOEYaBugxN+M6A== + dependencies: + "@eslint-community/eslint-utils" "^4.4.0" + "@typescript-eslint/scope-manager" "8.12.2" + "@typescript-eslint/types" "8.12.2" + "@typescript-eslint/typescript-estree" "8.12.2" + +"@typescript-eslint/visitor-keys@8.12.2": + version "8.12.2" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.12.2.tgz#94d7410f78eb6d134b9fcabaf1eeedb910ba8c38" + integrity sha512-PChz8UaKQAVNHghsHcPyx1OMHoFRUEA7rJSK/mDhdq85bk+PLsUHUBqTQTFt18VJZbmxBovM65fezlheQRsSDA== + dependencies: + "@typescript-eslint/types" "8.12.2" + eslint-visitor-keys "^3.4.3" + +"@ungap/structured-clone@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.2.0.tgz#756641adb587851b5ccb3e095daf27ae581c8406" + integrity sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ== + +acorn-jsx@^5.3.2: + version "5.3.2" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" + integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== + +acorn@^8.9.0: + version "8.14.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.14.0.tgz#063e2c70cac5fb4f6467f0b11152e04c682795b0" + integrity sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA== + +ajv@^6.12.4: + version "6.12.6" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" + integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== + dependencies: + fast-deep-equal "^3.1.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + +ansi-regex@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" + integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== + +ansi-regex@^6.0.1: + version "6.1.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.1.0.tgz#95ec409c69619d6cb1b8b34f14b660ef28ebd654" + integrity sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA== + +ansi-styles@^4.0.0, ansi-styles@^4.1.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" + +ansi-styles@^6.1.0: + version "6.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5" + integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug== + +any-promise@^1.0.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f" + integrity sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A== + +anymatch@~3.1.2: + version "3.1.3" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" + integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + +arg@^5.0.2: + version "5.0.2" + resolved "https://registry.yarnpkg.com/arg/-/arg-5.0.2.tgz#c81433cc427c92c4dcf4865142dbca6f15acd59c" + integrity sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg== + +argparse@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" + integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== + +aria-query@^5.3.2: + version "5.3.2" + resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-5.3.2.tgz#93f81a43480e33a338f19163a3d10a50c01dcd59" + integrity sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw== + +array-buffer-byte-length@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz#1e5583ec16763540a27ae52eed99ff899223568f" + integrity sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg== + dependencies: + call-bind "^1.0.5" + is-array-buffer "^3.0.4" + +array-includes@^3.1.6, array-includes@^3.1.8: + version "3.1.8" + resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.8.tgz#5e370cbe172fdd5dd6530c1d4aadda25281ba97d" + integrity sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + es-abstract "^1.23.2" + es-object-atoms "^1.0.0" + get-intrinsic "^1.2.4" + is-string "^1.0.7" + +array.prototype.findlast@^1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz#3e4fbcb30a15a7f5bf64cf2faae22d139c2e4904" + integrity sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + es-abstract "^1.23.2" + es-errors "^1.3.0" + es-object-atoms "^1.0.0" + es-shim-unscopables "^1.0.2" + +array.prototype.findlastindex@^1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz#8c35a755c72908719453f87145ca011e39334d0d" + integrity sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + es-abstract "^1.23.2" + es-errors "^1.3.0" + es-object-atoms "^1.0.0" + es-shim-unscopables "^1.0.2" + +array.prototype.flat@^1.3.1, array.prototype.flat@^1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz#1476217df8cff17d72ee8f3ba06738db5b387d18" + integrity sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + es-shim-unscopables "^1.0.0" + +array.prototype.flatmap@^1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz#c9a7c6831db8e719d6ce639190146c24bbd3e527" + integrity sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + es-shim-unscopables "^1.0.0" + +array.prototype.tosorted@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz#fe954678ff53034e717ea3352a03f0b0b86f7ffc" + integrity sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + es-abstract "^1.23.3" + es-errors "^1.3.0" + es-shim-unscopables "^1.0.2" + +arraybuffer.prototype.slice@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz#097972f4255e41bc3425e37dc3f6421cf9aefde6" + integrity sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A== + dependencies: + array-buffer-byte-length "^1.0.1" + call-bind "^1.0.5" + define-properties "^1.2.1" + es-abstract "^1.22.3" + es-errors "^1.2.1" + get-intrinsic "^1.2.3" + is-array-buffer "^3.0.4" + is-shared-array-buffer "^1.0.2" + +ast-types-flow@^0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/ast-types-flow/-/ast-types-flow-0.0.8.tgz#0a85e1c92695769ac13a428bb653e7538bea27d6" + integrity sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ== + +available-typed-arrays@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz#a5cc375d6a03c2efc87a553f3e0b1522def14846" + integrity sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ== + dependencies: + possible-typed-array-names "^1.0.0" + +axe-core@^4.10.0: + version "4.10.2" + resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.10.2.tgz#85228e3e1d8b8532a27659b332e39b7fa0e022df" + integrity sha512-RE3mdQ7P3FRSe7eqCWoeQ/Z9QXrtniSjp1wUjt5nRC3WIpz5rSCve6o3fsZ2aCpJtrZjSZgjwXAoTO5k4tEI0w== + +axobject-query@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-4.1.0.tgz#28768c76d0e3cff21bc62a9e2d0b6ac30042a1ee" + integrity sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ== + +balanced-match@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== + +binary-extensions@^2.0.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.3.0.tgz#f6e14a97858d327252200242d4ccfe522c445522" + integrity sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw== + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +brace-expansion@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" + integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== + dependencies: + balanced-match "^1.0.0" + +braces@^3.0.3, braces@~3.0.2: + version "3.0.3" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789" + integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== + dependencies: + fill-range "^7.1.1" + +busboy@1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/busboy/-/busboy-1.6.0.tgz#966ea36a9502e43cdb9146962523b92f531f6893" + integrity sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA== + dependencies: + streamsearch "^1.1.0" + +call-bind@^1.0.2, call-bind@^1.0.5, call-bind@^1.0.6, call-bind@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.7.tgz#06016599c40c56498c18769d2730be242b6fa3b9" + integrity sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w== + dependencies: + es-define-property "^1.0.0" + es-errors "^1.3.0" + function-bind "^1.1.2" + get-intrinsic "^1.2.4" + set-function-length "^1.2.1" + +callsites@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" + integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== + +camelcase-css@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/camelcase-css/-/camelcase-css-2.0.1.tgz#ee978f6947914cc30c6b44741b6ed1df7f043fd5" + integrity sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA== + +caniuse-lite@^1.0.30001579: + version "1.0.30001674" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001674.tgz#eb200a716c3e796d33d30b9c8890517a72f862c8" + integrity sha512-jOsKlZVRnzfhLojb+Ykb+gyUSp9Xb57So+fAiFlLzzTKpqg8xxSav0e40c8/4F/v9N8QSvrRRaLeVzQbLqomYw== + +chalk@^4.0.0: + version "4.1.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +chokidar@^3.5.3: + version "3.6.0" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b" + integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw== + dependencies: + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" + optionalDependencies: + fsevents "~2.3.2" + +client-only@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/client-only/-/client-only-0.0.1.tgz#38bba5d403c41ab150bff64a95c85013cf73bca1" + integrity sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA== + +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + +color-name@^1.0.0, color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +color-string@^1.9.0: + version "1.9.1" + resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.9.1.tgz#4467f9146f036f855b764dfb5bf8582bf342c7a4" + integrity sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg== + dependencies: + color-name "^1.0.0" + simple-swizzle "^0.2.2" + +color@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/color/-/color-4.2.3.tgz#d781ecb5e57224ee43ea9627560107c0e0c6463a" + integrity sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A== + dependencies: + color-convert "^2.0.1" + color-string "^1.9.0" + +commander@^4.0.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-4.1.1.tgz#9fd602bd936294e9e9ef46a3f4d6964044b18068" + integrity sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA== + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== + +cross-spawn@^7.0.0, cross-spawn@^7.0.2: + version "7.0.3" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" + integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + +cssesc@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" + integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg== + +csstype@^3.0.2: + version "3.1.3" + resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.3.tgz#d80ff294d114fb0e6ac500fbf85b60137d7eff81" + integrity sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw== + +damerau-levenshtein@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz#b43d286ccbd36bc5b2f7ed41caf2d0aba1f8a6e7" + integrity sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA== + +data-view-buffer@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/data-view-buffer/-/data-view-buffer-1.0.1.tgz#8ea6326efec17a2e42620696e671d7d5a8bc66b2" + integrity sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA== + dependencies: + call-bind "^1.0.6" + es-errors "^1.3.0" + is-data-view "^1.0.1" + +data-view-byte-length@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz#90721ca95ff280677eb793749fce1011347669e2" + integrity sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ== + dependencies: + call-bind "^1.0.7" + es-errors "^1.3.0" + is-data-view "^1.0.1" + +data-view-byte-offset@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz#5e0bbfb4828ed2d1b9b400cd8a7d119bca0ff18a" + integrity sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA== + dependencies: + call-bind "^1.0.6" + es-errors "^1.3.0" + is-data-view "^1.0.1" + +debug@^3.2.7: + version "3.2.7" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" + integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== + dependencies: + ms "^2.1.1" + +debug@^4.3.1, debug@^4.3.2, debug@^4.3.4, debug@^4.3.5: + version "4.3.7" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.7.tgz#87945b4151a011d76d95a198d7111c865c360a52" + integrity sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ== + dependencies: + ms "^2.1.3" + +deep-is@^0.1.3: + version "0.1.4" + resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" + integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== + +define-data-property@^1.0.1, define-data-property@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.4.tgz#894dc141bb7d3060ae4366f6a0107e68fbe48c5e" + integrity sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A== + dependencies: + es-define-property "^1.0.0" + es-errors "^1.3.0" + gopd "^1.0.1" + +define-properties@^1.1.3, define-properties@^1.2.0, define-properties@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.1.tgz#10781cc616eb951a80a034bafcaa7377f6af2b6c" + integrity sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg== + dependencies: + define-data-property "^1.0.1" + has-property-descriptors "^1.0.0" + object-keys "^1.1.1" + +detect-libc@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-2.0.3.tgz#f0cd503b40f9939b894697d19ad50895e30cf700" + integrity sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw== + +didyoumean@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/didyoumean/-/didyoumean-1.2.2.tgz#989346ffe9e839b4555ecf5666edea0d3e8ad037" + integrity sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw== + +dlv@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/dlv/-/dlv-1.1.3.tgz#5c198a8a11453596e751494d49874bc7732f2e79" + integrity sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA== + +doctrine@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" + integrity sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw== + dependencies: + esutils "^2.0.2" + +doctrine@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" + integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== + dependencies: + esutils "^2.0.2" + +eastasianwidth@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" + integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA== + +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + +emoji-regex@^9.2.2: + version "9.2.2" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" + integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== + +enhanced-resolve@^5.15.0: + version "5.17.1" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz#67bfbbcc2f81d511be77d686a90267ef7f898a15" + integrity sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg== + dependencies: + graceful-fs "^4.2.4" + tapable "^2.2.0" + +es-abstract@^1.17.5, es-abstract@^1.22.1, es-abstract@^1.22.3, es-abstract@^1.23.0, es-abstract@^1.23.1, es-abstract@^1.23.2, es-abstract@^1.23.3: + version "1.23.3" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.23.3.tgz#8f0c5a35cd215312573c5a27c87dfd6c881a0aa0" + integrity sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A== + dependencies: + array-buffer-byte-length "^1.0.1" + arraybuffer.prototype.slice "^1.0.3" + available-typed-arrays "^1.0.7" + call-bind "^1.0.7" + data-view-buffer "^1.0.1" + data-view-byte-length "^1.0.1" + data-view-byte-offset "^1.0.0" + es-define-property "^1.0.0" + es-errors "^1.3.0" + es-object-atoms "^1.0.0" + es-set-tostringtag "^2.0.3" + es-to-primitive "^1.2.1" + function.prototype.name "^1.1.6" + get-intrinsic "^1.2.4" + get-symbol-description "^1.0.2" + globalthis "^1.0.3" + gopd "^1.0.1" + has-property-descriptors "^1.0.2" + has-proto "^1.0.3" + has-symbols "^1.0.3" + hasown "^2.0.2" + internal-slot "^1.0.7" + is-array-buffer "^3.0.4" + is-callable "^1.2.7" + is-data-view "^1.0.1" + is-negative-zero "^2.0.3" + is-regex "^1.1.4" + is-shared-array-buffer "^1.0.3" + is-string "^1.0.7" + is-typed-array "^1.1.13" + is-weakref "^1.0.2" + object-inspect "^1.13.1" + object-keys "^1.1.1" + object.assign "^4.1.5" + regexp.prototype.flags "^1.5.2" + safe-array-concat "^1.1.2" + safe-regex-test "^1.0.3" + string.prototype.trim "^1.2.9" + string.prototype.trimend "^1.0.8" + string.prototype.trimstart "^1.0.8" + typed-array-buffer "^1.0.2" + typed-array-byte-length "^1.0.1" + typed-array-byte-offset "^1.0.2" + typed-array-length "^1.0.6" + unbox-primitive "^1.0.2" + which-typed-array "^1.1.15" + +es-define-property@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.0.tgz#c7faefbdff8b2696cf5f46921edfb77cc4ba3845" + integrity sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ== + dependencies: + get-intrinsic "^1.2.4" + +es-errors@^1.2.1, es-errors@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f" + integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== + +es-iterator-helpers@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/es-iterator-helpers/-/es-iterator-helpers-1.1.0.tgz#f6d745d342aea214fe09497e7152170dc333a7a6" + integrity sha512-/SurEfycdyssORP/E+bj4sEu1CWw4EmLDsHynHwSXQ7utgbrMRWW195pTrCjFgFCddf/UkYm3oqKPRq5i8bJbw== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + es-abstract "^1.23.3" + es-errors "^1.3.0" + es-set-tostringtag "^2.0.3" + function-bind "^1.1.2" + get-intrinsic "^1.2.4" + globalthis "^1.0.4" + has-property-descriptors "^1.0.2" + has-proto "^1.0.3" + has-symbols "^1.0.3" + internal-slot "^1.0.7" + iterator.prototype "^1.1.3" + safe-array-concat "^1.1.2" + +es-object-atoms@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/es-object-atoms/-/es-object-atoms-1.0.0.tgz#ddb55cd47ac2e240701260bc2a8e31ecb643d941" + integrity sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw== + dependencies: + es-errors "^1.3.0" + +es-set-tostringtag@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz#8bb60f0a440c2e4281962428438d58545af39777" + integrity sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ== + dependencies: + get-intrinsic "^1.2.4" + has-tostringtag "^1.0.2" + hasown "^2.0.1" + +es-shim-unscopables@^1.0.0, es-shim-unscopables@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz#1f6942e71ecc7835ed1c8a83006d8771a63a3763" + integrity sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw== + dependencies: + hasown "^2.0.0" + +es-to-primitive@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" + integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA== + dependencies: + is-callable "^1.1.4" + is-date-object "^1.0.1" + is-symbol "^1.0.2" + +escape-string-regexp@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" + integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== + +eslint-config-next@15.0.1: + version "15.0.1" + resolved "https://registry.yarnpkg.com/eslint-config-next/-/eslint-config-next-15.0.1.tgz#5f49a01d312420cdbf1e87299396ef779ae99004" + integrity sha512-3cYCrgbH6GS/ufApza7XCKz92vtq4dAdYhx++rMFNlH2cAV+/GsAKkrr4+bohYOACmzG2nAOR+uWprKC1Uld6A== + dependencies: + "@next/eslint-plugin-next" "15.0.1" + "@rushstack/eslint-patch" "^1.10.3" + "@typescript-eslint/eslint-plugin" "^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0" + "@typescript-eslint/parser" "^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0" + eslint-import-resolver-node "^0.3.6" + eslint-import-resolver-typescript "^3.5.2" + eslint-plugin-import "^2.31.0" + eslint-plugin-jsx-a11y "^6.10.0" + eslint-plugin-react "^7.35.0" + eslint-plugin-react-hooks "^5.0.0" + +eslint-import-resolver-node@^0.3.6, eslint-import-resolver-node@^0.3.9: + version "0.3.9" + resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz#d4eaac52b8a2e7c3cd1903eb00f7e053356118ac" + integrity sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g== + dependencies: + debug "^3.2.7" + is-core-module "^2.13.0" + resolve "^1.22.4" + +eslint-import-resolver-typescript@^3.5.2: + version "3.6.3" + resolved "https://registry.yarnpkg.com/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.6.3.tgz#bb8e388f6afc0f940ce5d2c5fd4a3d147f038d9e" + integrity sha512-ud9aw4szY9cCT1EWWdGv1L1XR6hh2PaRWif0j2QjQ0pgTY/69iw+W0Z4qZv5wHahOl8isEr+k/JnyAqNQkLkIA== + dependencies: + "@nolyfill/is-core-module" "1.0.39" + debug "^4.3.5" + enhanced-resolve "^5.15.0" + eslint-module-utils "^2.8.1" + fast-glob "^3.3.2" + get-tsconfig "^4.7.5" + is-bun-module "^1.0.2" + is-glob "^4.0.3" + +eslint-module-utils@^2.12.0, eslint-module-utils@^2.8.1: + version "2.12.0" + resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.12.0.tgz#fe4cfb948d61f49203d7b08871982b65b9af0b0b" + integrity sha512-wALZ0HFoytlyh/1+4wuZ9FJCD/leWHQzzrxJ8+rebyReSLk7LApMyd3WJaLVoN+D5+WIdJyDK1c6JnE65V4Zyg== + dependencies: + debug "^3.2.7" + +eslint-plugin-import@^2.31.0: + version "2.31.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.31.0.tgz#310ce7e720ca1d9c0bb3f69adfd1c6bdd7d9e0e7" + integrity sha512-ixmkI62Rbc2/w8Vfxyh1jQRTdRTF52VxwRVHl/ykPAmqG+Nb7/kNn+byLP0LxPgI7zWA16Jt82SybJInmMia3A== + dependencies: + "@rtsao/scc" "^1.1.0" + array-includes "^3.1.8" + array.prototype.findlastindex "^1.2.5" + array.prototype.flat "^1.3.2" + array.prototype.flatmap "^1.3.2" + debug "^3.2.7" + doctrine "^2.1.0" + eslint-import-resolver-node "^0.3.9" + eslint-module-utils "^2.12.0" + hasown "^2.0.2" + is-core-module "^2.15.1" + is-glob "^4.0.3" + minimatch "^3.1.2" + object.fromentries "^2.0.8" + object.groupby "^1.0.3" + object.values "^1.2.0" + semver "^6.3.1" + string.prototype.trimend "^1.0.8" + tsconfig-paths "^3.15.0" + +eslint-plugin-jsx-a11y@^6.10.0: + version "6.10.2" + resolved "https://registry.yarnpkg.com/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.10.2.tgz#d2812bb23bf1ab4665f1718ea442e8372e638483" + integrity sha512-scB3nz4WmG75pV8+3eRUQOHZlNSUhFNq37xnpgRkCCELU3XMvXAxLk1eqWWyE22Ki4Q01Fnsw9BA3cJHDPgn2Q== + dependencies: + aria-query "^5.3.2" + array-includes "^3.1.8" + array.prototype.flatmap "^1.3.2" + ast-types-flow "^0.0.8" + axe-core "^4.10.0" + axobject-query "^4.1.0" + damerau-levenshtein "^1.0.8" + emoji-regex "^9.2.2" + hasown "^2.0.2" + jsx-ast-utils "^3.3.5" + language-tags "^1.0.9" + minimatch "^3.1.2" + object.fromentries "^2.0.8" + safe-regex-test "^1.0.3" + string.prototype.includes "^2.0.1" + +eslint-plugin-react-hooks@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.0.0.tgz#72e2eefbac4b694f5324154619fee44f5f60f101" + integrity sha512-hIOwI+5hYGpJEc4uPRmz2ulCjAGD/N13Lukkh8cLV0i2IRk/bdZDYjgLVHj+U9Z704kLIdIO6iueGvxNur0sgw== + +eslint-plugin-react@^7.35.0: + version "7.37.2" + resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.37.2.tgz#cd0935987876ba2900df2f58339f6d92305acc7a" + integrity sha512-EsTAnj9fLVr/GZleBLFbj/sSuXeWmp1eXIN60ceYnZveqEaUCyW4X+Vh4WTdUhCkW4xutXYqTXCUSyqD4rB75w== + dependencies: + array-includes "^3.1.8" + array.prototype.findlast "^1.2.5" + array.prototype.flatmap "^1.3.2" + array.prototype.tosorted "^1.1.4" + doctrine "^2.1.0" + es-iterator-helpers "^1.1.0" + estraverse "^5.3.0" + hasown "^2.0.2" + jsx-ast-utils "^2.4.1 || ^3.0.0" + minimatch "^3.1.2" + object.entries "^1.1.8" + object.fromentries "^2.0.8" + object.values "^1.2.0" + prop-types "^15.8.1" + resolve "^2.0.0-next.5" + semver "^6.3.1" + string.prototype.matchall "^4.0.11" + string.prototype.repeat "^1.0.0" + +eslint-scope@^7.2.2: + version "7.2.2" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.2.2.tgz#deb4f92563390f32006894af62a22dba1c46423f" + integrity sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg== + dependencies: + esrecurse "^4.3.0" + estraverse "^5.2.0" + +eslint-visitor-keys@^3.4.1, eslint-visitor-keys@^3.4.3: + version "3.4.3" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" + integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== + +eslint@^8: + version "8.57.1" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.57.1.tgz#7df109654aba7e3bbe5c8eae533c5e461d3c6ca9" + integrity sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA== + dependencies: + "@eslint-community/eslint-utils" "^4.2.0" + "@eslint-community/regexpp" "^4.6.1" + "@eslint/eslintrc" "^2.1.4" + "@eslint/js" "8.57.1" + "@humanwhocodes/config-array" "^0.13.0" + "@humanwhocodes/module-importer" "^1.0.1" + "@nodelib/fs.walk" "^1.2.8" + "@ungap/structured-clone" "^1.2.0" + ajv "^6.12.4" + chalk "^4.0.0" + cross-spawn "^7.0.2" + debug "^4.3.2" + doctrine "^3.0.0" + escape-string-regexp "^4.0.0" + eslint-scope "^7.2.2" + eslint-visitor-keys "^3.4.3" + espree "^9.6.1" + esquery "^1.4.2" + esutils "^2.0.2" + fast-deep-equal "^3.1.3" + file-entry-cache "^6.0.1" + find-up "^5.0.0" + glob-parent "^6.0.2" + globals "^13.19.0" + graphemer "^1.4.0" + ignore "^5.2.0" + imurmurhash "^0.1.4" + is-glob "^4.0.0" + is-path-inside "^3.0.3" + js-yaml "^4.1.0" + json-stable-stringify-without-jsonify "^1.0.1" + levn "^0.4.1" + lodash.merge "^4.6.2" + minimatch "^3.1.2" + natural-compare "^1.4.0" + optionator "^0.9.3" + strip-ansi "^6.0.1" + text-table "^0.2.0" + +espree@^9.6.0, espree@^9.6.1: + version "9.6.1" + resolved "https://registry.yarnpkg.com/espree/-/espree-9.6.1.tgz#a2a17b8e434690a5432f2f8018ce71d331a48c6f" + integrity sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ== + dependencies: + acorn "^8.9.0" + acorn-jsx "^5.3.2" + eslint-visitor-keys "^3.4.1" + +esquery@^1.4.2: + version "1.6.0" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.6.0.tgz#91419234f804d852a82dceec3e16cdc22cf9dae7" + integrity sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg== + dependencies: + estraverse "^5.1.0" + +esrecurse@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" + integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== + dependencies: + estraverse "^5.2.0" + +estraverse@^5.1.0, estraverse@^5.2.0, estraverse@^5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" + integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== + +esutils@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" + integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== + +fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== + +fast-glob@3.3.1: + version "3.3.1" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.1.tgz#784b4e897340f3dbbef17413b3f11acf03c874c4" + integrity sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.2" + merge2 "^1.3.0" + micromatch "^4.0.4" + +fast-glob@^3.3.0, fast-glob@^3.3.2: + version "3.3.2" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.2.tgz#a904501e57cfdd2ffcded45e99a54fef55e46129" + integrity sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.2" + merge2 "^1.3.0" + micromatch "^4.0.4" + +fast-json-stable-stringify@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" + integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== + +fast-levenshtein@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== + +fastq@^1.6.0: + version "1.17.1" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.17.1.tgz#2a523f07a4e7b1e81a42b91b8bf2254107753b47" + integrity sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w== + dependencies: + reusify "^1.0.4" + +file-entry-cache@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" + integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg== + dependencies: + flat-cache "^3.0.4" + +fill-range@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" + integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg== + dependencies: + to-regex-range "^5.0.1" + +find-up@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" + integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== + dependencies: + locate-path "^6.0.0" + path-exists "^4.0.0" + +flat-cache@^3.0.4: + version "3.2.0" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.2.0.tgz#2c0c2d5040c99b1632771a9d105725c0115363ee" + integrity sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw== + dependencies: + flatted "^3.2.9" + keyv "^4.5.3" + rimraf "^3.0.2" + +flatted@^3.2.9: + version "3.3.1" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.3.1.tgz#21db470729a6734d4997002f439cb308987f567a" + integrity sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw== + +for-each@^0.3.3: + version "0.3.3" + resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e" + integrity sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw== + dependencies: + is-callable "^1.1.3" + +foreground-child@^3.1.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-3.3.0.tgz#0ac8644c06e431439f8561db8ecf29a7b5519c77" + integrity sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg== + dependencies: + cross-spawn "^7.0.0" + signal-exit "^4.0.1" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== + +fsevents@~2.3.2: + version "2.3.3" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" + integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== + +function-bind@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" + integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== + +function.prototype.name@^1.1.6: + version "1.1.6" + resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.6.tgz#cdf315b7d90ee77a4c6ee216c3c3362da07533fd" + integrity sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + functions-have-names "^1.2.3" + +functions-have-names@^1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834" + integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ== + +get-intrinsic@^1.1.3, get-intrinsic@^1.2.1, get-intrinsic@^1.2.3, get-intrinsic@^1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.4.tgz#e385f5a4b5227d449c3eabbad05494ef0abbeadd" + integrity sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ== + dependencies: + es-errors "^1.3.0" + function-bind "^1.1.2" + has-proto "^1.0.1" + has-symbols "^1.0.3" + hasown "^2.0.0" + +get-symbol-description@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.0.2.tgz#533744d5aa20aca4e079c8e5daf7fd44202821f5" + integrity sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg== + dependencies: + call-bind "^1.0.5" + es-errors "^1.3.0" + get-intrinsic "^1.2.4" + +get-tsconfig@^4.7.5: + version "4.8.1" + resolved "https://registry.yarnpkg.com/get-tsconfig/-/get-tsconfig-4.8.1.tgz#8995eb391ae6e1638d251118c7b56de7eb425471" + integrity sha512-k9PN+cFBmaLWtVz29SkUoqU5O0slLuHJXt/2P+tMVFT+phsSGXGkp9t3rQIqdz0e+06EHNGs3oM6ZX1s2zHxRg== + dependencies: + resolve-pkg-maps "^1.0.0" + +glob-parent@^5.1.2, glob-parent@~5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== + dependencies: + is-glob "^4.0.1" + +glob-parent@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" + integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== + dependencies: + is-glob "^4.0.3" + +glob@^10.3.10: + version "10.4.5" + resolved "https://registry.yarnpkg.com/glob/-/glob-10.4.5.tgz#f4d9f0b90ffdbab09c9d77f5f29b4262517b0956" + integrity sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg== + dependencies: + foreground-child "^3.1.0" + jackspeak "^3.1.2" + minimatch "^9.0.4" + minipass "^7.1.2" + package-json-from-dist "^1.0.0" + path-scurry "^1.11.1" + +glob@^7.1.3: + version "7.2.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" + integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.1.1" + once "^1.3.0" + path-is-absolute "^1.0.0" + +globals@^13.19.0: + version "13.24.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-13.24.0.tgz#8432a19d78ce0c1e833949c36adb345400bb1171" + integrity sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ== + dependencies: + type-fest "^0.20.2" + +globalthis@^1.0.3, globalthis@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.4.tgz#7430ed3a975d97bfb59bcce41f5cabbafa651236" + integrity sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ== + dependencies: + define-properties "^1.2.1" + gopd "^1.0.1" + +gopd@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c" + integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA== + dependencies: + get-intrinsic "^1.1.3" + +graceful-fs@^4.2.4: + version "4.2.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" + integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== + +graphemer@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" + integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== + +has-bigints@^1.0.1, has-bigints@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa" + integrity sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ== + +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + +has-property-descriptors@^1.0.0, has-property-descriptors@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz#963ed7d071dc7bf5f084c5bfbe0d1b6222586854" + integrity sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg== + dependencies: + es-define-property "^1.0.0" + +has-proto@^1.0.1, has-proto@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.3.tgz#b31ddfe9b0e6e9914536a6ab286426d0214f77fd" + integrity sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q== + +has-symbols@^1.0.2, has-symbols@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" + integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== + +has-tostringtag@^1.0.0, has-tostringtag@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.2.tgz#2cdc42d40bef2e5b4eeab7c01a73c54ce7ab5abc" + integrity sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw== + dependencies: + has-symbols "^1.0.3" + +hasown@^2.0.0, hasown@^2.0.1, hasown@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" + integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== + dependencies: + function-bind "^1.1.2" + +ignore@^5.2.0, ignore@^5.3.1: + version "5.3.2" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.2.tgz#3cd40e729f3643fd87cb04e50bf0eb722bc596f5" + integrity sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g== + +import-fresh@^3.2.1: + version "3.3.0" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" + integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== + dependencies: + parent-module "^1.0.0" + resolve-from "^4.0.0" + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +internal-slot@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.7.tgz#c06dcca3ed874249881007b0a5523b172a190802" + integrity sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g== + dependencies: + es-errors "^1.3.0" + hasown "^2.0.0" + side-channel "^1.0.4" + +is-array-buffer@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/is-array-buffer/-/is-array-buffer-3.0.4.tgz#7a1f92b3d61edd2bc65d24f130530ea93d7fae98" + integrity sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.2.1" + +is-arrayish@^0.3.1: + version "0.3.2" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.3.2.tgz#4574a2ae56f7ab206896fb431eaeed066fdf8f03" + integrity sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ== + +is-async-function@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-async-function/-/is-async-function-2.0.0.tgz#8e4418efd3e5d3a6ebb0164c05ef5afb69aa9646" + integrity sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA== + dependencies: + has-tostringtag "^1.0.0" + +is-bigint@^1.0.1: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.4.tgz#08147a1875bc2b32005d41ccd8291dffc6691df3" + integrity sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg== + dependencies: + has-bigints "^1.0.1" + +is-binary-path@~2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" + integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== + dependencies: + binary-extensions "^2.0.0" + +is-boolean-object@^1.1.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.1.2.tgz#5c6dc200246dd9321ae4b885a114bb1f75f63719" + integrity sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA== + dependencies: + call-bind "^1.0.2" + has-tostringtag "^1.0.0" + +is-bun-module@^1.0.2: + version "1.2.1" + resolved "https://registry.yarnpkg.com/is-bun-module/-/is-bun-module-1.2.1.tgz#495e706f42e29f086fd5fe1ac3c51f106062b9fc" + integrity sha512-AmidtEM6D6NmUiLOvvU7+IePxjEjOzra2h0pSrsfSAcXwl/83zLLXDByafUJy9k/rKK0pvXMLdwKwGHlX2Ke6Q== + dependencies: + semver "^7.6.3" + +is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.2.7: + version "1.2.7" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" + integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== + +is-core-module@^2.13.0, is-core-module@^2.15.1: + version "2.15.1" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.15.1.tgz#a7363a25bee942fefab0de13bf6aa372c82dcc37" + integrity sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ== + dependencies: + hasown "^2.0.2" + +is-data-view@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-data-view/-/is-data-view-1.0.1.tgz#4b4d3a511b70f3dc26d42c03ca9ca515d847759f" + integrity sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w== + dependencies: + is-typed-array "^1.1.13" + +is-date-object@^1.0.1, is-date-object@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.5.tgz#0841d5536e724c25597bf6ea62e1bd38298df31f" + integrity sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ== + dependencies: + has-tostringtag "^1.0.0" + +is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== + +is-finalizationregistry@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz#c8749b65f17c133313e661b1289b95ad3dbd62e6" + integrity sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw== + dependencies: + call-bind "^1.0.2" + +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + +is-generator-function@^1.0.10: + version "1.0.10" + resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.0.10.tgz#f1558baf1ac17e0deea7c0415c438351ff2b3c72" + integrity sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A== + dependencies: + has-tostringtag "^1.0.0" + +is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: + version "4.0.3" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" + integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== + dependencies: + is-extglob "^2.1.1" + +is-map@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/is-map/-/is-map-2.0.3.tgz#ede96b7fe1e270b3c4465e3a465658764926d62e" + integrity sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw== + +is-negative-zero@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.3.tgz#ced903a027aca6381b777a5743069d7376a49747" + integrity sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw== + +is-number-object@^1.0.4: + version "1.0.7" + resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.7.tgz#59d50ada4c45251784e9904f5246c742f07a42fc" + integrity sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ== + dependencies: + has-tostringtag "^1.0.0" + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +is-path-inside@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" + integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== + +is-regex@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" + integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg== + dependencies: + call-bind "^1.0.2" + has-tostringtag "^1.0.0" + +is-set@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/is-set/-/is-set-2.0.3.tgz#8ab209ea424608141372ded6e0cb200ef1d9d01d" + integrity sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg== + +is-shared-array-buffer@^1.0.2, is-shared-array-buffer@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz#1237f1cba059cdb62431d378dcc37d9680181688" + integrity sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg== + dependencies: + call-bind "^1.0.7" + +is-string@^1.0.5, is-string@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd" + integrity sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg== + dependencies: + has-tostringtag "^1.0.0" + +is-symbol@^1.0.2, is-symbol@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.4.tgz#a6dac93b635b063ca6872236de88910a57af139c" + integrity sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg== + dependencies: + has-symbols "^1.0.2" + +is-typed-array@^1.1.13: + version "1.1.13" + resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.13.tgz#d6c5ca56df62334959322d7d7dd1cca50debe229" + integrity sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw== + dependencies: + which-typed-array "^1.1.14" + +is-weakmap@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/is-weakmap/-/is-weakmap-2.0.2.tgz#bf72615d649dfe5f699079c54b83e47d1ae19cfd" + integrity sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w== + +is-weakref@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.2.tgz#9529f383a9338205e89765e0392efc2f100f06f2" + integrity sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ== + dependencies: + call-bind "^1.0.2" + +is-weakset@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/is-weakset/-/is-weakset-2.0.3.tgz#e801519df8c0c43e12ff2834eead84ec9e624007" + integrity sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ== + dependencies: + call-bind "^1.0.7" + get-intrinsic "^1.2.4" + +isarray@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723" + integrity sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw== + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== + +iterator.prototype@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/iterator.prototype/-/iterator.prototype-1.1.3.tgz#016c2abe0be3bbdb8319852884f60908ac62bf9c" + integrity sha512-FW5iMbeQ6rBGm/oKgzq2aW4KvAGpxPzYES8N4g4xNXUKpL1mclMvOe+76AcLDTvD+Ze+sOpVhgdAQEKF4L9iGQ== + dependencies: + define-properties "^1.2.1" + get-intrinsic "^1.2.1" + has-symbols "^1.0.3" + reflect.getprototypeof "^1.0.4" + set-function-name "^2.0.1" + +jackspeak@^3.1.2: + version "3.4.3" + resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-3.4.3.tgz#8833a9d89ab4acde6188942bd1c53b6390ed5a8a" + integrity sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw== + dependencies: + "@isaacs/cliui" "^8.0.2" + optionalDependencies: + "@pkgjs/parseargs" "^0.11.0" + +jiti@^1.21.0: + version "1.21.6" + resolved "https://registry.yarnpkg.com/jiti/-/jiti-1.21.6.tgz#6c7f7398dd4b3142767f9a168af2f317a428d268" + integrity sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w== + +"js-tokens@^3.0.0 || ^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + +js-yaml@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" + integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== + dependencies: + argparse "^2.0.1" + +json-buffer@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" + integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== + +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + +json-stable-stringify-without-jsonify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" + integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== + +json5@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.2.tgz#63d98d60f21b313b77c4d6da18bfa69d80e1d593" + integrity sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA== + dependencies: + minimist "^1.2.0" + +"jsx-ast-utils@^2.4.1 || ^3.0.0", jsx-ast-utils@^3.3.5: + version "3.3.5" + resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz#4766bd05a8e2a11af222becd19e15575e52a853a" + integrity sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ== + dependencies: + array-includes "^3.1.6" + array.prototype.flat "^1.3.1" + object.assign "^4.1.4" + object.values "^1.1.6" + +keyv@^4.5.3: + version "4.5.4" + resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93" + integrity sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw== + dependencies: + json-buffer "3.0.1" + +language-subtag-registry@^0.3.20: + version "0.3.23" + resolved "https://registry.yarnpkg.com/language-subtag-registry/-/language-subtag-registry-0.3.23.tgz#23529e04d9e3b74679d70142df3fd2eb6ec572e7" + integrity sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ== + +language-tags@^1.0.9: + version "1.0.9" + resolved "https://registry.yarnpkg.com/language-tags/-/language-tags-1.0.9.tgz#1ffdcd0ec0fafb4b1be7f8b11f306ad0f9c08777" + integrity sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA== + dependencies: + language-subtag-registry "^0.3.20" + +levn@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" + integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== + dependencies: + prelude-ls "^1.2.1" + type-check "~0.4.0" + +lilconfig@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.1.0.tgz#78e23ac89ebb7e1bfbf25b18043de756548e7f52" + integrity sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ== + +lilconfig@^3.0.0: + version "3.1.2" + resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-3.1.2.tgz#e4a7c3cb549e3a606c8dcc32e5ae1005e62c05cb" + integrity sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow== + +lines-and-columns@^1.1.6: + version "1.2.4" + resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" + integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== + +locate-path@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" + integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== + dependencies: + p-locate "^5.0.0" + +lodash.merge@^4.6.2: + version "4.6.2" + resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" + integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== + +loose-envify@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" + integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== + dependencies: + js-tokens "^3.0.0 || ^4.0.0" + +lru-cache@^10.2.0: + version "10.4.3" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.4.3.tgz#410fc8a17b70e598013df257c2446b7f3383f119" + integrity sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ== + +merge2@^1.3.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" + integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== + +micromatch@^4.0.4, micromatch@^4.0.5: + version "4.0.8" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.8.tgz#d66fa18f3a47076789320b9b1af32bd86d9fa202" + integrity sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA== + dependencies: + braces "^3.0.3" + picomatch "^2.3.1" + +minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" + integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== + dependencies: + brace-expansion "^1.1.7" + +minimatch@^9.0.4: + version "9.0.5" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.5.tgz#d74f9dd6b57d83d8e98cfb82133b03978bc929e5" + integrity sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow== + dependencies: + brace-expansion "^2.0.1" + +minimist@^1.2.0, minimist@^1.2.6: + version "1.2.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" + integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== + +"minipass@^5.0.0 || ^6.0.2 || ^7.0.0", minipass@^7.1.2: + version "7.1.2" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.1.2.tgz#93a9626ce5e5e66bd4db86849e7515e92340a707" + integrity sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw== + +ms@^2.1.1, ms@^2.1.3: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + +mz@^2.7.0: + version "2.7.0" + resolved "https://registry.yarnpkg.com/mz/-/mz-2.7.0.tgz#95008057a56cafadc2bc63dde7f9ff6955948e32" + integrity sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q== + dependencies: + any-promise "^1.0.0" + object-assign "^4.0.1" + thenify-all "^1.0.0" + +nanoid@^3.3.6, nanoid@^3.3.7: + version "3.3.7" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.7.tgz#d0c301a691bc8d54efa0a2226ccf3fe2fd656bd8" + integrity sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g== + +natural-compare@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" + integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== + +next@15.0.1: + version "15.0.1" + resolved "https://registry.yarnpkg.com/next/-/next-15.0.1.tgz#a0e8eda35d803cb7f8092b2a2eb9d072e22bf21d" + integrity sha512-PSkFkr/w7UnFWm+EP8y/QpHrJXMqpZzAXpergB/EqLPOh4SGPJXv1wj4mslr2hUZBAS9pX7/9YLIdxTv6fwytw== + dependencies: + "@next/env" "15.0.1" + "@swc/counter" "0.1.3" + "@swc/helpers" "0.5.13" + busboy "1.6.0" + caniuse-lite "^1.0.30001579" + postcss "8.4.31" + styled-jsx "5.1.6" + optionalDependencies: + "@next/swc-darwin-arm64" "15.0.1" + "@next/swc-darwin-x64" "15.0.1" + "@next/swc-linux-arm64-gnu" "15.0.1" + "@next/swc-linux-arm64-musl" "15.0.1" + "@next/swc-linux-x64-gnu" "15.0.1" + "@next/swc-linux-x64-musl" "15.0.1" + "@next/swc-win32-arm64-msvc" "15.0.1" + "@next/swc-win32-x64-msvc" "15.0.1" + sharp "^0.33.5" + +normalize-path@^3.0.0, normalize-path@~3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + +object-assign@^4.0.1, object-assign@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== + +object-hash@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-3.0.0.tgz#73f97f753e7baffc0e2cc9d6e079079744ac82e9" + integrity sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw== + +object-inspect@^1.13.1: + version "1.13.2" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.2.tgz#dea0088467fb991e67af4058147a24824a3043ff" + integrity sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g== + +object-keys@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" + integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== + +object.assign@^4.1.4, object.assign@^4.1.5: + version "4.1.5" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.5.tgz#3a833f9ab7fdb80fc9e8d2300c803d216d8fdbb0" + integrity sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ== + dependencies: + call-bind "^1.0.5" + define-properties "^1.2.1" + has-symbols "^1.0.3" + object-keys "^1.1.1" + +object.entries@^1.1.8: + version "1.1.8" + resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.8.tgz#bffe6f282e01f4d17807204a24f8edd823599c41" + integrity sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + es-object-atoms "^1.0.0" + +object.fromentries@^2.0.8: + version "2.0.8" + resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.8.tgz#f7195d8a9b97bd95cbc1999ea939ecd1a2b00c65" + integrity sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + es-abstract "^1.23.2" + es-object-atoms "^1.0.0" + +object.groupby@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/object.groupby/-/object.groupby-1.0.3.tgz#9b125c36238129f6f7b61954a1e7176148d5002e" + integrity sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + es-abstract "^1.23.2" + +object.values@^1.1.6, object.values@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.2.0.tgz#65405a9d92cee68ac2d303002e0b8470a4d9ab1b" + integrity sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + es-object-atoms "^1.0.0" + +once@^1.3.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== + dependencies: + wrappy "1" + +optionator@^0.9.3: + version "0.9.4" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.4.tgz#7ea1c1a5d91d764fb282139c88fe11e182a3a734" + integrity sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g== + dependencies: + deep-is "^0.1.3" + fast-levenshtein "^2.0.6" + levn "^0.4.1" + prelude-ls "^1.2.1" + type-check "^0.4.0" + word-wrap "^1.2.5" + +p-limit@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" + integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== + dependencies: + yocto-queue "^0.1.0" + +p-locate@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" + integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== + dependencies: + p-limit "^3.0.2" + +package-json-from-dist@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz#4f1471a010827a86f94cfd9b0727e36d267de505" + integrity sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw== + +parent-module@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" + integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== + dependencies: + callsites "^3.0.0" + +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== + +path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + +path-parse@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" + integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== + +path-scurry@^1.11.1: + version "1.11.1" + resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.11.1.tgz#7960a668888594a0720b12a911d1a742ab9f11d2" + integrity sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA== + dependencies: + lru-cache "^10.2.0" + minipass "^5.0.0 || ^6.0.2 || ^7.0.0" + +picocolors@^1.0.0, picocolors@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b" + integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA== + +picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== + +pify@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" + integrity sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog== + +pirates@^4.0.1: + version "4.0.6" + resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.6.tgz#3018ae32ecfcff6c29ba2267cbf21166ac1f36b9" + integrity sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg== + +possible-typed-array-names@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz#89bb63c6fada2c3e90adc4a647beeeb39cc7bf8f" + integrity sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q== + +postcss-import@^15.1.0: + version "15.1.0" + resolved "https://registry.yarnpkg.com/postcss-import/-/postcss-import-15.1.0.tgz#41c64ed8cc0e23735a9698b3249ffdbf704adc70" + integrity sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew== + dependencies: + postcss-value-parser "^4.0.0" + read-cache "^1.0.0" + resolve "^1.1.7" + +postcss-js@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-js/-/postcss-js-4.0.1.tgz#61598186f3703bab052f1c4f7d805f3991bee9d2" + integrity sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw== + dependencies: + camelcase-css "^2.0.1" + +postcss-load-config@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-4.0.2.tgz#7159dcf626118d33e299f485d6afe4aff7c4a3e3" + integrity sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ== + dependencies: + lilconfig "^3.0.0" + yaml "^2.3.4" + +postcss-nested@^6.0.1: + version "6.2.0" + resolved "https://registry.yarnpkg.com/postcss-nested/-/postcss-nested-6.2.0.tgz#4c2d22ab5f20b9cb61e2c5c5915950784d068131" + integrity sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ== + dependencies: + postcss-selector-parser "^6.1.1" + +postcss-selector-parser@^6.0.11, postcss-selector-parser@^6.1.1: + version "6.1.2" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz#27ecb41fb0e3b6ba7a1ec84fff347f734c7929de" + integrity sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg== + dependencies: + cssesc "^3.0.0" + util-deprecate "^1.0.2" + +postcss-value-parser@^4.0.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514" + integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ== + +postcss@8.4.31: + version "8.4.31" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.31.tgz#92b451050a9f914da6755af352bdc0192508656d" + integrity sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ== + dependencies: + nanoid "^3.3.6" + picocolors "^1.0.0" + source-map-js "^1.0.2" + +postcss@^8, postcss@^8.4.23: + version "8.4.47" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.47.tgz#5bf6c9a010f3e724c503bf03ef7947dcb0fea365" + integrity sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ== + dependencies: + nanoid "^3.3.7" + picocolors "^1.1.0" + source-map-js "^1.2.1" + +prelude-ls@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" + integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== + +prop-types@^15.8.1: + version "15.8.1" + resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" + integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg== + dependencies: + loose-envify "^1.4.0" + object-assign "^4.1.1" + react-is "^16.13.1" + +punycode@^2.1.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" + integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== + +queue-microtask@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" + integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== + +react-dom@19.0.0-rc-69d4b800-20241021: + version "19.0.0-rc-69d4b800-20241021" + resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-19.0.0-rc-69d4b800-20241021.tgz#e27b4f2c962236e9ece496a0ea1c9c7161608ea0" + integrity sha512-ZXBsP/kTDLI9QopUaUgYJhmmAhO8aKz7DCv2Ui2rA9boCfJ/dRRh6BlVidsyb2dPzG01rItdRFQqwbP+x9s5Rg== + dependencies: + scheduler "0.25.0-rc-69d4b800-20241021" + +react-is@^16.13.1: + version "16.13.1" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" + integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== + +react@19.0.0-rc-69d4b800-20241021: + version "19.0.0-rc-69d4b800-20241021" + resolved "https://registry.yarnpkg.com/react/-/react-19.0.0-rc-69d4b800-20241021.tgz#2c3ce2a581df8c4c9e4059189af29b89022edd41" + integrity sha512-dXki4tN+rP+4xhsm65q/QI/19VCZdu5vPcy4h6zaJt20XP8/1r/LCwrLFYuj8hElbNz5AmxW6JtRa7ej0BzZdg== + +read-cache@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/read-cache/-/read-cache-1.0.0.tgz#e664ef31161166c9751cdbe8dbcf86b5fb58f774" + integrity sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA== + dependencies: + pify "^2.3.0" + +readdirp@~3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" + integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== + dependencies: + picomatch "^2.2.1" + +reflect-metadata@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/reflect-metadata/-/reflect-metadata-0.2.2.tgz#400c845b6cba87a21f2c65c4aeb158f4fa4d9c5b" + integrity sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q== + +reflect.getprototypeof@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/reflect.getprototypeof/-/reflect.getprototypeof-1.0.6.tgz#3ab04c32a8390b770712b7a8633972702d278859" + integrity sha512-fmfw4XgoDke3kdI6h4xcUz1dG8uaiv5q9gcEwLS4Pnth2kxT+GZ7YehS1JTMGBQmtV7Y4GFGbs2re2NqhdozUg== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + es-abstract "^1.23.1" + es-errors "^1.3.0" + get-intrinsic "^1.2.4" + globalthis "^1.0.3" + which-builtin-type "^1.1.3" + +regexp.prototype.flags@^1.5.2: + version "1.5.3" + resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.5.3.tgz#b3ae40b1d2499b8350ab2c3fe6ef3845d3a96f42" + integrity sha512-vqlC04+RQoFalODCbCumG2xIOvapzVMHwsyIGM/SIE8fRhFFsXeH8/QQ+s0T0kDAhKc4k30s73/0ydkHQz6HlQ== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + es-errors "^1.3.0" + set-function-name "^2.0.2" + +resolve-from@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" + integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== + +resolve-pkg-maps@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz#616b3dc2c57056b5588c31cdf4b3d64db133720f" + integrity sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw== + +resolve@^1.1.7, resolve@^1.22.2, resolve@^1.22.4: + version "1.22.8" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d" + integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== + dependencies: + is-core-module "^2.13.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + +resolve@^2.0.0-next.5: + version "2.0.0-next.5" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-2.0.0-next.5.tgz#6b0ec3107e671e52b68cd068ef327173b90dc03c" + integrity sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA== + dependencies: + is-core-module "^2.13.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + +reusify@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" + integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== + +rimraf@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" + integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== + dependencies: + glob "^7.1.3" + +run-parallel@^1.1.9: + version "1.2.0" + resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" + integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== + dependencies: + queue-microtask "^1.2.2" + +safe-array-concat@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/safe-array-concat/-/safe-array-concat-1.1.2.tgz#81d77ee0c4e8b863635227c721278dd524c20edb" + integrity sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q== + dependencies: + call-bind "^1.0.7" + get-intrinsic "^1.2.4" + has-symbols "^1.0.3" + isarray "^2.0.5" + +safe-regex-test@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/safe-regex-test/-/safe-regex-test-1.0.3.tgz#a5b4c0f06e0ab50ea2c395c14d8371232924c377" + integrity sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw== + dependencies: + call-bind "^1.0.6" + es-errors "^1.3.0" + is-regex "^1.1.4" + +scheduler@0.25.0-rc-69d4b800-20241021: + version "0.25.0-rc-69d4b800-20241021" + resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.25.0-rc-69d4b800-20241021.tgz#336e47ef2bd5eddb0ebacfd910b5df1b236d92bd" + integrity sha512-S5AYX/YhMAN6u9AXgKYbZP4U4ZklC6R9Q7HmFSBk7d4DLiHVNxvAvlSvuM4nxFkwOk50MnpfTKQ7UWHXDOc9Eg== + +semver@^6.3.1: + version "6.3.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" + integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== + +semver@^7.6.0, semver@^7.6.3: + version "7.6.3" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.3.tgz#980f7b5550bc175fb4dc09403085627f9eb33143" + integrity sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A== + +set-function-length@^1.2.1: + version "1.2.2" + resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.2.tgz#aac72314198eaed975cf77b2c3b6b880695e5449" + integrity sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg== + dependencies: + define-data-property "^1.1.4" + es-errors "^1.3.0" + function-bind "^1.1.2" + get-intrinsic "^1.2.4" + gopd "^1.0.1" + has-property-descriptors "^1.0.2" + +set-function-name@^2.0.1, set-function-name@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/set-function-name/-/set-function-name-2.0.2.tgz#16a705c5a0dc2f5e638ca96d8a8cd4e1c2b90985" + integrity sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ== + dependencies: + define-data-property "^1.1.4" + es-errors "^1.3.0" + functions-have-names "^1.2.3" + has-property-descriptors "^1.0.2" + +sharp@^0.33.5: + version "0.33.5" + resolved "https://registry.yarnpkg.com/sharp/-/sharp-0.33.5.tgz#13e0e4130cc309d6a9497596715240b2ec0c594e" + integrity sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw== + dependencies: + color "^4.2.3" + detect-libc "^2.0.3" + semver "^7.6.3" + optionalDependencies: + "@img/sharp-darwin-arm64" "0.33.5" + "@img/sharp-darwin-x64" "0.33.5" + "@img/sharp-libvips-darwin-arm64" "1.0.4" + "@img/sharp-libvips-darwin-x64" "1.0.4" + "@img/sharp-libvips-linux-arm" "1.0.5" + "@img/sharp-libvips-linux-arm64" "1.0.4" + "@img/sharp-libvips-linux-s390x" "1.0.4" + "@img/sharp-libvips-linux-x64" "1.0.4" + "@img/sharp-libvips-linuxmusl-arm64" "1.0.4" + "@img/sharp-libvips-linuxmusl-x64" "1.0.4" + "@img/sharp-linux-arm" "0.33.5" + "@img/sharp-linux-arm64" "0.33.5" + "@img/sharp-linux-s390x" "0.33.5" + "@img/sharp-linux-x64" "0.33.5" + "@img/sharp-linuxmusl-arm64" "0.33.5" + "@img/sharp-linuxmusl-x64" "0.33.5" + "@img/sharp-wasm32" "0.33.5" + "@img/sharp-win32-ia32" "0.33.5" + "@img/sharp-win32-x64" "0.33.5" + +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + +side-channel@^1.0.4, side-channel@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.6.tgz#abd25fb7cd24baf45466406b1096b7831c9215f2" + integrity sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA== + dependencies: + call-bind "^1.0.7" + es-errors "^1.3.0" + get-intrinsic "^1.2.4" + object-inspect "^1.13.1" + +signal-exit@^4.0.1: + version "4.1.0" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04" + integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== + +simple-swizzle@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/simple-swizzle/-/simple-swizzle-0.2.2.tgz#a4da6b635ffcccca33f70d17cb92592de95e557a" + integrity sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg== + dependencies: + is-arrayish "^0.3.1" + +source-map-js@^1.0.2, source-map-js@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.1.tgz#1ce5650fddd87abc099eda37dcff024c2667ae46" + integrity sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA== + +streamsearch@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-1.1.0.tgz#404dd1e2247ca94af554e841a8ef0eaa238da764" + integrity sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg== + +"string-width-cjs@npm:string-width@^4.2.0": + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string-width@^4.1.0: + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string-width@^5.0.1, string-width@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" + integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA== + dependencies: + eastasianwidth "^0.2.0" + emoji-regex "^9.2.2" + strip-ansi "^7.0.1" + +string.prototype.includes@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/string.prototype.includes/-/string.prototype.includes-2.0.1.tgz#eceef21283640761a81dbe16d6c7171a4edf7d92" + integrity sha512-o7+c9bW6zpAdJHTtujeePODAhkuicdAryFsfVKwA+wGw89wJ4GTY484WTucM9hLtDEOpOvI+aHnzqnC5lHp4Rg== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + es-abstract "^1.23.3" + +string.prototype.matchall@^4.0.11: + version "4.0.11" + resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.11.tgz#1092a72c59268d2abaad76582dccc687c0297e0a" + integrity sha512-NUdh0aDavY2og7IbBPenWqR9exH+E26Sv8e0/eTe1tltDGZL+GtBkDAnnyBtmekfK6/Dq3MkcGtzXFEd1LQrtg== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + es-abstract "^1.23.2" + es-errors "^1.3.0" + es-object-atoms "^1.0.0" + get-intrinsic "^1.2.4" + gopd "^1.0.1" + has-symbols "^1.0.3" + internal-slot "^1.0.7" + regexp.prototype.flags "^1.5.2" + set-function-name "^2.0.2" + side-channel "^1.0.6" + +string.prototype.repeat@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz#e90872ee0308b29435aa26275f6e1b762daee01a" + integrity sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.5" + +string.prototype.trim@^1.2.9: + version "1.2.9" + resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz#b6fa326d72d2c78b6df02f7759c73f8f6274faa4" + integrity sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + es-abstract "^1.23.0" + es-object-atoms "^1.0.0" + +string.prototype.trimend@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz#3651b8513719e8a9f48de7f2f77640b26652b229" + integrity sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + es-object-atoms "^1.0.0" + +string.prototype.trimstart@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz#7ee834dda8c7c17eff3118472bb35bfedaa34dde" + integrity sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + es-object-atoms "^1.0.0" + +"strip-ansi-cjs@npm:strip-ansi@^6.0.1": + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-ansi@^7.0.1: + version "7.1.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" + integrity sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ== + dependencies: + ansi-regex "^6.0.1" + +strip-bom@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" + integrity sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA== + +strip-json-comments@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" + integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== + +styled-jsx@5.1.6: + version "5.1.6" + resolved "https://registry.yarnpkg.com/styled-jsx/-/styled-jsx-5.1.6.tgz#83b90c077e6c6a80f7f5e8781d0f311b2fe41499" + integrity sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA== + dependencies: + client-only "0.0.1" + +sucrase@^3.32.0: + version "3.35.0" + resolved "https://registry.yarnpkg.com/sucrase/-/sucrase-3.35.0.tgz#57f17a3d7e19b36d8995f06679d121be914ae263" + integrity sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA== + dependencies: + "@jridgewell/gen-mapping" "^0.3.2" + commander "^4.0.0" + glob "^10.3.10" + lines-and-columns "^1.1.6" + mz "^2.7.0" + pirates "^4.0.1" + ts-interface-checker "^0.1.9" + +supports-color@^7.1.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + dependencies: + has-flag "^4.0.0" + +supports-preserve-symlinks-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" + integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== + +tailwindcss@^3.4.1: + version "3.4.14" + resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-3.4.14.tgz#6dd23a7f54ec197b19159e91e3bb1e55e7aa73ac" + integrity sha512-IcSvOcTRcUtQQ7ILQL5quRDg7Xs93PdJEk1ZLbhhvJc7uj/OAhYOnruEiwnGgBvUtaUAJ8/mhSw1o8L2jCiENA== + dependencies: + "@alloc/quick-lru" "^5.2.0" + arg "^5.0.2" + chokidar "^3.5.3" + didyoumean "^1.2.2" + dlv "^1.1.3" + fast-glob "^3.3.0" + glob-parent "^6.0.2" + is-glob "^4.0.3" + jiti "^1.21.0" + lilconfig "^2.1.0" + micromatch "^4.0.5" + normalize-path "^3.0.0" + object-hash "^3.0.0" + picocolors "^1.0.0" + postcss "^8.4.23" + postcss-import "^15.1.0" + postcss-js "^4.0.1" + postcss-load-config "^4.0.1" + postcss-nested "^6.0.1" + postcss-selector-parser "^6.0.11" + resolve "^1.22.2" + sucrase "^3.32.0" + +tapable@^2.2.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" + integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== + +text-table@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" + integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== + +thenify-all@^1.0.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/thenify-all/-/thenify-all-1.6.0.tgz#1a1918d402d8fc3f98fbf234db0bcc8cc10e9726" + integrity sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA== + dependencies: + thenify ">= 3.1.0 < 4" + +"thenify@>= 3.1.0 < 4": + version "3.3.1" + resolved "https://registry.yarnpkg.com/thenify/-/thenify-3.3.1.tgz#8932e686a4066038a016dd9e2ca46add9838a95f" + integrity sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw== + dependencies: + any-promise "^1.0.0" + +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + +ts-api-utils@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.3.0.tgz#4b490e27129f1e8e686b45cc4ab63714dc60eea1" + integrity sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ== + +ts-interface-checker@^0.1.9: + version "0.1.13" + resolved "https://registry.yarnpkg.com/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz#784fd3d679722bc103b1b4b8030bcddb5db2a699" + integrity sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA== + +tsconfig-paths@^3.15.0: + version "3.15.0" + resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz#5299ec605e55b1abb23ec939ef15edaf483070d4" + integrity sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg== + dependencies: + "@types/json5" "^0.0.29" + json5 "^1.0.2" + minimist "^1.2.6" + strip-bom "^3.0.0" + +tslib@^1.9.3: + version "1.14.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" + integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== + +tslib@^2.4.0: + version "2.8.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.0.tgz#d124c86c3c05a40a91e6fdea4021bd31d377971b" + integrity sha512-jWVzBLplnCmoaTr13V9dYbiQ99wvZRd0vNWaDRg+aVYRcjDF3nDksxFDE/+fkXnKhpnUUkmx5pK/v8mCtLVqZA== + +tsyringe@^4.8.0: + version "4.8.0" + resolved "https://registry.yarnpkg.com/tsyringe/-/tsyringe-4.8.0.tgz#d599651b36793ba872870fee4f845bd484a5cac1" + integrity sha512-YB1FG+axdxADa3ncEtRnQCFq/M0lALGLxSZeVNbTU8NqhOVc51nnv2CISTcvc1kyv6EGPtXVr0v6lWeDxiijOA== + dependencies: + tslib "^1.9.3" + +type-check@^0.4.0, type-check@~0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" + integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== + dependencies: + prelude-ls "^1.2.1" + +type-fest@^0.20.2: + version "0.20.2" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" + integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== + +typed-array-buffer@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz#1867c5d83b20fcb5ccf32649e5e2fc7424474ff3" + integrity sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ== + dependencies: + call-bind "^1.0.7" + es-errors "^1.3.0" + is-typed-array "^1.1.13" + +typed-array-byte-length@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz#d92972d3cff99a3fa2e765a28fcdc0f1d89dec67" + integrity sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw== + dependencies: + call-bind "^1.0.7" + for-each "^0.3.3" + gopd "^1.0.1" + has-proto "^1.0.3" + is-typed-array "^1.1.13" + +typed-array-byte-offset@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz#f9ec1acb9259f395093e4567eb3c28a580d02063" + integrity sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA== + dependencies: + available-typed-arrays "^1.0.7" + call-bind "^1.0.7" + for-each "^0.3.3" + gopd "^1.0.1" + has-proto "^1.0.3" + is-typed-array "^1.1.13" + +typed-array-length@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/typed-array-length/-/typed-array-length-1.0.6.tgz#57155207c76e64a3457482dfdc1c9d1d3c4c73a3" + integrity sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g== + dependencies: + call-bind "^1.0.7" + for-each "^0.3.3" + gopd "^1.0.1" + has-proto "^1.0.3" + is-typed-array "^1.1.13" + possible-typed-array-names "^1.0.0" + +typescript@^5: + version "5.6.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.6.3.tgz#5f3449e31c9d94febb17de03cc081dd56d81db5b" + integrity sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw== + +unbox-primitive@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.2.tgz#29032021057d5e6cdbd08c5129c226dff8ed6f9e" + integrity sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw== + dependencies: + call-bind "^1.0.2" + has-bigints "^1.0.2" + has-symbols "^1.0.3" + which-boxed-primitive "^1.0.2" + +undici-types@~6.19.2: + version "6.19.8" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.19.8.tgz#35111c9d1437ab83a7cdc0abae2f26d88eda0a02" + integrity sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw== + +uri-js@^4.2.2: + version "4.4.1" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" + integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== + dependencies: + punycode "^2.1.0" + +util-deprecate@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== + +which-boxed-primitive@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6" + integrity sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg== + dependencies: + is-bigint "^1.0.1" + is-boolean-object "^1.1.0" + is-number-object "^1.0.4" + is-string "^1.0.5" + is-symbol "^1.0.3" + +which-builtin-type@^1.1.3: + version "1.1.4" + resolved "https://registry.yarnpkg.com/which-builtin-type/-/which-builtin-type-1.1.4.tgz#592796260602fc3514a1b5ee7fa29319b72380c3" + integrity sha512-bppkmBSsHFmIMSl8BO9TbsyzsvGjVoppt8xUiGzwiu/bhDCGxnpOKCxgqj6GuyHE0mINMDecBFPlOm2hzY084w== + dependencies: + function.prototype.name "^1.1.6" + has-tostringtag "^1.0.2" + is-async-function "^2.0.0" + is-date-object "^1.0.5" + is-finalizationregistry "^1.0.2" + is-generator-function "^1.0.10" + is-regex "^1.1.4" + is-weakref "^1.0.2" + isarray "^2.0.5" + which-boxed-primitive "^1.0.2" + which-collection "^1.0.2" + which-typed-array "^1.1.15" + +which-collection@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/which-collection/-/which-collection-1.0.2.tgz#627ef76243920a107e7ce8e96191debe4b16c2a0" + integrity sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw== + dependencies: + is-map "^2.0.3" + is-set "^2.0.3" + is-weakmap "^2.0.2" + is-weakset "^2.0.3" + +which-typed-array@^1.1.14, which-typed-array@^1.1.15: + version "1.1.15" + resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.15.tgz#264859e9b11a649b388bfaaf4f767df1f779b38d" + integrity sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA== + dependencies: + available-typed-arrays "^1.0.7" + call-bind "^1.0.7" + for-each "^0.3.3" + gopd "^1.0.1" + has-tostringtag "^1.0.2" + +which@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + +word-wrap@^1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.5.tgz#d2c45c6dd4fbce621a66f136cbe328afd0410b34" + integrity sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA== + +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrap-ansi@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" + integrity sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ== + dependencies: + ansi-styles "^6.1.0" + string-width "^5.0.1" + strip-ansi "^7.0.1" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== + +yaml@^2.3.4: + version "2.6.0" + resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.6.0.tgz#14059ad9d0b1680d0f04d3a60fe00f3a857303c3" + integrity sha512-a6ae//JvKDEra2kdi1qzCyrJW/WZCgFi8ydDV+eXExl95t+5R+ijnqHJbz9tmMh8FUjx3iv2fCQ4dclAQlO2UQ== + +yocto-queue@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" + integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== -- 2.39.5 From f6fba115e322797959033d08e808cf2e99e8c70a Mon Sep 17 00:00:00 2001 From: behnam <behnamrahimpour74@gmail.com> Date: Thu, 31 Oct 2024 18:28:01 +0300 Subject: [PATCH 02/37] Add base architecture --- components.json | 20 ++++++ package.json | 6 ++ src/{ => app}/components/button/button-vm.ts | 0 src/{ => app}/components/button/button.tsx | 6 +- src/app/globals.css | 71 ++++++++++++++++--- src/app/layout.tsx | 1 - src/app/test/client/view/parent-view.tsx | 13 ++++ src/app/test/client/vm/test-button-vm.ts | 34 +++++++++ src/app/test/layout.tsx | 10 +++ src/app/test/modules/test-app-module.ts | 13 ++++ src/app/test/page.tsx | 7 +- src/app/test/vm/test-button-vm.ts | 17 ----- src/bootstrap/di/di-context.tsx | 21 ++++++ src/bootstrap/di/init-di.ts | 4 +- src/bootstrap/helpers/view/base-view.tsx | 32 ++++----- src/bootstrap/helpers/vm/base-vm.ts | 5 ++ src/bootstrap/helpers/vm/vm-decorator.ts | 9 --- src/feature/common/server-di.ts | 13 ++++ .../service/test-get-button-title-service.ts | 9 +++ .../domain/test/service/test-service-repo.ts | 5 ++ src/feature/domain/test/test-module-key.ts | 1 + src/feature/infra/test/module/test-module.ts | 12 ++++ src/feature/infra/test/repo/test-repo-iml.ts | 14 ++++ src/lib/utils.ts | 6 ++ tailwind.config.ts | 61 +++++++++++++--- yarn.lock | 37 ++++++++++ 26 files changed, 355 insertions(+), 72 deletions(-) create mode 100644 components.json rename src/{ => app}/components/button/button-vm.ts (100%) rename src/{ => app}/components/button/button.tsx (80%) create mode 100644 src/app/test/client/view/parent-view.tsx create mode 100644 src/app/test/client/vm/test-button-vm.ts create mode 100644 src/app/test/layout.tsx create mode 100644 src/app/test/modules/test-app-module.ts delete mode 100644 src/app/test/vm/test-button-vm.ts create mode 100644 src/bootstrap/di/di-context.tsx delete mode 100644 src/bootstrap/helpers/vm/vm-decorator.ts create mode 100644 src/feature/common/server-di.ts create mode 100644 src/feature/domain/test/service/test-get-button-title-service.ts create mode 100644 src/feature/domain/test/service/test-service-repo.ts create mode 100644 src/feature/domain/test/test-module-key.ts create mode 100644 src/feature/infra/test/module/test-module.ts create mode 100644 src/feature/infra/test/repo/test-repo-iml.ts create mode 100644 src/lib/utils.ts diff --git a/components.json b/components.json new file mode 100644 index 0000000..7a63543 --- /dev/null +++ b/components.json @@ -0,0 +1,20 @@ +{ + "$schema": "https://ui.shadcn.com/schema.json", + "style": "new-york", + "rsc": true, + "tsx": true, + "tailwind": { + "config": "tailwind.config.ts", + "css": "src/app/globals.css", + "baseColor": "zinc", + "cssVariables": true, + "prefix": "" + }, + "aliases": { + "components": "@/components", + "utils": "@/lib/utils", + "ui": "@/components/ui", + "lib": "@/lib", + "hooks": "@/hooks" + } +} \ No newline at end of file diff --git a/package.json b/package.json index 2db330d..95b1c2b 100644 --- a/package.json +++ b/package.json @@ -9,10 +9,16 @@ "lint": "next lint" }, "dependencies": { + "@radix-ui/react-icons": "^1.3.1", + "class-variance-authority": "^0.7.0", + "clsx": "^2.1.1", + "lucide-react": "^0.454.0", "next": "15.0.1", "react": "19.0.0-rc-69d4b800-20241021", "react-dom": "19.0.0-rc-69d4b800-20241021", "reflect-metadata": "^0.2.2", + "tailwind-merge": "^2.5.4", + "tailwindcss-animate": "^1.0.7", "tsyringe": "^4.8.0" }, "devDependencies": { diff --git a/src/components/button/button-vm.ts b/src/app/components/button/button-vm.ts similarity index 100% rename from src/components/button/button-vm.ts rename to src/app/components/button/button-vm.ts diff --git a/src/components/button/button.tsx b/src/app/components/button/button.tsx similarity index 80% rename from src/components/button/button.tsx rename to src/app/components/button/button.tsx index 6b0452b..e1b8a4d 100644 --- a/src/components/button/button.tsx +++ b/src/app/components/button/button.tsx @@ -1,10 +1,12 @@ +"use client" import BaseView, { BuildProps } from "@/bootstrap/helpers/view/base-view"; -import ButtonVm from "@/components/button/button-vm"; +import ButtonVm from "@/app/components/button/button-vm"; import { ReactNode } from "react"; export default class Button extends BaseView<ButtonVm> { protected Build(props: BuildProps<ButtonVm>): ReactNode { const {vm} = props + return <button onClick={vm.onClick} >{vm.props.title}</button> } -} \ No newline at end of file +} diff --git a/src/app/globals.css b/src/app/globals.css index 6b717ad..942f871 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -2,20 +2,71 @@ @tailwind components; @tailwind utilities; -:root { - --background: #ffffff; - --foreground: #171717; +body { + font-family: Arial, Helvetica, sans-serif; } -@media (prefers-color-scheme: dark) { +@layer base { :root { - --background: #0a0a0a; - --foreground: #ededed; + --background: 0 0% 100%; + --foreground: 240 10% 3.9%; + --card: 0 0% 100%; + --card-foreground: 240 10% 3.9%; + --popover: 0 0% 100%; + --popover-foreground: 240 10% 3.9%; + --primary: 240 5.9% 10%; + --primary-foreground: 0 0% 98%; + --secondary: 240 4.8% 95.9%; + --secondary-foreground: 240 5.9% 10%; + --muted: 240 4.8% 95.9%; + --muted-foreground: 240 3.8% 46.1%; + --accent: 240 4.8% 95.9%; + --accent-foreground: 240 5.9% 10%; + --destructive: 0 84.2% 60.2%; + --destructive-foreground: 0 0% 98%; + --border: 240 5.9% 90%; + --input: 240 5.9% 90%; + --ring: 240 10% 3.9%; + --chart-1: 12 76% 61%; + --chart-2: 173 58% 39%; + --chart-3: 197 37% 24%; + --chart-4: 43 74% 66%; + --chart-5: 27 87% 67%; + --radius: 0.5rem; + } + .dark { + --background: 240 10% 3.9%; + --foreground: 0 0% 98%; + --card: 240 10% 3.9%; + --card-foreground: 0 0% 98%; + --popover: 240 10% 3.9%; + --popover-foreground: 0 0% 98%; + --primary: 0 0% 98%; + --primary-foreground: 240 5.9% 10%; + --secondary: 240 3.7% 15.9%; + --secondary-foreground: 0 0% 98%; + --muted: 240 3.7% 15.9%; + --muted-foreground: 240 5% 64.9%; + --accent: 240 3.7% 15.9%; + --accent-foreground: 0 0% 98%; + --destructive: 0 62.8% 30.6%; + --destructive-foreground: 0 0% 98%; + --border: 240 3.7% 15.9%; + --input: 240 3.7% 15.9%; + --ring: 240 4.9% 83.9%; + --chart-1: 220 70% 50%; + --chart-2: 160 60% 45%; + --chart-3: 30 80% 55%; + --chart-4: 280 65% 60%; + --chart-5: 340 75% 55%; } } -body { - color: var(--foreground); - background: var(--background); - font-family: Arial, Helvetica, sans-serif; +@layer base { + * { + @apply border-border; + } + body { + @apply bg-background text-foreground; + } } diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 1cd9211..ba8b4a7 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -1,4 +1,3 @@ -import "reflect-metadata" import type { Metadata } from "next"; import localFont from "next/font/local"; import "./globals.css"; diff --git a/src/app/test/client/view/parent-view.tsx b/src/app/test/client/view/parent-view.tsx new file mode 100644 index 0000000..81de26a --- /dev/null +++ b/src/app/test/client/view/parent-view.tsx @@ -0,0 +1,13 @@ +"use client" +import Button from "@/app/components/button/button" +import { TestButtonVM } from "@/app/test/client/vm/test-button-vm" +import { useDI } from "@/bootstrap/di/di-context" +import { useRef } from "react" + +export default function ParentView() { + const di = useDI() + + const vmRef = useRef(di.resolve(TestButtonVM)) + + return <Button vm={vmRef.current} /> +} \ No newline at end of file diff --git a/src/app/test/client/vm/test-button-vm.ts b/src/app/test/client/vm/test-button-vm.ts new file mode 100644 index 0000000..1a74c04 --- /dev/null +++ b/src/app/test/client/vm/test-button-vm.ts @@ -0,0 +1,34 @@ +"use client" +import BaseVM from "@/bootstrap/helpers/vm/base-vm"; +import ButtonVm from "@/app/components/button/button-vm"; +import { useEffect, useState } from "react"; +import getButtonTitle from "@/feature/domain/test/service/test-get-button-title-service"; + +export class TestButtonVM extends BaseVM<ButtonVm> { + private getButtonTitle: () => Promise<string> + + constructor() { + super() + this.getButtonTitle = this.di.resolve(getButtonTitle.name) + } + + useVM(): ButtonVm { + const [ buttonTitle, setTitle ] = useState("Default title") + useEffect(() => { + (async () => { + const title = await this.getButtonTitle() + setTitle(title) + })() + }, []) + return { + props: { + title: buttonTitle + }, + onClick: () => { + console.log("clicked on the button"); + } + } + } +} + +export const testKey = "testKey" \ No newline at end of file diff --git a/src/app/test/layout.tsx b/src/app/test/layout.tsx new file mode 100644 index 0000000..173e5ca --- /dev/null +++ b/src/app/test/layout.tsx @@ -0,0 +1,10 @@ +"use client" +import testAppModule from "@/app/test/modules/test-app-module"; +import { DiContext } from "@/bootstrap/di/di-context"; +import { PropsWithChildren, useRef } from "react"; + +export default function WithDILayout(props: PropsWithChildren) { + const testDi = useRef(testAppModule()) + return <DiContext.Provider value={testDi.current}>{props.children}</DiContext.Provider> +} + diff --git a/src/app/test/modules/test-app-module.ts b/src/app/test/modules/test-app-module.ts new file mode 100644 index 0000000..7f4d702 --- /dev/null +++ b/src/app/test/modules/test-app-module.ts @@ -0,0 +1,13 @@ +import { TestButtonVM, testKey } from "@/app/test/client/vm/test-button-vm"; +import di from "@/bootstrap/di/init-di" +import getButtonTitle from "@/feature/domain/test/service/test-get-button-title-service"; + +export default function testAppModule() { + const testDi = di.createChildContainer() + + testDi.registerInstance(testKey, TestButtonVM); + testDi.register(getButtonTitle.name, { + useValue: getButtonTitle + }) + return testDi +} diff --git a/src/app/test/page.tsx b/src/app/test/page.tsx index f08fc5e..fb067fd 100644 --- a/src/app/test/page.tsx +++ b/src/app/test/page.tsx @@ -1,8 +1,5 @@ -"use client" -import "reflect-metadata" -import TestButtonVM from "@/app/test/vm/test-button-vm"; -import Button from "@/components/button/button"; +import ParentView from "@/app/test/client/view/parent-view"; export default function Page() { - return <Button vmName={TestButtonVM.name} /> + return <ParentView /> } \ No newline at end of file diff --git a/src/app/test/vm/test-button-vm.ts b/src/app/test/vm/test-button-vm.ts deleted file mode 100644 index 414d5ce..0000000 --- a/src/app/test/vm/test-button-vm.ts +++ /dev/null @@ -1,17 +0,0 @@ -import BaseVM from "@/bootstrap/helpers/vm/base-vm"; -import injectableVm from "@/bootstrap/helpers/vm/vm-decorator"; -import ButtonVm from "@/components/button/button-vm"; - -@injectableVm() -export default class TestButtonVM extends BaseVM<ButtonVm> { - useVM(): ButtonVm { - return { - props: { - title: "Test Button" - }, - onClick: () => { - console.log("clicked on the button"); - } - } - } -} \ No newline at end of file diff --git a/src/bootstrap/di/di-context.tsx b/src/bootstrap/di/di-context.tsx new file mode 100644 index 0000000..2474156 --- /dev/null +++ b/src/bootstrap/di/di-context.tsx @@ -0,0 +1,21 @@ +"use client" +import di from "@/bootstrap/di/init-di"; +import { createContext, use } from "react"; +import { DependencyContainer } from "tsyringe"; + +const DiContext = createContext<null | DependencyContainer>(di) + +const useDI = () => { + const di = use(DiContext) + + if (!di) { + throw new Error("Di has not provided") + } + + return di +} + +export { + DiContext, + useDI, +} \ No newline at end of file diff --git a/src/bootstrap/di/init-di.ts b/src/bootstrap/di/init-di.ts index 79281ec..3ebdeef 100644 --- a/src/bootstrap/di/init-di.ts +++ b/src/bootstrap/di/init-di.ts @@ -1,5 +1,5 @@ +// "use client" import "reflect-metadata" - import { container, DependencyContainer } from "tsyringe"; /** @@ -8,7 +8,7 @@ import { container, DependencyContainer } from "tsyringe"; * are registered and available for injection throughout the application. */ const InitDI = (): DependencyContainer => { - const di = container; + const di = container.createChildContainer(); return di; }; diff --git a/src/bootstrap/helpers/view/base-view.tsx b/src/bootstrap/helpers/view/base-view.tsx index a7498cf..a1eecc7 100644 --- a/src/bootstrap/helpers/view/base-view.tsx +++ b/src/bootstrap/helpers/view/base-view.tsx @@ -1,17 +1,17 @@ "use client" +// import gdi from "@/bootstrap/di/init-di"; /* eslint-disable react/display-name */ /* eslint-disable @typescript-eslint/no-explicit-any */ /* eslint-disable react/jsx-props-no-spreading */ -import di from "@/bootstrap/di/init-di"; -import BaseVM from "@/bootstrap/helpers/vm/base-vm"; -import { Component, ReactNode, FC, PropsWithChildren, memo, MemoExoticComponent } from "react"; +import IBaseVM from "@/bootstrap/helpers/vm/i-base-vm"; +import { Component, ReactNode, FC, PropsWithChildren, memo } from "react"; /* -------------------------------------------------------------------------- */ /* Connector Component */ /* -------------------------------------------------------------------------- */ interface IVvmConnector<IVM, PROPS> extends PropsWithChildren { View: FC<any & { vm: IVM }>; - vmName: string; + Vm: IBaseVM<IVM>; restProps?: PROPS; memoizedByVM?: boolean; } @@ -21,11 +21,9 @@ interface IVvmConnector<IVM, PROPS> extends PropsWithChildren { */ const VvmConnector = memo( <IVM, PROPS>(props: IVvmConnector<IVM, PROPS>) => { - const { View, vmName, restProps, children } = props; - const VmInstance = di.resolve(vmName) as new () => BaseVM<IVM>; - if (!VmInstance) throw new Error(`Provided vm as ${vmName} is not exists`) + const { View, Vm, restProps, children } = props; - const vm = new VmInstance().useVM() + const vm = Vm.useVM() const allProps = { restProps, @@ -46,8 +44,8 @@ const VvmConnector = memo( type IVMParent = Record<string, any>; type IPropParent = Record<string, any> | undefined; -type BaseProps<PROPS extends IPropParent = undefined> = { - vmName: string; +type BaseProps<IVM extends IVMParent, PROPS extends IPropParent = undefined> = { + vm: IBaseVM<IVM>; restProps?: PROPS; /** * By default it's true. @@ -70,25 +68,23 @@ export type BuildProps< export default abstract class BaseView< IVM extends IVMParent, PROPS extends IPropParent = undefined, -> extends Component<BaseProps<PROPS>> { +> extends Component<BaseProps<IVM, PROPS>> { /* -------------------------------- Abstracts ------------------------------- */ protected abstract Build(props: BuildProps<IVM, PROPS>): ReactNode; /* -------------------------------- Renderer -------------------------------- */ render(): ReactNode { - const { vmName, restProps, memoizedByVM, children, ...rest } = this.props; + const { vm, restProps, memoizedByVM, children, ...rest } = this.props; - const Connector = VvmConnector as MemoExoticComponent<((props: IVvmConnector<IVM, PROPS>) => JSX.Element)>; - return ( - <Connector + <VvmConnector View={this.Build} - vmName={vmName} + Vm={vm} memoizedByVM={typeof memoizedByVM === "undefined" ? true : memoizedByVM} - restProps={{ ...restProps, ...rest } as PROPS} + restProps={{ ...restProps, ...rest }} > {children} - </Connector> + </VvmConnector> ); } /* -------------------------------------------------------------------------- */ diff --git a/src/bootstrap/helpers/vm/base-vm.ts b/src/bootstrap/helpers/vm/base-vm.ts index e82a80e..b9bb379 100644 --- a/src/bootstrap/helpers/vm/base-vm.ts +++ b/src/bootstrap/helpers/vm/base-vm.ts @@ -1,4 +1,5 @@ "use client" +import { useDI } from "@/bootstrap/di/di-context"; import { NoOverride } from "@/bootstrap/helpers/type-helper"; import IBaseVM from "@/bootstrap/helpers/vm/i-base-vm"; import { useState } from "react"; @@ -28,6 +29,10 @@ export default abstract class BaseVM< */ protected rerender?: () => void; + /* -------------------------------------------------------------------------- */ + protected get di() { + return useDI() + } /* -------------------------------------------------------------------------- */ /** * You can use this hook in your useVm method to get rerender method diff --git a/src/bootstrap/helpers/vm/vm-decorator.ts b/src/bootstrap/helpers/vm/vm-decorator.ts deleted file mode 100644 index 2092738..0000000 --- a/src/bootstrap/helpers/vm/vm-decorator.ts +++ /dev/null @@ -1,9 +0,0 @@ -"use client" -import di from "@/bootstrap/di/init-di"; -import IBaseVM from "@/bootstrap/helpers/vm/i-base-vm"; - -export default function injectableVm() { - return function (target: new (...args: unknown[]) => IBaseVM<object>) { - di.registerInstance(target.name, target); - }; -} \ No newline at end of file diff --git a/src/feature/common/server-di.ts b/src/feature/common/server-di.ts new file mode 100644 index 0000000..54200bd --- /dev/null +++ b/src/feature/common/server-di.ts @@ -0,0 +1,13 @@ +import { testModuleKey } from "@/feature/domain/test/test-module-key"; +import getTestModule from "@/feature/infra/test/module/test-module"; +import { DependencyContainer } from "tsyringe"; + +export default function serverDi(module: string): DependencyContainer { + const getDi = { + [testModuleKey]: getTestModule + }[module] + + if (!getDi) throw new Error("Server Di didn't found for module: " + module) + + return getDi() +} \ No newline at end of file diff --git a/src/feature/domain/test/service/test-get-button-title-service.ts b/src/feature/domain/test/service/test-get-button-title-service.ts new file mode 100644 index 0000000..c9a4910 --- /dev/null +++ b/src/feature/domain/test/service/test-get-button-title-service.ts @@ -0,0 +1,9 @@ +"use server" +import serverDi from "@/feature/common/server-di"; +import TestRepo, { testRepoKey } from "@/feature/domain/test/service/test-service-repo" +import { testModuleKey } from "@/feature/domain/test/test-module-key"; + +export default async function getButtonTitle() { + const repo = serverDi(testModuleKey).resolve<TestRepo>(testRepoKey) + return repo.getButtonTitle() +} diff --git a/src/feature/domain/test/service/test-service-repo.ts b/src/feature/domain/test/service/test-service-repo.ts new file mode 100644 index 0000000..91e00f8 --- /dev/null +++ b/src/feature/domain/test/service/test-service-repo.ts @@ -0,0 +1,5 @@ +export default interface TestRepo { + getButtonTitle(): Promise<string> +} + +export const testRepoKey = "restRepoKey" \ No newline at end of file diff --git a/src/feature/domain/test/test-module-key.ts b/src/feature/domain/test/test-module-key.ts new file mode 100644 index 0000000..abb15e6 --- /dev/null +++ b/src/feature/domain/test/test-module-key.ts @@ -0,0 +1 @@ +export const testModuleKey = "testModuleKey" \ No newline at end of file diff --git a/src/feature/infra/test/module/test-module.ts b/src/feature/infra/test/module/test-module.ts new file mode 100644 index 0000000..d8963b8 --- /dev/null +++ b/src/feature/infra/test/module/test-module.ts @@ -0,0 +1,12 @@ +import di from "@/bootstrap/di/init-di" +import { testRepoKey } from "@/feature/domain/test/service/test-service-repo" +import TestRepoImpl from "@/feature/infra/test/repo/test-repo-iml" + +export default function getTestModule() { + const testDi = di.createChildContainer() + + di.register(testRepoKey, { + useClass: TestRepoImpl + }) + return testDi +} \ No newline at end of file diff --git a/src/feature/infra/test/repo/test-repo-iml.ts b/src/feature/infra/test/repo/test-repo-iml.ts new file mode 100644 index 0000000..f519bee --- /dev/null +++ b/src/feature/infra/test/repo/test-repo-iml.ts @@ -0,0 +1,14 @@ +import TestRepo from "@/feature/domain/test/service/test-service-repo"; + +export default class TestRepoImpl implements TestRepo { + async getButtonTitle(): Promise<string> { + await new Promise((res) => { + setTimeout(() => { + res(true) + }, 3000) + }) + console.log('hereee'); + return Promise.resolve("Button title") + } + +} \ No newline at end of file diff --git a/src/lib/utils.ts b/src/lib/utils.ts new file mode 100644 index 0000000..bd0c391 --- /dev/null +++ b/src/lib/utils.ts @@ -0,0 +1,6 @@ +import { clsx, type ClassValue } from "clsx" +import { twMerge } from "tailwind-merge" + +export function cn(...inputs: ClassValue[]) { + return twMerge(clsx(inputs)) +} diff --git a/tailwind.config.ts b/tailwind.config.ts index 021c393..1f7474c 100644 --- a/tailwind.config.ts +++ b/tailwind.config.ts @@ -1,19 +1,64 @@ +/* eslint-disable @typescript-eslint/no-require-imports */ import type { Config } from "tailwindcss"; const config: Config = { - content: [ + darkMode: ["class"], + content: [ "./src/pages/**/*.{js,ts,jsx,tsx,mdx}", "./src/components/**/*.{js,ts,jsx,tsx,mdx}", "./src/app/**/*.{js,ts,jsx,tsx,mdx}", ], theme: { - extend: { - colors: { - background: "var(--background)", - foreground: "var(--foreground)", - }, - }, + extend: { + colors: { + background: 'hsl(var(--background))', + foreground: 'hsl(var(--foreground))', + card: { + DEFAULT: 'hsl(var(--card))', + foreground: 'hsl(var(--card-foreground))' + }, + popover: { + DEFAULT: 'hsl(var(--popover))', + foreground: 'hsl(var(--popover-foreground))' + }, + primary: { + DEFAULT: 'hsl(var(--primary))', + foreground: 'hsl(var(--primary-foreground))' + }, + secondary: { + DEFAULT: 'hsl(var(--secondary))', + foreground: 'hsl(var(--secondary-foreground))' + }, + muted: { + DEFAULT: 'hsl(var(--muted))', + foreground: 'hsl(var(--muted-foreground))' + }, + accent: { + DEFAULT: 'hsl(var(--accent))', + foreground: 'hsl(var(--accent-foreground))' + }, + destructive: { + DEFAULT: 'hsl(var(--destructive))', + foreground: 'hsl(var(--destructive-foreground))' + }, + border: 'hsl(var(--border))', + input: 'hsl(var(--input))', + ring: 'hsl(var(--ring))', + chart: { + '1': 'hsl(var(--chart-1))', + '2': 'hsl(var(--chart-2))', + '3': 'hsl(var(--chart-3))', + '4': 'hsl(var(--chart-4))', + '5': 'hsl(var(--chart-5))' + } + }, + borderRadius: { + lg: 'var(--radius)', + md: 'calc(var(--radius) - 2px)', + sm: 'calc(var(--radius) - 4px)' + } + } }, - plugins: [], + plugins: [require("tailwindcss-animate")], }; export default config; diff --git a/yarn.lock b/yarn.lock index 05b8294..c6c3ff2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -305,6 +305,11 @@ resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33" integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg== +"@radix-ui/react-icons@^1.3.1": + version "1.3.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-icons/-/react-icons-1.3.1.tgz#462c85fd726a77854cd5956e29eb19a575aa7ce5" + integrity sha512-QvYompk0X+8Yjlo/Fv4McrzxohDdM5GgLHyQcPpcsPvlOSXCGFjdbuyGL5dzRbg0GpknAjQJJZzdiRK7iWVuFQ== + "@rtsao/scc@^1.1.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@rtsao/scc/-/scc-1.1.0.tgz#927dd2fae9bc3361403ac2c7a00c32ddce9ad7e8" @@ -714,11 +719,28 @@ chokidar@^3.5.3: optionalDependencies: fsevents "~2.3.2" +class-variance-authority@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/class-variance-authority/-/class-variance-authority-0.7.0.tgz#1c3134d634d80271b1837452b06d821915954522" + integrity sha512-jFI8IQw4hczaL4ALINxqLEXQbWcNjoSkloa4IaufXCJr6QawJyw7tuRysRsrE8w2p/4gGaxKIt/hX3qz/IbD1A== + dependencies: + clsx "2.0.0" + client-only@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/client-only/-/client-only-0.0.1.tgz#38bba5d403c41ab150bff64a95c85013cf73bca1" integrity sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA== +clsx@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/clsx/-/clsx-2.0.0.tgz#12658f3fd98fafe62075595a5c30e43d18f3d00b" + integrity sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q== + +clsx@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/clsx/-/clsx-2.1.1.tgz#eed397c9fd8bd882bfb18deab7102049a2f32999" + integrity sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA== + color-convert@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" @@ -1871,6 +1893,11 @@ lru-cache@^10.2.0: resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.4.3.tgz#410fc8a17b70e598013df257c2446b7f3383f119" integrity sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ== +lucide-react@^0.454.0: + version "0.454.0" + resolved "https://registry.yarnpkg.com/lucide-react/-/lucide-react-0.454.0.tgz#a81b9c482018720f07ead0503ae502d94d528444" + integrity sha512-hw7zMDwykCLnEzgncEEjHeA6+45aeEzRYuKHuyRSOPkhko+J3ySGjGIzu+mmMfDFG1vazHepMaYFYHbTFAZAAQ== + merge2@^1.3.0: version "1.4.1" resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" @@ -2599,6 +2626,16 @@ supports-preserve-symlinks-flag@^1.0.0: resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== +tailwind-merge@^2.5.4: + version "2.5.4" + resolved "https://registry.yarnpkg.com/tailwind-merge/-/tailwind-merge-2.5.4.tgz#4bf574e81fa061adeceba099ae4df56edcee78d1" + integrity sha512-0q8cfZHMu9nuYP/b5Shb7Y7Sh1B7Nnl5GqNr1U+n2p6+mybvRtayrQ+0042Z5byvTA8ihjlP8Odo8/VnHbZu4Q== + +tailwindcss-animate@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/tailwindcss-animate/-/tailwindcss-animate-1.0.7.tgz#318b692c4c42676cc9e67b19b78775742388bef4" + integrity sha512-bl6mpH3T7I3UFxuvDEXLxy/VuFxBk5bbzplh7tXI68mwMokNYd1t9qPBHlnyTwfa4JGC4zP516I1hYYtQ/vspA== + tailwindcss@^3.4.1: version "3.4.14" resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-3.4.14.tgz#6dd23a7f54ec197b19159e91e3bb1e55e7aa73ac" -- 2.39.5 From 80e0d8ec5437d8caee53ac875cdcb8bc03863fd2 Mon Sep 17 00:00:00 2001 From: behnam <behnamrahimpour74@gmail.com> Date: Thu, 31 Oct 2024 19:09:19 +0300 Subject: [PATCH 03/37] Add base ui of dashboard --- public/file.svg | 2 +- public/globe.svg | 2 +- public/window.svg | 2 +- src/app/components/icons/document.tsx | 5 + src/app/components/icons/home.tsx | 5 + src/app/components/icons/user.tsx | 7 + src/app/components/skeleton/skeletons.tsx | 218 +++++++++++++++++++++ src/app/dashboard/(overview)/loading.tsx | 5 + src/app/dashboard/(overview)/page.tsx | 22 +++ src/app/dashboard/components/nav-links.tsx | 45 +++++ src/app/dashboard/components/sidenav.tsx | 21 ++ src/app/dashboard/layout.tsx | 13 ++ src/app/page.tsx | 106 ++-------- 13 files changed, 355 insertions(+), 98 deletions(-) create mode 100644 src/app/components/icons/document.tsx create mode 100644 src/app/components/icons/home.tsx create mode 100644 src/app/components/icons/user.tsx create mode 100644 src/app/components/skeleton/skeletons.tsx create mode 100644 src/app/dashboard/(overview)/loading.tsx create mode 100644 src/app/dashboard/(overview)/page.tsx create mode 100644 src/app/dashboard/components/nav-links.tsx create mode 100644 src/app/dashboard/components/sidenav.tsx create mode 100644 src/app/dashboard/layout.tsx diff --git a/public/file.svg b/public/file.svg index 004145c..adfd2a9 100644 --- a/public/file.svg +++ b/public/file.svg @@ -1 +1 @@ -<svg fill="none" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M14.5 13.5V5.41a1 1 0 0 0-.3-.7L9.8.29A1 1 0 0 0 9.08 0H1.5v13.5A2.5 2.5 0 0 0 4 16h8a2.5 2.5 0 0 0 2.5-2.5m-1.5 0v-7H8v-5H3v12a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1M9.5 5V2.12L12.38 5zM5.13 5h-.62v1.25h2.12V5zm-.62 3h7.12v1.25H4.5zm.62 3h-.62v1.25h7.12V11z" clip-rule="evenodd" fill="#666" fill-rule="evenodd"/></svg> \ No newline at end of file +<svg fill="none" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M14.5 13.5V5.41a1 1 0 0 0-.3-.7L9.8.29A1 1 0 0 0 9.08 0H1.5v13.5A2.5 2.5 0 0 0 4 16h8a2.5 2.5 0 0 0 2.5-2.5m-1.5 0v-7H8v-5H3v12a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1M9.5 5V2.12L12.38 5zM5.13 5h-.62v1.25h2.12V5zm-.62 3h7.12v1.25H4.5zm.62 3h-.62v1.25h7.12V11z" clipRule="evenodd" fill="#666" fillRule="evenodd"/></svg> \ No newline at end of file diff --git a/public/globe.svg b/public/globe.svg index 567f17b..4af126a 100644 --- a/public/globe.svg +++ b/public/globe.svg @@ -1 +1 @@ -<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><g clip-path="url(#a)"><path fill-rule="evenodd" clip-rule="evenodd" d="M10.27 14.1a6.5 6.5 0 0 0 3.67-3.45q-1.24.21-2.7.34-.31 1.83-.97 3.1M8 16A8 8 0 1 0 8 0a8 8 0 0 0 0 16m.48-1.52a7 7 0 0 1-.96 0H7.5a4 4 0 0 1-.84-1.32q-.38-.89-.63-2.08a40 40 0 0 0 3.92 0q-.25 1.2-.63 2.08a4 4 0 0 1-.84 1.31zm2.94-4.76q1.66-.15 2.95-.43a7 7 0 0 0 0-2.58q-1.3-.27-2.95-.43a18 18 0 0 1 0 3.44m-1.27-3.54a17 17 0 0 1 0 3.64 39 39 0 0 1-4.3 0 17 17 0 0 1 0-3.64 39 39 0 0 1 4.3 0m1.1-1.17q1.45.13 2.69.34a6.5 6.5 0 0 0-3.67-3.44q.65 1.26.98 3.1M8.48 1.5l.01.02q.41.37.84 1.31.38.89.63 2.08a40 40 0 0 0-3.92 0q.25-1.2.63-2.08a4 4 0 0 1 .85-1.32 7 7 0 0 1 .96 0m-2.75.4a6.5 6.5 0 0 0-3.67 3.44 29 29 0 0 1 2.7-.34q.31-1.83.97-3.1M4.58 6.28q-1.66.16-2.95.43a7 7 0 0 0 0 2.58q1.3.27 2.95.43a18 18 0 0 1 0-3.44m.17 4.71q-1.45-.12-2.69-.34a6.5 6.5 0 0 0 3.67 3.44q-.65-1.27-.98-3.1" fill="#666"/></g><defs><clipPath id="a"><path fill="#fff" d="M0 0h16v16H0z"/></clipPath></defs></svg> \ No newline at end of file +<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><g clip-path="url(#a)"><path fillRule="evenodd" clipRule="evenodd" d="M10.27 14.1a6.5 6.5 0 0 0 3.67-3.45q-1.24.21-2.7.34-.31 1.83-.97 3.1M8 16A8 8 0 1 0 8 0a8 8 0 0 0 0 16m.48-1.52a7 7 0 0 1-.96 0H7.5a4 4 0 0 1-.84-1.32q-.38-.89-.63-2.08a40 40 0 0 0 3.92 0q-.25 1.2-.63 2.08a4 4 0 0 1-.84 1.31zm2.94-4.76q1.66-.15 2.95-.43a7 7 0 0 0 0-2.58q-1.3-.27-2.95-.43a18 18 0 0 1 0 3.44m-1.27-3.54a17 17 0 0 1 0 3.64 39 39 0 0 1-4.3 0 17 17 0 0 1 0-3.64 39 39 0 0 1 4.3 0m1.1-1.17q1.45.13 2.69.34a6.5 6.5 0 0 0-3.67-3.44q.65 1.26.98 3.1M8.48 1.5l.01.02q.41.37.84 1.31.38.89.63 2.08a40 40 0 0 0-3.92 0q.25-1.2.63-2.08a4 4 0 0 1 .85-1.32 7 7 0 0 1 .96 0m-2.75.4a6.5 6.5 0 0 0-3.67 3.44 29 29 0 0 1 2.7-.34q.31-1.83.97-3.1M4.58 6.28q-1.66.16-2.95.43a7 7 0 0 0 0 2.58q1.3.27 2.95.43a18 18 0 0 1 0-3.44m.17 4.71q-1.45-.12-2.69-.34a6.5 6.5 0 0 0 3.67 3.44q-.65-1.27-.98-3.1" fill="#666"/></g><defs><clipPath id="a"><path fill="#fff" d="M0 0h16v16H0z"/></clipPath></defs></svg> \ No newline at end of file diff --git a/public/window.svg b/public/window.svg index b2b2a44..98febf2 100644 --- a/public/window.svg +++ b/public/window.svg @@ -1 +1 @@ -<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path fill-rule="evenodd" clip-rule="evenodd" d="M1.5 2.5h13v10a1 1 0 0 1-1 1h-11a1 1 0 0 1-1-1zM0 1h16v11.5a2.5 2.5 0 0 1-2.5 2.5h-11A2.5 2.5 0 0 1 0 12.5zm3.75 4.5a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5M7 4.75a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0m1.75.75a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5" fill="#666"/></svg> \ No newline at end of file +<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path fillRule="evenodd" clipRule="evenodd" d="M1.5 2.5h13v10a1 1 0 0 1-1 1h-11a1 1 0 0 1-1-1zM0 1h16v11.5a2.5 2.5 0 0 1-2.5 2.5h-11A2.5 2.5 0 0 1 0 12.5zm3.75 4.5a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5M7 4.75a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0m1.75.75a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5" fill="#666"/></svg> \ No newline at end of file diff --git a/src/app/components/icons/document.tsx b/src/app/components/icons/document.tsx new file mode 100644 index 0000000..a8cbcb6 --- /dev/null +++ b/src/app/components/icons/document.tsx @@ -0,0 +1,5 @@ +export function DocumentIcon(props: {className?: string}) { + return ( + <svg className={props.className} width="15" height="15" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M3 2.5C3 2.22386 3.22386 2 3.5 2H9.08579C9.21839 2 9.34557 2.05268 9.43934 2.14645L11.8536 4.56066C11.9473 4.65443 12 4.78161 12 4.91421V12.5C12 12.7761 11.7761 13 11.5 13H3.5C3.22386 13 3 12.7761 3 12.5V2.5ZM3.5 1C2.67157 1 2 1.67157 2 2.5V12.5C2 13.3284 2.67157 14 3.5 14H11.5C12.3284 14 13 13.3284 13 12.5V4.91421C13 4.51639 12.842 4.13486 12.5607 3.85355L10.1464 1.43934C9.86514 1.15804 9.48361 1 9.08579 1H3.5ZM4.5 4C4.22386 4 4 4.22386 4 4.5C4 4.77614 4.22386 5 4.5 5H7.5C7.77614 5 8 4.77614 8 4.5C8 4.22386 7.77614 4 7.5 4H4.5ZM4.5 7C4.22386 7 4 7.22386 4 7.5C4 7.77614 4.22386 8 4.5 8H10.5C10.7761 8 11 7.77614 11 7.5C11 7.22386 10.7761 7 10.5 7H4.5ZM4.5 10C4.22386 10 4 10.2239 4 10.5C4 10.7761 4.22386 11 4.5 11H10.5C10.7761 11 11 10.7761 11 10.5C11 10.2239 10.7761 10 10.5 10H4.5Z" fill="currentColor" fillRule="evenodd" clipRule="evenodd"></path></svg> + ) +} \ No newline at end of file diff --git a/src/app/components/icons/home.tsx b/src/app/components/icons/home.tsx new file mode 100644 index 0000000..8270d4e --- /dev/null +++ b/src/app/components/icons/home.tsx @@ -0,0 +1,5 @@ +export default function HomeIcon(props: {className?: string}) { + return ( + <svg className={props.className} width="15" height="15" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M7.07926 0.222253C7.31275 -0.007434 7.6873 -0.007434 7.92079 0.222253L14.6708 6.86227C14.907 7.09465 14.9101 7.47453 14.6778 7.71076C14.4454 7.947 14.0655 7.95012 13.8293 7.71773L13 6.90201V12.5C13 12.7761 12.7762 13 12.5 13H2.50002C2.22388 13 2.00002 12.7761 2.00002 12.5V6.90201L1.17079 7.71773C0.934558 7.95012 0.554672 7.947 0.32229 7.71076C0.0899079 7.47453 0.0930283 7.09465 0.32926 6.86227L7.07926 0.222253ZM7.50002 1.49163L12 5.91831V12H10V8.49999C10 8.22385 9.77617 7.99999 9.50002 7.99999H6.50002C6.22388 7.99999 6.00002 8.22385 6.00002 8.49999V12H3.00002V5.91831L7.50002 1.49163ZM7.00002 12H9.00002V8.99999H7.00002V12Z" fill="currentColor" fillRule="evenodd" clipRule="evenodd"></path></svg> + ) +} \ No newline at end of file diff --git a/src/app/components/icons/user.tsx b/src/app/components/icons/user.tsx new file mode 100644 index 0000000..02b56ed --- /dev/null +++ b/src/app/components/icons/user.tsx @@ -0,0 +1,7 @@ +export function UserIcon(props: {className?: string}) { + return ( + <svg className={props.className} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor"> + <path strokeLinecap="round" strokeLinejoin="round" d="M15.75 6a3.75 3.75 0 1 1-7.5 0 3.75 3.75 0 0 1 7.5 0ZM4.501 20.118a7.5 7.5 0 0 1 14.998 0A17.933 17.933 0 0 1 12 21.75c-2.676 0-5.216-.584-7.499-1.632Z" /> + </svg> + ) +} \ No newline at end of file diff --git a/src/app/components/skeleton/skeletons.tsx b/src/app/components/skeleton/skeletons.tsx new file mode 100644 index 0000000..52b8a87 --- /dev/null +++ b/src/app/components/skeleton/skeletons.tsx @@ -0,0 +1,218 @@ +// Loading animation +const shimmer = + 'before:absolute before:inset-0 before:-translate-x-full before:animate-[shimmer_2s_infinite] before:bg-gradient-to-r before:from-transparent before:via-white/60 before:to-transparent'; + +export function CardSkeleton() { + return ( + <div + className={`${shimmer} relative overflow-hidden rounded-xl bg-gray-100 p-2 shadow-sm`} + > + <div className="flex p-4"> + <div className="h-5 w-5 rounded-md bg-gray-200" /> + <div className="ml-2 h-6 w-16 rounded-md bg-gray-200 text-sm font-medium" /> + </div> + <div className="flex items-center justify-center truncate rounded-xl bg-white px-4 py-8"> + <div className="h-7 w-20 rounded-md bg-gray-200" /> + </div> + </div> + ); +} + +export function CardsSkeleton() { + return ( + <> + <CardSkeleton /> + <CardSkeleton /> + <CardSkeleton /> + <CardSkeleton /> + </> + ); +} + +export function RevenueChartSkeleton() { + return ( + <div className={`${shimmer} relative w-full overflow-hidden md:col-span-4`}> + <div className="mb-4 h-8 w-36 rounded-md bg-gray-100" /> + <div className="rounded-xl bg-gray-100 p-4"> + <div className="mt-0 grid h-[410px] grid-cols-12 items-end gap-2 rounded-md bg-white p-4 sm:grid-cols-13 md:gap-4" /> + <div className="flex items-center pb-2 pt-6"> + <div className="h-5 w-5 rounded-full bg-gray-200" /> + <div className="ml-2 h-4 w-20 rounded-md bg-gray-200" /> + </div> + </div> + </div> + ); +} + +export function InvoiceSkeleton() { + return ( + <div className="flex flex-row items-center justify-between border-b border-gray-100 py-4"> + <div className="flex items-center"> + <div className="mr-2 h-8 w-8 rounded-full bg-gray-200" /> + <div className="min-w-0"> + <div className="h-5 w-40 rounded-md bg-gray-200" /> + <div className="mt-2 h-4 w-12 rounded-md bg-gray-200" /> + </div> + </div> + <div className="mt-2 h-4 w-12 rounded-md bg-gray-200" /> + </div> + ); +} + +export function LatestInvoicesSkeleton() { + return ( + <div + className={`${shimmer} relative flex w-full flex-col overflow-hidden md:col-span-4`} + > + <div className="mb-4 h-8 w-36 rounded-md bg-gray-100" /> + <div className="flex grow flex-col justify-between rounded-xl bg-gray-100 p-4"> + <div className="bg-white px-6"> + <InvoiceSkeleton /> + <InvoiceSkeleton /> + <InvoiceSkeleton /> + <InvoiceSkeleton /> + <InvoiceSkeleton /> + <div className="flex items-center pb-2 pt-6"> + <div className="h-5 w-5 rounded-full bg-gray-200" /> + <div className="ml-2 h-4 w-20 rounded-md bg-gray-200" /> + </div> + </div> + </div> + </div> + ); +} + +export default function DashboardSkeleton() { + return ( + <> + <div + className={`${shimmer} relative mb-4 h-8 w-36 overflow-hidden rounded-md bg-gray-100`} + /> + <div className="grid gap-6 sm:grid-cols-2 lg:grid-cols-4"> + <CardSkeleton /> + <CardSkeleton /> + <CardSkeleton /> + <CardSkeleton /> + </div> + <div className="mt-6 grid grid-cols-1 gap-6 md:grid-cols-4 lg:grid-cols-8"> + <RevenueChartSkeleton /> + <LatestInvoicesSkeleton /> + </div> + </> + ); +} + +export function TableRowSkeleton() { + return ( + <tr className="w-full border-b border-gray-100 last-of-type:border-none [&:first-child>td:first-child]:rounded-tl-lg [&:first-child>td:last-child]:rounded-tr-lg [&:last-child>td:first-child]:rounded-bl-lg [&:last-child>td:last-child]:rounded-br-lg"> + {/* Customer Name and Image */} + <td className="relative overflow-hidden whitespace-nowrap py-3 pl-6 pr-3"> + <div className="flex items-center gap-3"> + <div className="h-8 w-8 rounded-full bg-gray-100"></div> + <div className="h-6 w-24 rounded bg-gray-100"></div> + </div> + </td> + {/* Email */} + <td className="whitespace-nowrap px-3 py-3"> + <div className="h-6 w-32 rounded bg-gray-100"></div> + </td> + {/* Amount */} + <td className="whitespace-nowrap px-3 py-3"> + <div className="h-6 w-16 rounded bg-gray-100"></div> + </td> + {/* Date */} + <td className="whitespace-nowrap px-3 py-3"> + <div className="h-6 w-16 rounded bg-gray-100"></div> + </td> + {/* Status */} + <td className="whitespace-nowrap px-3 py-3"> + <div className="h-6 w-16 rounded bg-gray-100"></div> + </td> + {/* Actions */} + <td className="whitespace-nowrap py-3 pl-6 pr-3"> + <div className="flex justify-end gap-3"> + <div className="h-[38px] w-[38px] rounded bg-gray-100"></div> + <div className="h-[38px] w-[38px] rounded bg-gray-100"></div> + </div> + </td> + </tr> + ); +} + +export function InvoicesMobileSkeleton() { + return ( + <div className="mb-2 w-full rounded-md bg-white p-4"> + <div className="flex items-center justify-between border-b border-gray-100 pb-8"> + <div className="flex items-center"> + <div className="mr-2 h-8 w-8 rounded-full bg-gray-100"></div> + <div className="h-6 w-16 rounded bg-gray-100"></div> + </div> + <div className="h-6 w-16 rounded bg-gray-100"></div> + </div> + <div className="flex w-full items-center justify-between pt-4"> + <div> + <div className="h-6 w-16 rounded bg-gray-100"></div> + <div className="mt-2 h-6 w-24 rounded bg-gray-100"></div> + </div> + <div className="flex justify-end gap-2"> + <div className="h-10 w-10 rounded bg-gray-100"></div> + <div className="h-10 w-10 rounded bg-gray-100"></div> + </div> + </div> + </div> + ); +} + +export function InvoicesTableSkeleton() { + return ( + <div className="mt-6 flow-root"> + <div className="inline-block min-w-full align-middle"> + <div className="rounded-lg bg-gray-50 p-2 md:pt-0"> + <div className="md:hidden"> + <InvoicesMobileSkeleton /> + <InvoicesMobileSkeleton /> + <InvoicesMobileSkeleton /> + <InvoicesMobileSkeleton /> + <InvoicesMobileSkeleton /> + <InvoicesMobileSkeleton /> + </div> + <table className="hidden min-w-full text-gray-900 md:table"> + <thead className="rounded-lg text-left text-sm font-normal"> + <tr> + <th scope="col" className="px-4 py-5 font-medium sm:pl-6"> + Customer + </th> + <th scope="col" className="px-3 py-5 font-medium"> + Email + </th> + <th scope="col" className="px-3 py-5 font-medium"> + Amount + </th> + <th scope="col" className="px-3 py-5 font-medium"> + Date + </th> + <th scope="col" className="px-3 py-5 font-medium"> + Status + </th> + <th + scope="col" + className="relative pb-4 pl-3 pr-6 pt-2 sm:pr-6" + > + <span className="sr-only">Edit</span> + </th> + </tr> + </thead> + <tbody className="bg-white"> + <TableRowSkeleton /> + <TableRowSkeleton /> + <TableRowSkeleton /> + <TableRowSkeleton /> + <TableRowSkeleton /> + <TableRowSkeleton /> + </tbody> + </table> + </div> + </div> + </div> + ); +} diff --git a/src/app/dashboard/(overview)/loading.tsx b/src/app/dashboard/(overview)/loading.tsx new file mode 100644 index 0000000..fcf5df1 --- /dev/null +++ b/src/app/dashboard/(overview)/loading.tsx @@ -0,0 +1,5 @@ +import DashboardSkeleton from "@/app/components/skeleton/skeletons"; + +export default function Loading() { + return <DashboardSkeleton />; +} \ No newline at end of file diff --git a/src/app/dashboard/(overview)/page.tsx b/src/app/dashboard/(overview)/page.tsx new file mode 100644 index 0000000..60a12e0 --- /dev/null +++ b/src/app/dashboard/(overview)/page.tsx @@ -0,0 +1,22 @@ + +export default async function Dashboard() { + + return ( + <main> + <h1 className={`mb-4 text-xl md:text-2xl`}> + Dashboard + </h1> + <div className="grid gap-6 sm:grid-cols-2 lg:grid-cols-4"> + {/* <CardWrapper /> */} + </div> + <div className="mt-6 grid grid-cols-1 gap-6 md:grid-cols-4 lg:grid-cols-8"> + {/* <Suspense fallback={<RevenueChartSkeleton />}> + <RevenueChart /> + </Suspense> */} + {/* <Suspense fallback={<LatestInvoicesSkeleton />}> + <LatestInvoices /> + </Suspense> */} + </div> + </main> + ) +} diff --git a/src/app/dashboard/components/nav-links.tsx b/src/app/dashboard/components/nav-links.tsx new file mode 100644 index 0000000..ecfca9e --- /dev/null +++ b/src/app/dashboard/components/nav-links.tsx @@ -0,0 +1,45 @@ +'use client' +import { DocumentIcon } from '@/app/components/icons/document'; +import HomeIcon from '@/app/components/icons/home'; +import { UserIcon } from '@/app/components/icons/user'; +import clsx from 'clsx'; +import Link from 'next/link' +import { usePathname } from 'next/navigation'; + +// Map of links to display in the side navigation. +// Depending on the size of the application, this would be stored in a database. +const links = [ + { name: 'Home', href: '/dashboard', icon: HomeIcon }, + { + name: 'Invoices', + href: '/dashboard/invoices', + icon: DocumentIcon, + }, + { name: 'Customers', href: '/dashboard/customers', icon: UserIcon }, +]; + +export default function NavLinks() { + const pathname = usePathname() + return ( + <> + {links.map((link) => { + const LinkIcon = link.icon; + return ( + <Link + key={link.name} + href={link.href} + className={clsx( + 'flex h-[48px] grow items-center justify-center gap-2 rounded-md bg-gray-50 p-3 text-sm font-medium hover:bg-sky-100 hover:text-blue-600 md:flex-none md:justify-start md:p-2 md:px-3', + { + 'bg-sky-100 text-blue-600': pathname === link.href, + }, + )} + > + <LinkIcon className="w-6" /> + <p className="hidden md:block">{link.name}</p> + </Link> + ); + })} + </> + ); +} diff --git a/src/app/dashboard/components/sidenav.tsx b/src/app/dashboard/components/sidenav.tsx new file mode 100644 index 0000000..7cf3d44 --- /dev/null +++ b/src/app/dashboard/components/sidenav.tsx @@ -0,0 +1,21 @@ +import NavLinks from '@/app/dashboard/components/nav-links'; +import Link from 'next/link'; + +export default function SideNav() { + return ( + <div className="flex h-full flex-col px-3 py-4 md:px-2"> + <Link + className="mb-2 flex h-20 items-end justify-start rounded-md bg-blue-600 p-4 md:h-40" + href="/" + > + <div className="w-32 text-white md:w-40"> + Home + </div> + </Link> + <div className="flex grow flex-row justify-between space-x-2 md:flex-col md:space-x-0 md:space-y-2"> + <NavLinks /> + <div className="hidden h-auto w-full grow rounded-md bg-gray-50 md:block"></div> + </div> + </div> + ); +} diff --git a/src/app/dashboard/layout.tsx b/src/app/dashboard/layout.tsx new file mode 100644 index 0000000..d28eae9 --- /dev/null +++ b/src/app/dashboard/layout.tsx @@ -0,0 +1,13 @@ +import SideNav from "@/app/dashboard/components/sidenav"; + + +export default function Layout({ children }: { children: React.ReactNode }) { + return ( + <div className="flex h-screen flex-col md:flex-row md:overflow-hidden"> + <div className="w-full flex-none md:w-64"> + <SideNav /> + </div> + <div className="flex-grow p-6 md:overflow-y-auto md:p-12">{children}</div> + </div> + ); +} \ No newline at end of file diff --git a/src/app/page.tsx b/src/app/page.tsx index 3eee014..b34fd95 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,101 +1,17 @@ -import Image from "next/image"; export default function Home() { return ( - <div className="grid grid-rows-[20px_1fr_20px] items-center justify-items-center min-h-screen p-8 pb-20 gap-16 sm:p-20 font-[family-name:var(--font-geist-sans)]"> - <main className="flex flex-col gap-8 row-start-2 items-center sm:items-start"> - <Image - className="dark:invert" - src="/next.svg" - alt="Next.js logo" - width={180} - height={38} - priority - /> - <ol className="list-inside list-decimal text-sm text-center sm:text-left font-[family-name:var(--font-geist-mono)]"> - <li className="mb-2"> - Get started by editing{" "} - <code className="bg-black/[.05] dark:bg-white/[.06] px-1 py-0.5 rounded font-semibold"> - src/app/page.tsx - </code> - . - </li> - <li>Save and see your changes instantly.</li> - </ol> - - <div className="flex gap-4 items-center flex-col sm:flex-row"> - <a - className="rounded-full border border-solid border-transparent transition-colors flex items-center justify-center bg-foreground text-background gap-2 hover:bg-[#383838] dark:hover:bg-[#ccc] text-sm sm:text-base h-10 sm:h-12 px-4 sm:px-5" - href="https://vercel.com/new?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app" - target="_blank" - rel="noopener noreferrer" - > - <Image - className="dark:invert" - src="/vercel.svg" - alt="Vercel logomark" - width={20} - height={20} - /> - Deploy now - </a> - <a - className="rounded-full border border-solid border-black/[.08] dark:border-white/[.145] transition-colors flex items-center justify-center hover:bg-[#f2f2f2] dark:hover:bg-[#1a1a1a] hover:border-transparent text-sm sm:text-base h-10 sm:h-12 px-4 sm:px-5 sm:min-w-44" - href="https://nextjs.org/docs?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app" - target="_blank" - rel="noopener noreferrer" - > - Read our docs - </a> + <main className="flex min-h-screen flex-col p-6"> + <div className="mt-4 flex grow flex-col gap-4 md:flex-row"> + <div className="flex flex-col justify-center gap-6 rounded-lg bg-gray-50 px-6 py-10 md:w-2/5 md:px-20"> + <div /> + <p className={`text-xl text-gray-800 md:text-3xl md:leading-normal`}> + <strong>Welcome to Acme.</strong> This is the example for the{' '} + + , brought to you by Vercel. + </p> </div> - </main> - <footer className="row-start-3 flex gap-6 flex-wrap items-center justify-center"> - <a - className="flex items-center gap-2 hover:underline hover:underline-offset-4" - href="https://nextjs.org/learn?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app" - target="_blank" - rel="noopener noreferrer" - > - <Image - aria-hidden - src="/file.svg" - alt="File icon" - width={16} - height={16} - /> - Learn - </a> - <a - className="flex items-center gap-2 hover:underline hover:underline-offset-4" - href="https://vercel.com/templates?framework=next.js&utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app" - target="_blank" - rel="noopener noreferrer" - > - <Image - aria-hidden - src="/window.svg" - alt="Window icon" - width={16} - height={16} - /> - Examples - </a> - <a - className="flex items-center gap-2 hover:underline hover:underline-offset-4" - href="https://nextjs.org?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app" - target="_blank" - rel="noopener noreferrer" - > - <Image - aria-hidden - src="/globe.svg" - alt="Globe icon" - width={16} - height={16} - /> - Go to nextjs.org → - </a> - </footer> - </div> + </div> + </main> ); } -- 2.39.5 From fa26fa6ad62ad839ca1efc88d45de0b29884ec41 Mon Sep 17 00:00:00 2001 From: behnam <behnamrahimpour74@gmail.com> Date: Thu, 31 Oct 2024 19:55:06 +0300 Subject: [PATCH 04/37] Add seed file --- package.json | 6 +- src/bootstrap/db/placeholder-data.js | 188 ++++++++++++++++++ src/bootstrap/db/seed.js | 188 ++++++++++++++++++ tsconfig.json | 2 +- yarn.lock | 273 +++++++++++++++++++++++++-- 5 files changed, 642 insertions(+), 15 deletions(-) create mode 100644 src/bootstrap/db/placeholder-data.js create mode 100644 src/bootstrap/db/seed.js diff --git a/package.json b/package.json index 95b1c2b..b9fb46b 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,8 @@ "dev": "next dev --turbopack", "build": "next build", "start": "next start --port 4000", - "lint": "next lint" + "lint": "next lint", + "seed": "node -r dotenv/config ./src/bootstrap/db/seed.js" }, "dependencies": { "@radix-ui/react-icons": "^1.3.1", @@ -14,6 +15,7 @@ "clsx": "^2.1.1", "lucide-react": "^0.454.0", "next": "15.0.1", + "postgres": "^3.4.5", "react": "19.0.0-rc-69d4b800-20241021", "react-dom": "19.0.0-rc-69d4b800-20241021", "reflect-metadata": "^0.2.2", @@ -25,6 +27,8 @@ "@types/node": "^20", "@types/react": "^18", "@types/react-dom": "^18", + "bcrypt": "^5.1.1", + "dotenv": "^16.4.5", "eslint": "^8", "eslint-config-next": "15.0.1", "postcss": "^8", diff --git a/src/bootstrap/db/placeholder-data.js b/src/bootstrap/db/placeholder-data.js new file mode 100644 index 0000000..15a4156 --- /dev/null +++ b/src/bootstrap/db/placeholder-data.js @@ -0,0 +1,188 @@ +// This file contains placeholder data that you'll be replacing with real data in the Data Fetching chapter: +// https://nextjs.org/learn/dashboard-app/fetching-data +const users = [ + { + id: '410544b2-4001-4271-9855-fec4b6a6442a', + name: 'User', + email: 'user@nextmail.com', + password: '123456', + }, +]; + +const customers = [ + { + id: '3958dc9e-712f-4377-85e9-fec4b6a6442a', + name: 'Delba de Oliveira', + email: 'delba@oliveira.com', + image_url: '/customers/delba-de-oliveira.png', + }, + { + id: '3958dc9e-742f-4377-85e9-fec4b6a6442a', + name: 'Lee Robinson', + email: 'lee@robinson.com', + image_url: '/customers/lee-robinson.png', + }, + { + id: '3958dc9e-737f-4377-85e9-fec4b6a6442a', + name: 'Hector Simpson', + email: 'hector@simpson.com', + image_url: '/customers/hector-simpson.png', + }, + { + id: '50ca3e18-62cd-11ee-8c99-0242ac120002', + name: 'Steven Tey', + email: 'steven@tey.com', + image_url: '/customers/steven-tey.png', + }, + { + id: '3958dc9e-787f-4377-85e9-fec4b6a6442a', + name: 'Steph Dietz', + email: 'steph@dietz.com', + image_url: '/customers/steph-dietz.png', + }, + { + id: '76d65c26-f784-44a2-ac19-586678f7c2f2', + name: 'Michael Novotny', + email: 'michael@novotny.com', + image_url: '/customers/michael-novotny.png', + }, + { + id: 'd6e15727-9fe1-4961-8c5b-ea44a9bd81aa', + name: 'Evil Rabbit', + email: 'evil@rabbit.com', + image_url: '/customers/evil-rabbit.png', + }, + { + id: '126eed9c-c90c-4ef6-a4a8-fcf7408d3c66', + name: 'Emil Kowalski', + email: 'emil@kowalski.com', + image_url: '/customers/emil-kowalski.png', + }, + { + id: 'CC27C14A-0ACF-4F4A-A6C9-D45682C144B9', + name: 'Amy Burns', + email: 'amy@burns.com', + image_url: '/customers/amy-burns.png', + }, + { + id: '13D07535-C59E-4157-A011-F8D2EF4E0CBB', + name: 'Balazs Orban', + email: 'balazs@orban.com', + image_url: '/customers/balazs-orban.png', + }, +]; + +const invoices = [ + { + customer_id: customers[0].id, + amount: 15795, + status: 'pending', + date: '2022-12-06', + }, + { + customer_id: customers[1].id, + amount: 20348, + status: 'pending', + date: '2022-11-14', + }, + { + customer_id: customers[4].id, + amount: 3040, + status: 'paid', + date: '2022-10-29', + }, + { + customer_id: customers[3].id, + amount: 44800, + status: 'paid', + date: '2023-09-10', + }, + { + customer_id: customers[5].id, + amount: 34577, + status: 'pending', + date: '2023-08-05', + }, + { + customer_id: customers[7].id, + amount: 54246, + status: 'pending', + date: '2023-07-16', + }, + { + customer_id: customers[6].id, + amount: 666, + status: 'pending', + date: '2023-06-27', + }, + { + customer_id: customers[3].id, + amount: 32545, + status: 'paid', + date: '2023-06-09', + }, + { + customer_id: customers[4].id, + amount: 1250, + status: 'paid', + date: '2023-06-17', + }, + { + customer_id: customers[5].id, + amount: 8546, + status: 'paid', + date: '2023-06-07', + }, + { + customer_id: customers[1].id, + amount: 500, + status: 'paid', + date: '2023-08-19', + }, + { + customer_id: customers[5].id, + amount: 8945, + status: 'paid', + date: '2023-06-03', + }, + { + customer_id: customers[2].id, + amount: 8945, + status: 'paid', + date: '2023-06-18', + }, + { + customer_id: customers[0].id, + amount: 8945, + status: 'paid', + date: '2023-10-04', + }, + { + customer_id: customers[2].id, + amount: 1000, + status: 'paid', + date: '2022-06-05', + }, +]; + +const revenue = [ + { month: 'Jan', revenue: 2000 }, + { month: 'Feb', revenue: 1800 }, + { month: 'Mar', revenue: 2200 }, + { month: 'Apr', revenue: 2500 }, + { month: 'May', revenue: 2300 }, + { month: 'Jun', revenue: 3200 }, + { month: 'Jul', revenue: 3500 }, + { month: 'Aug', revenue: 3700 }, + { month: 'Sep', revenue: 2500 }, + { month: 'Oct', revenue: 2800 }, + { month: 'Nov', revenue: 3000 }, + { month: 'Dec', revenue: 4800 }, +]; + +module.exports = { + users, + customers, + invoices, + revenue, +}; diff --git a/src/bootstrap/db/seed.js b/src/bootstrap/db/seed.js new file mode 100644 index 0000000..1b4273f --- /dev/null +++ b/src/bootstrap/db/seed.js @@ -0,0 +1,188 @@ +/* eslint-disable @typescript-eslint/no-require-imports */ +const { + invoices, + customers, + revenue, + users, +} = require('./placeholder-data.js'); +const bcrypt = require('bcrypt'); +const postgres = require('postgres'); + +async function seedUsers(sql) { + try { + await sql`CREATE EXTENSION IF NOT EXISTS "uuid-ossp"`; + // Create the "users" table if it doesn't exist + const createTable = await sql` + CREATE TABLE IF NOT EXISTS users ( + id UUID DEFAULT uuid_generate_v4() PRIMARY KEY, + name VARCHAR(255) NOT NULL, + email TEXT NOT NULL UNIQUE, + password TEXT NOT NULL + ); + `; + + console.log(`Created "users" table`); + + // Insert data into the "users" table + const insertedUsers = await Promise.all( + users.map(async (user) => { + const hashedPassword = await bcrypt.hash(user.password, 10); + return sql` + INSERT INTO users (id, name, email, password) + VALUES (${user.id}, ${user.name}, ${user.email}, ${hashedPassword}) + ON CONFLICT (id) DO NOTHING; + `; + }), + ); + + console.log(`Seeded ${insertedUsers.length} users`); + + return { + createTable, + users: insertedUsers, + }; + } catch (error) { + console.error('Error seeding users:', error); + throw error; + } +} + +async function seedInvoices(sql) { + try { + await sql`CREATE EXTENSION IF NOT EXISTS "uuid-ossp"`; + + // Create the "invoices" table if it doesn't exist + const createTable = await sql` + CREATE TABLE IF NOT EXISTS invoices ( + id UUID DEFAULT uuid_generate_v4() PRIMARY KEY, + customer_id UUID NOT NULL, + amount INT NOT NULL, + status VARCHAR(255) NOT NULL, + date DATE NOT NULL + ); +`; + + console.log(`Created "invoices" table`); + + // Insert data into the "invoices" table + const insertedInvoices = await Promise.all( + invoices.map( + (invoice) => sql` + INSERT INTO invoices (customer_id, amount, status, date) + VALUES (${invoice.customer_id}, ${invoice.amount}, ${invoice.status}, ${invoice.date}) + ON CONFLICT (id) DO NOTHING; + `, + ), + ); + + console.log(`Seeded ${insertedInvoices.length} invoices`); + + return { + createTable, + invoices: insertedInvoices, + }; + } catch (error) { + console.error('Error seeding invoices:', error); + throw error; + } +} + +async function seedCustomers(sql) { + try { + await sql`CREATE EXTENSION IF NOT EXISTS "uuid-ossp"`; + + // Create the "customers" table if it doesn't exist + const createTable = await sql` + CREATE TABLE IF NOT EXISTS customers ( + id UUID DEFAULT uuid_generate_v4() PRIMARY KEY, + name VARCHAR(255) NOT NULL, + email VARCHAR(255) NOT NULL, + image_url VARCHAR(255) NOT NULL + ); + `; + + console.log(`Created "customers" table`); + + // Insert data into the "customers" table + const insertedCustomers = await Promise.all( + customers.map( + (customer) => sql` + INSERT INTO customers (id, name, email, image_url) + VALUES (${customer.id}, ${customer.name}, ${customer.email}, ${customer.image_url}) + ON CONFLICT (id) DO NOTHING; + `, + ), + ); + + console.log(`Seeded ${insertedCustomers.length} customers`); + + return { + createTable, + customers: insertedCustomers, + }; + } catch (error) { + console.error('Error seeding customers:', error); + throw error; + } +} + +async function seedRevenue(sql) { + try { + // Create the "revenue" table if it doesn't exist + const createTable = await sql` + CREATE TABLE IF NOT EXISTS revenue ( + month VARCHAR(4) NOT NULL UNIQUE, + revenue INT NOT NULL + ); + `; + + console.log(`Created "revenue" table`); + + // Insert data into the "revenue" table + const insertedRevenue = await Promise.all( + revenue.map( + (rev) => sql` + INSERT INTO revenue (month, revenue) + VALUES (${rev.month}, ${rev.revenue}) + ON CONFLICT (month) DO NOTHING; + `, + ), + ); + + console.log(`Seeded ${insertedRevenue.length} revenue`); + + return { + createTable, + revenue: insertedRevenue, + }; + } catch (error) { + console.error('Error seeding revenue:', error); + throw error; + } +} + +async function main() { + const envs = process.env; + const dbConfigs = { + host: process.env.POSTGRES_HOST, + port: envs.POSTGRES_PORT, + username: envs.POSTGRES_USER, + password: envs.POSTGRES_PASS, + database: envs.POSTGRES_DB, + } + + const sql = postgres(dbConfigs); + + await seedUsers(sql); + await seedCustomers(sql); + await seedInvoices(sql); + await seedRevenue(sql); + +} + +main().catch((err) => { + console.error( + 'An error occurred while attempting to seed the database:', + err, + ); +}); diff --git a/tsconfig.json b/tsconfig.json index 714376b..d42c189 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -24,6 +24,6 @@ "@/*": ["./src/*"] } }, - "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], + "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts", "src/bootstrap/db/seed.js", "src/bootstrap/db/placeholder-data.js"], "exclude": ["node_modules"] } diff --git a/yarn.lock b/yarn.lock index c6c3ff2..9b2101a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -222,6 +222,21 @@ "@jridgewell/resolve-uri" "^3.1.0" "@jridgewell/sourcemap-codec" "^1.4.14" +"@mapbox/node-pre-gyp@^1.0.11": + version "1.0.11" + resolved "https://registry.yarnpkg.com/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz#417db42b7f5323d79e93b34a6d7a2a12c0df43fa" + integrity sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ== + dependencies: + detect-libc "^2.0.0" + https-proxy-agent "^5.0.0" + make-dir "^3.1.0" + node-fetch "^2.6.7" + nopt "^5.0.0" + npmlog "^5.0.1" + rimraf "^3.0.2" + semver "^7.3.5" + tar "^6.1.11" + "@next/env@15.0.1": version "15.0.1" resolved "https://registry.yarnpkg.com/@next/env/-/env-15.0.1.tgz#660fe9303e255cec112d3f4198d2897a24bc60b3" @@ -450,6 +465,11 @@ resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.2.0.tgz#756641adb587851b5ccb3e095daf27ae581c8406" integrity sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ== +abbrev@1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" + integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== + acorn-jsx@^5.3.2: version "5.3.2" resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" @@ -460,6 +480,13 @@ acorn@^8.9.0: resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.14.0.tgz#063e2c70cac5fb4f6467f0b11152e04c682795b0" integrity sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA== +agent-base@6: + version "6.0.2" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" + integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ== + dependencies: + debug "4" + ajv@^6.12.4: version "6.12.6" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" @@ -505,6 +532,19 @@ anymatch@~3.1.2: normalize-path "^3.0.0" picomatch "^2.0.4" +"aproba@^1.0.3 || ^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/aproba/-/aproba-2.0.0.tgz#52520b8ae5b569215b354efc0caa3fe1e45a8adc" + integrity sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ== + +are-we-there-yet@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz#372e0e7bd279d8e94c653aaa1f67200884bf3e1c" + integrity sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw== + dependencies: + delegates "^1.0.0" + readable-stream "^3.6.0" + arg@^5.0.2: version "5.0.2" resolved "https://registry.yarnpkg.com/arg/-/arg-5.0.2.tgz#c81433cc427c92c4dcf4865142dbca6f15acd59c" @@ -636,6 +676,14 @@ balanced-match@^1.0.0: resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== +bcrypt@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/bcrypt/-/bcrypt-5.1.1.tgz#0f732c6dcb4e12e5b70a25e326a72965879ba6e2" + integrity sha512-AGBHOG5hPYZ5Xl9KXzU5iKq9516yEmvCKDg3ecP5kX2aB6UqTeXZxk2ELnDgDm6BQSMlLt9rDB4LoSMx0rYwww== + dependencies: + "@mapbox/node-pre-gyp" "^1.0.11" + node-addon-api "^5.0.0" + binary-extensions@^2.0.0: version "2.3.0" resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.3.0.tgz#f6e14a97858d327252200242d4ccfe522c445522" @@ -719,6 +767,11 @@ chokidar@^3.5.3: optionalDependencies: fsevents "~2.3.2" +chownr@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece" + integrity sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ== + class-variance-authority@^0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/class-variance-authority/-/class-variance-authority-0.7.0.tgz#1c3134d634d80271b1837452b06d821915954522" @@ -761,6 +814,11 @@ color-string@^1.9.0: color-name "^1.0.0" simple-swizzle "^0.2.2" +color-support@^1.1.2: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-support/-/color-support-1.1.3.tgz#93834379a1cc9a0c61f82f52f0d04322251bd5a2" + integrity sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg== + color@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/color/-/color-4.2.3.tgz#d781ecb5e57224ee43ea9627560107c0e0c6463a" @@ -779,6 +837,11 @@ concat-map@0.0.1: resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== +console-control-strings@^1.0.0, console-control-strings@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" + integrity sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ== + cross-spawn@^7.0.0, cross-spawn@^7.0.2: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" @@ -830,6 +893,13 @@ data-view-byte-offset@^1.0.0: es-errors "^1.3.0" is-data-view "^1.0.1" +debug@4, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4, debug@^4.3.5: + version "4.3.7" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.7.tgz#87945b4151a011d76d95a198d7111c865c360a52" + integrity sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ== + dependencies: + ms "^2.1.3" + debug@^3.2.7: version "3.2.7" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" @@ -837,13 +907,6 @@ debug@^3.2.7: dependencies: ms "^2.1.1" -debug@^4.3.1, debug@^4.3.2, debug@^4.3.4, debug@^4.3.5: - version "4.3.7" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.7.tgz#87945b4151a011d76d95a198d7111c865c360a52" - integrity sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ== - dependencies: - ms "^2.1.3" - deep-is@^0.1.3: version "0.1.4" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" @@ -867,7 +930,12 @@ define-properties@^1.1.3, define-properties@^1.2.0, define-properties@^1.2.1: has-property-descriptors "^1.0.0" object-keys "^1.1.1" -detect-libc@^2.0.3: +delegates@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" + integrity sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ== + +detect-libc@^2.0.0, detect-libc@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-2.0.3.tgz#f0cd503b40f9939b894697d19ad50895e30cf700" integrity sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw== @@ -896,6 +964,11 @@ doctrine@^3.0.0: dependencies: esutils "^2.0.2" +dotenv@^16.4.5: + version "16.4.5" + resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.4.5.tgz#cdd3b3b604cb327e286b4762e13502f717cb099f" + integrity sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg== + eastasianwidth@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" @@ -1346,6 +1419,13 @@ foreground-child@^3.1.0: cross-spawn "^7.0.0" signal-exit "^4.0.1" +fs-minipass@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb" + integrity sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg== + dependencies: + minipass "^3.0.0" + fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" @@ -1376,6 +1456,21 @@ functions-have-names@^1.2.3: resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834" integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ== +gauge@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/gauge/-/gauge-3.0.2.tgz#03bf4441c044383908bcfa0656ad91803259b395" + integrity sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q== + dependencies: + aproba "^1.0.3 || ^2.0.0" + color-support "^1.1.2" + console-control-strings "^1.0.0" + has-unicode "^2.0.1" + object-assign "^4.1.1" + signal-exit "^3.0.0" + string-width "^4.2.3" + strip-ansi "^6.0.1" + wide-align "^1.1.2" + get-intrinsic@^1.1.3, get-intrinsic@^1.2.1, get-intrinsic@^1.2.3, get-intrinsic@^1.2.4: version "1.2.4" resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.4.tgz#e385f5a4b5227d449c3eabbad05494ef0abbeadd" @@ -1507,6 +1602,11 @@ has-tostringtag@^1.0.0, has-tostringtag@^1.0.2: dependencies: has-symbols "^1.0.3" +has-unicode@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" + integrity sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ== + hasown@^2.0.0, hasown@^2.0.1, hasown@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" @@ -1514,6 +1614,14 @@ hasown@^2.0.0, hasown@^2.0.1, hasown@^2.0.2: dependencies: function-bind "^1.1.2" +https-proxy-agent@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6" + integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA== + dependencies: + agent-base "6" + debug "4" + ignore@^5.2.0, ignore@^5.3.1: version "5.3.2" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.2.tgz#3cd40e729f3643fd87cb04e50bf0eb722bc596f5" @@ -1540,7 +1648,7 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2: +inherits@2, inherits@^2.0.3: version "2.0.4" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== @@ -1898,6 +2006,13 @@ lucide-react@^0.454.0: resolved "https://registry.yarnpkg.com/lucide-react/-/lucide-react-0.454.0.tgz#a81b9c482018720f07ead0503ae502d94d528444" integrity sha512-hw7zMDwykCLnEzgncEEjHeA6+45aeEzRYuKHuyRSOPkhko+J3ySGjGIzu+mmMfDFG1vazHepMaYFYHbTFAZAAQ== +make-dir@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" + integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== + dependencies: + semver "^6.0.0" + merge2@^1.3.0: version "1.4.1" resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" @@ -1930,11 +2045,36 @@ minimist@^1.2.0, minimist@^1.2.6: resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== +minipass@^3.0.0: + version "3.3.6" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.3.6.tgz#7bba384db3a1520d18c9c0e5251c3444e95dd94a" + integrity sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw== + dependencies: + yallist "^4.0.0" + +minipass@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-5.0.0.tgz#3e9788ffb90b694a5d0ec94479a45b5d8738133d" + integrity sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ== + "minipass@^5.0.0 || ^6.0.2 || ^7.0.0", minipass@^7.1.2: version "7.1.2" resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.1.2.tgz#93a9626ce5e5e66bd4db86849e7515e92340a707" integrity sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw== +minizlib@^2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.2.tgz#e90d3466ba209b932451508a11ce3d3632145931" + integrity sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg== + dependencies: + minipass "^3.0.0" + yallist "^4.0.0" + +mkdirp@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" + integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== + ms@^2.1.1, ms@^2.1.3: version "2.1.3" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" @@ -1982,11 +2122,40 @@ next@15.0.1: "@next/swc-win32-x64-msvc" "15.0.1" sharp "^0.33.5" +node-addon-api@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-5.1.0.tgz#49da1ca055e109a23d537e9de43c09cca21eb762" + integrity sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA== + +node-fetch@^2.6.7: + version "2.7.0" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" + integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== + dependencies: + whatwg-url "^5.0.0" + +nopt@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-5.0.0.tgz#530942bb58a512fccafe53fe210f13a25355dc88" + integrity sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ== + dependencies: + abbrev "1" + normalize-path@^3.0.0, normalize-path@~3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== +npmlog@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-5.0.1.tgz#f06678e80e29419ad67ab964e0fa69959c1eb8b0" + integrity sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw== + dependencies: + are-we-there-yet "^2.0.0" + console-control-strings "^1.1.0" + gauge "^3.0.0" + set-blocking "^2.0.0" + object-assign@^4.0.1, object-assign@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" @@ -2214,6 +2383,11 @@ postcss@^8, postcss@^8.4.23: picocolors "^1.1.0" source-map-js "^1.2.1" +postgres@^3.4.5: + version "3.4.5" + resolved "https://registry.yarnpkg.com/postgres/-/postgres-3.4.5.tgz#1ef99e51b0ba9b53cbda8a215dd406725f7d15f9" + integrity sha512-cDWgoah1Gez9rN3H4165peY9qfpEo+SA61oQv65O3cRUE1pOEoJWwddwcqKE8XZYjbblOJlYDlLV4h67HrEVDg== + prelude-ls@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" @@ -2262,6 +2436,15 @@ read-cache@^1.0.0: dependencies: pify "^2.3.0" +readable-stream@^3.6.0: + version "3.6.2" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" + integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + readdirp@~3.6.0: version "3.6.0" resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" @@ -2354,6 +2537,11 @@ safe-array-concat@^1.1.2: has-symbols "^1.0.3" isarray "^2.0.5" +safe-buffer@~5.2.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + safe-regex-test@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/safe-regex-test/-/safe-regex-test-1.0.3.tgz#a5b4c0f06e0ab50ea2c395c14d8371232924c377" @@ -2368,16 +2556,21 @@ scheduler@0.25.0-rc-69d4b800-20241021: resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.25.0-rc-69d4b800-20241021.tgz#336e47ef2bd5eddb0ebacfd910b5df1b236d92bd" integrity sha512-S5AYX/YhMAN6u9AXgKYbZP4U4ZklC6R9Q7HmFSBk7d4DLiHVNxvAvlSvuM4nxFkwOk50MnpfTKQ7UWHXDOc9Eg== -semver@^6.3.1: +semver@^6.0.0, semver@^6.3.1: version "6.3.1" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== -semver@^7.6.0, semver@^7.6.3: +semver@^7.3.5, semver@^7.6.0, semver@^7.6.3: version "7.6.3" resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.3.tgz#980f7b5550bc175fb4dc09403085627f9eb33143" integrity sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A== +set-blocking@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw== + set-function-length@^1.2.1: version "1.2.2" resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.2.tgz#aac72314198eaed975cf77b2c3b6b880695e5449" @@ -2451,6 +2644,11 @@ side-channel@^1.0.4, side-channel@^1.0.6: get-intrinsic "^1.2.4" object-inspect "^1.13.1" +signal-exit@^3.0.0: + version "3.0.7" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" + integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== + signal-exit@^4.0.1: version "4.1.0" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04" @@ -2482,7 +2680,7 @@ streamsearch@^1.1.0: is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.1" -string-width@^4.1.0: +"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -2563,6 +2761,13 @@ string.prototype.trimstart@^1.0.8: define-properties "^1.2.1" es-object-atoms "^1.0.0" +string_decoder@^1.1.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" + integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== + dependencies: + safe-buffer "~5.2.0" + "strip-ansi-cjs@npm:strip-ansi@^6.0.1": version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" @@ -2669,6 +2874,18 @@ tapable@^2.2.0: resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== +tar@^6.1.11: + version "6.2.1" + resolved "https://registry.yarnpkg.com/tar/-/tar-6.2.1.tgz#717549c541bc3c2af15751bea94b1dd068d4b03a" + integrity sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A== + dependencies: + chownr "^2.0.0" + fs-minipass "^2.0.0" + minipass "^5.0.0" + minizlib "^2.1.1" + mkdirp "^1.0.3" + yallist "^4.0.0" + text-table@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" @@ -2695,6 +2912,11 @@ to-regex-range@^5.0.1: dependencies: is-number "^7.0.0" +tr46@~0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" + integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== + ts-api-utils@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.3.0.tgz#4b490e27129f1e8e686b45cc4ab63714dc60eea1" @@ -2815,11 +3037,24 @@ uri-js@^4.2.2: dependencies: punycode "^2.1.0" -util-deprecate@^1.0.2: +util-deprecate@^1.0.1, util-deprecate@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== +webidl-conversions@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" + integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== + +whatwg-url@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" + integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== + dependencies: + tr46 "~0.0.3" + webidl-conversions "^3.0.0" + which-boxed-primitive@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6" @@ -2877,6 +3112,13 @@ which@^2.0.1: dependencies: isexe "^2.0.0" +wide-align@^1.1.2: + version "1.1.5" + resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.5.tgz#df1d4c206854369ecf3c9a4898f1b23fbd9d15d3" + integrity sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg== + dependencies: + string-width "^1.0.2 || 2 || 3 || 4" + word-wrap@^1.2.5: version "1.2.5" resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.5.tgz#d2c45c6dd4fbce621a66f136cbe328afd0410b34" @@ -2905,6 +3147,11 @@ wrappy@1: resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== +yallist@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== + yaml@^2.3.4: version "2.6.0" resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.6.0.tgz#14059ad9d0b1680d0f04d3a60fe00f3a857303c3" -- 2.39.5 From 3cfc073dd8163fed1c330f91272abe7bb5babbc6 Mon Sep 17 00:00:00 2001 From: behnam <behnamrahimpour74@gmail.com> Date: Thu, 31 Oct 2024 20:40:39 +0300 Subject: [PATCH 05/37] Add base of dashboard logics --- package.json | 4 +- public/customers/amy-burns.png | Bin 0 -> 7954 bytes public/customers/balazs-orban.png | Bin 0 -> 7951 bytes public/customers/delba-de-oliveira.png | Bin 0 -> 5824 bytes public/customers/emil-kowalski.png | Bin 0 -> 4141 bytes public/customers/evil-rabbit.png | Bin 0 -> 1019 bytes public/customers/guillermo-rauch.png | Bin 0 -> 6284 bytes public/customers/hector-simpson.png | Bin 0 -> 5602 bytes public/customers/jared-palmer.png | Bin 0 -> 6460 bytes public/customers/lee-robinson.png | Bin 0 -> 5653 bytes public/customers/michael-novotny.png | Bin 0 -> 9902 bytes public/customers/steph-dietz.png | Bin 0 -> 7151 bytes public/customers/steven-tey.png | Bin 0 -> 7345 bytes src/app/dashboard/(overview)/page.tsx | 15 +- src/app/dashboard/components/cards.tsx | 62 +++++ .../dashboard/components/latest-invoices.tsx | 60 +++++ .../dashboard/components/revenue-chart.tsx | 53 ++++ src/app/lib/actions.ts | 117 ++++++++ src/app/lib/data.ts | 254 ++++++++++++++++++ src/app/lib/definitions.ts | 86 ++++++ src/app/lib/placeholder-data.js | 188 +++++++++++++ src/app/lib/utils.ts | 69 +++++ src/bootstrap/db/db.ts | 13 + yarn.lock | 10 + 24 files changed, 925 insertions(+), 6 deletions(-) create mode 100644 public/customers/amy-burns.png create mode 100644 public/customers/balazs-orban.png create mode 100644 public/customers/delba-de-oliveira.png create mode 100644 public/customers/emil-kowalski.png create mode 100644 public/customers/evil-rabbit.png create mode 100644 public/customers/guillermo-rauch.png create mode 100644 public/customers/hector-simpson.png create mode 100644 public/customers/jared-palmer.png create mode 100644 public/customers/lee-robinson.png create mode 100644 public/customers/michael-novotny.png create mode 100644 public/customers/steph-dietz.png create mode 100644 public/customers/steven-tey.png create mode 100644 src/app/dashboard/components/cards.tsx create mode 100644 src/app/dashboard/components/latest-invoices.tsx create mode 100644 src/app/dashboard/components/revenue-chart.tsx create mode 100644 src/app/lib/actions.ts create mode 100644 src/app/lib/data.ts create mode 100644 src/app/lib/definitions.ts create mode 100644 src/app/lib/placeholder-data.js create mode 100644 src/app/lib/utils.ts create mode 100644 src/bootstrap/db/db.ts diff --git a/package.json b/package.json index b9fb46b..0cd01c1 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ "seed": "node -r dotenv/config ./src/bootstrap/db/seed.js" }, "dependencies": { + "@heroicons/react": "^2.1.5", "@radix-ui/react-icons": "^1.3.1", "class-variance-authority": "^0.7.0", "clsx": "^2.1.1", @@ -21,7 +22,8 @@ "reflect-metadata": "^0.2.2", "tailwind-merge": "^2.5.4", "tailwindcss-animate": "^1.0.7", - "tsyringe": "^4.8.0" + "tsyringe": "^4.8.0", + "zod": "^3.23.8" }, "devDependencies": { "@types/node": "^20", diff --git a/public/customers/amy-burns.png b/public/customers/amy-burns.png new file mode 100644 index 0000000000000000000000000000000000000000..7b29d72526a0644b11519442aac7d6d95f305702 GIT binary patch literal 7954 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 IM6N<$f~UlBhyVZp literal 0 HcmV?d00001 diff --git a/public/customers/balazs-orban.png b/public/customers/balazs-orban.png new file mode 100644 index 0000000000000000000000000000000000000000..7fbc0097b82ad2d27141447a4ca5ef1ec68f08cf GIT binary patch literal 7951 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 FV1nZ*du;#! literal 0 HcmV?d00001 diff --git a/public/customers/delba-de-oliveira.png b/public/customers/delba-de-oliveira.png new file mode 100644 index 0000000000000000000000000000000000000000..08db1b8e854c6e3d83f431518aa8a3d2b5c250c1 GIT binary patch literal 5824 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 KMNUMnLSTaFb|M-8 literal 0 HcmV?d00001 diff --git a/public/customers/emil-kowalski.png b/public/customers/emil-kowalski.png new file mode 100644 index 0000000000000000000000000000000000000000..8411e219dcd6484e52f53036066be7bd14995fab GIT binary patch literal 4141 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 literal 0 HcmV?d00001 diff --git a/public/customers/evil-rabbit.png b/public/customers/evil-rabbit.png new file mode 100644 index 0000000000000000000000000000000000000000..fe7990ff2f533d3d053a97f631800721e1dc64b6 GIT binary patch literal 1019 zcmV<X0|fkuP)<h;3K|Lk000e1NJLTq001}u001}$1^@s6sD?Wp00009a7bBm000XU z000XU0RWnu7ytkO0drDELIAGL9O(c600d`2O+f$vv5yP<VFdsH1CU8XK~#7F?V8Oi zd{G$3pYam%E+r{18!zQ`gRrnrO6>drWGhjmY*<)WP?D8cpp>$}N@78>@>a@1@{+fb zmz2#k(>%X(ZjFBPa<94fe(&h&e(G%Q%z4i9Ip^GS&zw6hB4YZ(#Lyqd5wtswpxto< z?T#bpr@p?P%FD~?w`pl<q2l6VU3EB;vbea&lD@t^j<gQCjE#*cISdXC>Zupm7yJAB z+0W?cXjH}0)6;o=e*U}trluymU~O$J|Iggq9A{@|TP~NCmBojLhXHNp<mBK5lai7+ zn1h1@&dbZQOs=r7kS{MU1KNCieAF8!@-NHa!Q9;3D2bruDk>`Y{{B9sy^W0x>jYO; zRyZ8j*Vj<Vva&LMdwUDp*3i(9b%Fx}1FXi$$%!(J&C1D+lCwgM=H_PW1gop7S&Ox` zHPeE-yStig6ciL#Cn(GL`MG8S?d|P`<+{4MG-EF<Eg6ZcuR>c}n`RP6M@O8ToUA*M z+}vEvsVS+csj*&Ami6^@%|u2<Ms&wqSXj`EIW;w9M9!FCette*TwJIo^YQV)nVFdp z$CLM!7F%0e93LMaJwaKDii$L+l-#?zT&^GE#Ky+*+1Z(D9C^=YWMmkXGcM?tl%u7_ z_V%{2?1vMT*D5P3d4GRjwZ7~?v)e(J-_j^mRaGRCq_niOu%C-O>FVl=+-^7dd_Lux z7&Q_L5ea$KxKB?{)Y#Zax3{-s7B*WtJ3ASP*Xu>@j37ajjW-IpqN4JG9a)H7453(F zUM3VU!MnRVLgDdv2n9?~>_iBK+Ja>Sm|$ybE1?jN4?+PGL?$KnoP+`*C?49H&osRt zk0)UxC{}kuAx_bhPD212K~zGLm>ArFJ0y}EJ>&>}etyE@!35=A6UFQ6E1`hRg@=a+ zLh=0kOekQ2o12@20vSsJ+0-^PG%$kq_jmL`GAs~}kB_riy1ToPa#%rGR##WqDAUu^ zXgTx0=z}ROEv3`bQ%X!s47ffqF+r)Rsg#hAKwn>9)Z5!jadC0qpUYqFb#-<0^72Ax z;Jr3EIT<oK$H&Jkgp{)wafA_#scFp=l_e!5h4=RMLL`QVhq<SxC*=Cf%#2lX)(FZX z&oO6bX9Gm!8>8S;I3tI|dJ6m=45p-{ggQDpNG$)fv$LaYq{Z7}5*<KdK_VecR${r} pZ{z$=#_l+RcE=I4JC2~;`3Gq$t(-cBvWWly002ovPDHLkV1i6I<+%U= literal 0 HcmV?d00001 diff --git a/public/customers/guillermo-rauch.png b/public/customers/guillermo-rauch.png new file mode 100644 index 0000000000000000000000000000000000000000..e46c96f4dad4a888b7339bbf9b9a8b07df56146d GIT binary patch literal 6284 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 CGA(id literal 0 HcmV?d00001 diff --git a/public/customers/hector-simpson.png b/public/customers/hector-simpson.png new file mode 100644 index 0000000000000000000000000000000000000000..295755705963ffa4ddadc19fef3f3f3194138df2 GIT binary patch literal 5602 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 literal 0 HcmV?d00001 diff --git a/public/customers/jared-palmer.png b/public/customers/jared-palmer.png new file mode 100644 index 0000000000000000000000000000000000000000..e495518423acca417164517e440d970edb5ac583 GIT binary patch literal 6460 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 WLj=Co%Z9=L0000<MNUMnLSTY04VNVV literal 0 HcmV?d00001 diff --git a/public/customers/lee-robinson.png b/public/customers/lee-robinson.png new file mode 100644 index 0000000000000000000000000000000000000000..633ae985b3beb0a902df9fd1a52482c1da69ca71 GIT binary patch literal 5653 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 literal 0 HcmV?d00001 diff --git a/public/customers/michael-novotny.png b/public/customers/michael-novotny.png new file mode 100644 index 0000000000000000000000000000000000000000..96a13a69892c1c90445cccca50ec3d28b1681971 GIT binary patch literal 9902 zcmV;fCQ;dmP)<h;3K|Lk000e1NJLTq002Ay002A)1^@s6I{evk00009a7bBm000XU z000XU0RWnu7ytkO0drDELIAGL9O(c600d`2O+f$vv5yP<VFdsHCPPU?K~#7FHJitm zB<GdgZ$?IXUs>LCRdu5cfOhZ%F~Cq5aYzn1XC$4Gn<H~19c{GHzrckyTFb1oo`u|) zGouknQ6fQN2!a5+3Dam_)#XiAW~H|gq2K$m2j>*3Ix92cd+xsb?u&~3{0A>agML|i z%{ARSz&Xfo-lIqJxp1j+}2mS$p_Ers$tPpwf*PmUw?`jNa;LVX3iKU6f9f=Q$p z?@21IaX8Xw5GWla6>E((9t@OB#<jLGtJ~KuX`?#iUfcTf4-QmsC-vry4ZV74K?%RF zqgq2xb~`#c9Vi})E1%CR3`4FhWwQwtxo?bnZtorH!A?!B?nHA7CB1t6vWnT9&RR|F z?w@G?psxNfkf%s~Oz!^vU{uyH^wka`bq0M6Cp}GqzLGu%k4rHOv3E!IvCtD{E1lxb z$)fyBS=m^mcBiIZr>RuZSAySrQB1=zPVgg~5GWpTSZ<h2CY1DiUK?sW8f)0$YB67h zbW)jgT7xi9I3B3S@9OQ5`n{2RJ<eUt;9(F-!??U~qS$DlJ`N4snPM7^BXxUI2c5V2 zI&Ba%91-9cj-|M7W@GqSFNGI8?Va<c^8v>lbAhpZFV2U3#j&k3<X{O;KEJK?LbdpJ z9HUe56o(1i_engabkdHN&|oy;aCWni5>dh(Xgm(o>kiazc9ihO?sG$&5k#Ky#k?|^ zEPnNIOr$;rx7tGu_)IPr!+|&+zb8EYk5eWDVZwVxlWBH&7WydCn12t4L$$j-b#PXH zI8qGfyN_XX7{=u9)`n_g@K!D0Mgcd(dp^fbWbhsb<$`q_vEPf7NhUQKabXPi{h<=^ zz7hc!!Q*9q$0yb857p^(c;7%izl#x+fC!I?c$3!(r4%Vi_ISKD@i}Kg)k<0ATu#|E zMhqvEhow~@&Wh9RpkwEVh%||!>6s>+wa<Ia=(r!J6g=mcPJf_Qr>DVS?CxpCrs4!5 zuoC2~_m28%4`OQd%!|H!Ud$)5+yHM!c39GLB8^F>!C*wBse^1<LyZ&+PgRJel+WP4 zaY5Z~M*-fQ;GmHA+5uyvaXjQ^1YtamIUGpFlbB-;4&C)LyvNExF^lSi`j3=OkQo@0 zC2P`&si8yCI`EzwOqj<++y3({4f&76$6?%;%!n-gi8_~}6s-_FaT)o~PWcd?2uB`i zg{P<)#kd)%78w%pUy_swiB<xzNaqUj(!M$ohYN-r7Vr5fMHu1_iE@|PtoIags9d3- zcwkPWcJMN{2Y|9fEKVj&aPovYoRFdzNmNHZrNGY?J<?0LlutJJO5tRSwq;8g`D#(; zc1<&p%M#tVlAMh?;T(~BZ|I63=8U#)=5XJ>hFy*^nj%>;frqR%yg&sGTPYPaCSnd@ z`Cy6*`+PEt0tY?`Uh{~ec{Was#{suE(Ic+PC)1WMIFo9fkfyx1L}uhO8TGi{hzQkM z6Lq>H)tcvOv?(DRc-|%@y8$>5XfE%&)Hi3v_@ZF|sAhDio<*1!JaXPAJ5uQsj!CQA z84`VrCbR~W_FtSI@EO4&C|<&<8KWl#MnuLN*ozp+hcL_^j;UwTDxM&vq%Mbw`@V8Y z(I$LNNUH#^nwez2A`CB-bBYb7>Ey*DhmLlzEC%N?DYbFH>3L6wwXO!#+;Qz(m10uu zLIhaxyT-s}R3Sx6O1gwo#OFgC8V>o{>f8Qrp~P6<%FItV01LwD>-PItY-((r&*nH+ zp6mIcPtkMOkV6lniH0DoPm1RAITh16%@$K496D>a)gO<jG18daN?2`LjdFt|=^dl* zh9GmXkW>c{8)q<bOb*!r&2kQzFQk>m=qC5rYqY4vm=>!uDq+=_sGPS9oySC%Xkc81 zqBDnPa4g+Mu2S);7nxzSJzhxhJD*$~6Y(IJxHLCIJ+d)Qrt;0T(F|o+$|S)bJUCaN z4+C1qq*B0@OR1!;S94m<mK1UGR@inI52@+NXy|}zgyB|OdCDM1nw#4qfX-zM7w?m* zla>*ZiL0RmAXF;kXkAHgqNK0idP$qVd%=>PnjSgBy2GySesx#9_9M~{KS$3~li#Jd zwhxxX2ywtQ`_IA6T9qO27-I*V&03RzlmV^*WXv=Cu#_g9!2>_-8z2R)-x}F4SKeMs z>uU>m&+h^Kk)8n(%|=IEB3#O5NpFBEHgIWXtsp~2Xp-axq&){HRYT2G66&5sIvX|> zA4ny7ZKYCGxxB2^xhpz7Jk-PcUr>8#&CV{XkT2@O%$hE(-_+?FyZY?QpR0DfZQ)da zV*_hDMldLcVPHKxdJcx%n(r}QACWoZ;dmNlvcNgZ3mr&Ojmp5n{2ZxSO3?<!Mq*;F zEp1jn$4p2{lfsFCPGK$ssHTw$^RlZVyx8mxd4Jq_+T)@lXk4e?m5*aGsjTG{bk5g} zTQ_v;>Mek<tY^<2>XS!527!|>qpmXff}Y%epv_Ag+PHX4#bQaz3+rUVjP5`ASbJxW z9i@yzgglUY7^Ac>ZV*^wlgm7dZV2iRDT4_u$s!)Po?u2#yTpVu(v0L^o=Lfs>+k_f z?`kg6BK4Q1MI@}JB!|kTFd!LW5Ff@EBL{8hr`61aw3&d871&n2-qmsIT=8P4Y5~+9 zB$ehy%cWU6mAcKQx<vNk?2J~|He|5dA2ijO$;&U4)H^@a$?oSW<TBcP;f8KreM^&V zPdm-6DV>ZD)r(W-FgP=K5}QWZ=%ayd8s|oq-UK7Ga<C{*E1%MjL$Jt*%^8puuxi44 zPkV-FaM~b4`X-f2_moNvwLUx1+mnobu?@$CMGXwx_#$CQV|w7kK#6vO!L4(Kk3O#C z^LcI_Zw>X)ukL7NaX}a6tNO;*|F-7l*IbXc+MH0g{oXk>+1J_0Go5Zf(vR=&>gtud zdi&k?bZK@&Cxb&}!-mSRz)>lt?PN@KYdO?m;0&_}8gs)eLLPS=IObZWF*HjNnwuj! zezDNUdjoo&RBYw6*Gg#T90X1zRmt^~OO61iP)j)v!{a)pKaPSpBqc+-X64bV28NCu zJRg8?Sr`ppLw*kHMB-%N=-tNJs$ReSuIA_0acaWYHFX9UrSeK=iYkuV+%KyNX_lk3 z{^Vz0>dset`sO#^(+u^W%C(gOs0!(b&f)2>g)!r38p$ceaK<P2td)R$8CWF&QM+F} znQ|rOr&C?1+gNE*Gn34y2F=_aFcI;6jkaRsyG1G-bwi!?4EdOD=%q2x)-L47nMQ(y zL*vR~2?H_^7w8=bouttZxo(kGbm_vTs?`-4H8O4;=WubONkkz@52ath;;PD*mQ|U% zpo98Y|Mi2rI{5E@MIWB%-~OBT+-Jw&O1wy!m5oR964(&{ik8yxT*8r)IQ%>{wz+_e z<@^b*Z(YLf=O>dByueNQ$E2U4tz=b=;u^q<Yv(p?`1-OD=}Rc+aogGf@NVrc7*q2p zkdK3g6hDN-U?j4^1D6kbW0zLeHcGj?))rUY0jy<2WQ3t-5LhNzkM&)Od!W6aE)wO6 z{=py3>hbBn*W&7&c8+%F`)LI@Iht_znNS&PJ!D%>8BGSEV~{Be1S##ehOSL2B71Q_ zHlI<BuRM<T4VXMUFyKNb-I$||SBuP+%*MNCLp7LazG}v_RUb^7I|h6Gk&5xG@|Bdz zL?%vZ4JHQszRRs)2kHn2&T;U{azQVztuY+Hgs9Uv49yI7T*R6MHRh%vO(&a(tnr|y z<=Hj;qrdz2^uK@dLzNl&jU08ttQbucl8G5Oxz9Zlq0Q3M95%MaG{F1XO2F0<1TmeC z!|o`PEMy8W^gWEQ8y!-&_fNW7gM_S<e1*`w{YG40odi1QOkAx57&c;VjsX^7F0BzW z=Ma_^kXun`Y>f!u;lZG%fSR6LsAy$vNgMMsj)_f%ZBi_749$$PzH02u3#|fe4kr!4 zhltTM1{luHFY3bjs!mSM)$1MWgz<78LerofTBnfBx6s@)z1$*e(BuXvpu~*I<jFvc z&Jo!{Aqxl-;dYyp;zqk?p|;LON=Hp?6zQLEPx}yKJk5L>F-slexW-S0@W1m$TVu$& z=Y}f!Bp}wOWsKYOOAIb-mbExr(o%I6FXvp-v|-&+*m$`0*64XpPtYA=vC#4NC@@9D z`Y9)eS#4fk(4*5c9gTYcDg#Hm<0!B>EL+K7cj(%li45%~oB_2YNv6;(9Z5>qL}zVm z0B@+(P%8kDt$G5ZQ6(S)M#*g2sbk>o83do2ARFDt7lVn#0f0$AP?Hwb$AHAdB`5XQ zcfc}X;`zguZt0Dy*H!N|@hpAT%Q9Y)74+{hnUV78(Wo32=@^a;=(9G++rI-eweh&a zSsE%<%le{mpl7WHV_}QP(q~QD!GHwyZ>`9~K_LP~r_p!QQkrQaNta0jnuZZJS9dyH zMq2vt!`;ZK1&yIGrBFNY=?-c^5=Em=AFY$lWBOM#u`~qbQqy{x@ScEC(x|1E0xU?a zK3WxQ01%sKy;WCux~+J=1Tv;T=8^7w{D1W9(L>#Nu&c#VPQUy9ds<w-<fbzlSOdg_ z!puDP$hx7#gg3g6?$)8TZbqKSH)<7kEm&dPh6rAVXAd#710#&Um=I2pw#mqNr%6dr zEMsHF*Zn(B2g=f8k3roqw7N>_l#~caCC5{6MjX-|!&}CC&10r0*o+$|GTB02Nf2;g zSP)H|I2Yp}S6_c!hldBsmP$?^8}=J&x6ZVEKGZgI@L*8a-CzDpH~J@(Ok4LK9O(1y zx^BPnqTYS~TdFQ^;;5Y3r1*qsDn>BE?#R_>jFHpsolGWNT2Fd`H3_<d@1&hr)^~He z&A{XF#PM%GF&#eq-6r#G*QPj|wHWoXN!PDTS+G9pB|V3vX<AE}XjvcbQbS{;6ce2M zV%jMno(<!M!9*aW7n~TVkh*!&IL_y@jGEVPyrqTmw!Zb&TeQCft)igijVpR`=SQ%- zeQnYE{RdCASpETh_K!HUuh(W*_1C8ll*}-gm?+$}Q8Y9T;S3m~un1w%aAXY5n2?dN z=z>Ak22D7~**s56vuyA!+>_ySoQj)hXRO7P3mX-vSN9=<^-O_2Rz<5OiUF*Ln?+V5 zHplTjoY)AKa6}-^^`14(_0C(rt%HO6Dut_%8;1Y+7nLtxqCIsT|Ba_|O6KOY@zPuR zJ2Q)VXMZ0M$}3mOJM_(9;ONeW1Y+dIR{PKOaZ@Wft1&AN2U}#j2nnWVxu~1m<WEUW zjuuvgV}}eL4WjRxR2qBEJ*|-kA#KN>=D$gy7QMJB8zW0Y#CbzUQkMSW7?Y`!_WKk@ zM>ZXCb1+&TJif2%8|&)Uj})w4Q4HgZ$a~fU4QPCNB2G-e%mlld_2}tyD^9mcm1tv> z(g>g#ZZ4^}d&Xxcj+~ghBjfH9&!K!aX~biqp4G335kxa(C1@HN24`uXCffG~Z8cFU zedo2v(M+4f9q1T2wI3Zd0Jv=aG#O{Yq?9&6Et+ac0UnzmzQz2hNEdhQfeh$TrzdUw zr$7B4`VKWY9JP6!p@KtoYlnbHq>FET*E!1CQUWeLY@&dc*Ksfa$NPKjW7u9xKd+sE z$expmoSbB(!}cQy-c*Y-$^^bnJ1zAPB%qD-WCVr;*DzyEX9Kj_kf=HeN4wvrOp-Qn zfMq6&Sd@)*d!Cy>ES)VCLehR<k_;b+NH>oU1kAo68ub9R->2;uua5BikX~nm#3Lj2 zhaEjWI@Ch7qFDD#I}djq*ImDSP5<RT{yP;I$S-cJ(Pyt{RNDgpOParYlT<f7hb-85 zS@-Y#HCd2#BB246wZ<f6vydw*hp}C_z!~Dcm7>kqDLRHJl%SQHfBPt-%@$K!x9<SW zw_au%uCXVJtfh$=YJ|nSX%UW@f#a#pJMencw&&{JQp=Rwc!X9IOB+m5!=$ut%xmHl zk%$u5dU#*!OEcO!I8_RxVtdaZfL(q3<x_q9#c%ZO+ZVLDzM{|W{90d&HC5iYtb@j> z{_N3LWR_h08+ova%%-6VX-aQ^V03hN+JFX+rm7{5%A^yngA5@{ww|$>-NgAGL9mpk zKy7?7EqA&Ivp8G7wO<;Yv=oh|)#oVNBo?^zvglg>i^E@I4F4%=GM%ziVwy=Y>@%#J zKwhW5YTHjB3q!r~>J|Ou^K)%%+|nzXZ)jopJ`}W}lir!0-P=*)xUTEHbq!Br`VYVQ zP`enCfflAgc#oxA9`Z6XJI5%=)KqWl;Iv5#?YR*!!{AVaK3b@nT}TFHWp!yFH<?VC zk?}guxNj7gI2NB8%ZHOW44@Xg_*Bj@pfTk0SX_C5$tcsI+pR*ZFB%Orq~~YPLSnyg z>kmMsSXP6n=)>PUg;1pRkN@CXh<+7$rA58^oj=ff|Lk8Yv-~3WN$DH!T!Zv<b?3=_ z)rWv5y(Z*q-0LY0vs=zpw3<QXBp~fpTlFTK-9!eEIm>Wh^6>yotB<igO08|*-O43+ z4obYYyju8v;FwhCRwDUo#vxlU&2IoD={9e!Z#fISshZ#v#i=rAT-H1p*s6o5456bw z*DRA}*Vot7tT%Ox5@JNYT+M5S?M2Zf8Pmc*;;Wmhx^kteX0xWd_n+!>JZFT%+DF`G z-eF90siNj$IVH%rCcOIovqLr6W7)=Gc9xN{m~$C5pmtkO-fnN?@W*<#laq~BVuv3Q z9W&O_*9f;pwmTd;hZvYS;_b;vqt==d({+xEx)Z?77uK60_A%CzK8v}KcJ}S{EBbFA ze5}pFyxzX?0t>lwHBA_4fxgWXnhbomp3=hVvg@N;TaWc8KmAhWo9i0S@VmCD{?H-F zNVQm?ZBezRj~}1t(X%6Vz&$4m7cq2}4N19>arN3|X16X7Jl`$({_~ZKm8&J5?QlF> zWSc@|J6#x(Evv@kXuA0$g+sTubvq8H5qU;PZ2omP=Q&UMwjPD)1gvf<sS@hP6`h^^ z81H%<sG#+Q89myo>BWnyT42l2YqbEAQ|i8>MyIWZJ59au=9@ZNgBOpGhexm~4!>Ne zYO~Cu9B^#b&-GyYKszTbS`-5g<KO%Y$j(G&0$!gkVr<HFnCN-Gb@?cF?&>UA5INy` znz13#?Xj0N-Z>;nZk+4OrL1Q~?@vc9gYeMwB-`(fjDE^(5lrbfooQiiQ&*sZ1@1Io zDwAqyU0z+#gTtnN^vQi)Ud#hPLYiHn#)f*l-^Qt)zWMsw`pfo?TG1ADo@R}j)kbbn zMI@V6v!UHXw)*t<0TWY-#a|(343GsM=e4nOME#D&V+T&Y6D#dZo;!Dj4d<<wmsz#A zO<Ux|>;UAo2>G;?(CuQ4v&LKv+t6UW(5Vu(>adlR?QAE3Lv_mlBlHQt@3m`husUsN zaee`P+q9&VD)8{{y?a}K{Ffi<qc3*Qyb%dM+XLu^dhLZ}efPbuNsXp1&0JD_w6Aob zq9q?hrp@)w>)Jg)xZgX2Jg^E%n4xJ}P|}^noMxI<gRB|y`-pbxJCPygmJ12ay^Qj* zuuulHmUG{?2wTsZuG^-IsOf|oIS(a3KTFNXwW#NsuK|I1?>QiN%%BV9HT~Y^Yg+J& zdVorC12MnP6qYxwiTCDEI;&Zf&*L-7a|951`u3Yw^!3|U)z~8)=dQBeDdPMt89-ge zGKzYAZSCyp^GEwSsyh{tEk#;$MBiGGdys*0YT;m8gqtuCJl`C;M=<y*P(m+k&T4tF zD$@%g2%a-GdcMoCy0x57SR>Ea#?2Vc#HkRY4kf^LB1!$EpmIx@ye_X?Rc__BYP)dl zXS?cbz{psE=8FsZqV|lsVT-|1&a~qcc=7F*msopFn7)!)MytN_>utS@s`;!l(t7+{ zU(dX#t+1w(+A#v&fxdjYr@dOoE#-?yxn=aMG|n^QM<d%Y58Rr?h6j6|1S(B*eTUkX zoy!X)%^~)uQbv$`dt||e@6hQ|vFBR7)kKj|G2v1;a=ka~kKHbLxiF{Ox4xmZxpm#n zmz6m<W^2&Xg8~D`0U8&^J~`vHQdXP!c^#aPy0MaR9L~sgkyUC1Aftimmv^7hUKkvz z2{dbui89oOpWfH<l}%MHZ0N~hmx=3Fta>nn7F0BrMT8SrWvD!`O$f$LY;kPzF9v3w z?~^U7%9W%xS1YQ{6aY3<(E_k;tRyn&)g+uK=9GKWw2abP#M4Yn2`{7di*M+ai!bTs z#-{G0h5c~%RGrhBF7o--Y*jyN!K?ZAw-M}W9AxMIj{XJcyd5v<`1G8a7>2~_EjAMq z1cvj0)tsl_zkWr(hML|)lRP{eIBY14S}H$2(F?D?tMA=>MgRFPeyC3$d`3EF+}3hp z5w)iVhC}xdjh#E`A{%$okG&^G$y~lPr{%c{WmO>JNmEnoshcr%V5(#25H4=Ihou7^ zdi#ZI`kmDqS}t#>NxRuUsHp-$m^mHkyJgUqOo$`4ov}zCG>`P+YE{opP82~7W>}2> zVDC@|Oe=5C6_r_E)CsL+7<g`@Sd1lgP7j?y?#;D2%GUSw@$p1ILc|~A)RkI;Gt@M= zu&%%L`~O`3<PRtM?CuBp<-K34!M@srJkWB=q6}j!Se_01zI%Y>#p^4&esK*n&rb&- zlNy&UmA-HKl=bJoc|^bmZ7VY?djGZW=zCXxTeEB(`Vfc5+@$?vTMOfw{`%nowUp3O zyTRrmREx>y1SEZVHm$EtJG!{Ih@7&er_}y^#DH`1c^=~mMEUM%SHIdm*1e+|YtM;Z zqSd8nLnTy@x!Js%b${#fl2)LV3DZsI77*$B+MsMV*I(8<H(wJ+0?eMdN24;vpa_t) zCmU1kA)B?0S-pDw60NNY8%sTZ?gN7>i<$3xZaop3KB-2}+MHj}zx=I#sI_=mk1^(8 z|5#si2l{~bnUdkbUH=ymiY~0N13uLQ$jWaR+8-dbWJ&*@(c0Dkf}4D{4L00w8<7~P z3t@Tb;=2Ct=Z_&LY&ST;`wLb5&hmnqrFnQbE1zse=Y9#!%*Nt)Ps4gc4Y+h-Z%-G! zy0#B`O6T+X8sgvk*RJc*^1M!Krw9)t*NQAy`AS-^z4C%q7nYn-WA*HewUiEqZU^X! z-IRKt`q|&_x$$hbEBAEGtEW3Eak2GMMQNs+1t@6ww68fht6w`umhI^1_()@>m-3}~ zmEp&q0qt?pcvK5qj~s%gEoRpyy!bnFGx}w%>7LEn#Mr%LUjOr?qn8T^=Z%p*Vci33 z)`d((y%{ow!J>?_FW|6yD4d(5aG`$4T9^KQ^BtzHTl%X{exNV!-vP`#Ev?OJac&mp zBNZVxM`VF%ZU$`erS+NbC){o)bj##T1oQQHg+(|hy1S!mG5TpLbX0T*5M+BD-CD?K zAFcY8m5N?Xhq^dlh7&I;YBaRcInq<2a{Jmk-}~CxeykEWv0z#^B%{F~@qRJJ7BbWv zDcC`^=*=!FgKF{8;7ntLhB_Hj0#|~AhPFxX4-e1O+ulW+%IJ?#H$%j~$q{2E%E#{9 zvU{TF4{lsn99Fkq+tRI<Ry1F&(ozd_o9Xi<MmbF$a!(c+=`h-9y>W;Ncy)bQuM|Rk z)fnr~wrYBuE9nRZ^RVJ6+vw_y`SgeEp|*FMdKm*^^u$MO4)=#im8z@ybpMe){N-o5 zf!O}i+^X(y-NU0}*;*$FUi{S=dN+r8A28{kx0LPF5d4o>g3qcjNhv!st5<MJfjw}m zl3>`6>mp0L3#Gn(FH6SxO;zdBeGvMCtz9+Fy9zhT^5(B;ee=Gu8GFtQwuplxH$zOx zk$Wo1h96TqOnQkxxFZJbFMXC^fYZY^5rQNC{mn&Pay3rVC+*%`E$V0{qZ<fpn+M1? zM)PKuwMf0bMlap3%&7@DWxu?u8N9wc&wl9c7s?`}-C(!-Nry3XWkp{h|Flpe4)+?g zCxE8u>DS1{<Cs0G<!fo=t4^7Hik98u{yUV$=Zt*?B0q*z#gKkB+lP7+K-$~y!>DHT z&XrqW#g@~*`pncOIor0x+TfT)fj=DDkUb^eR@65)HWa|3{^AMCaJB=N1KP#2Z7tHY z>)8SkK3COiYmF8BWxTy`e83trh0Fr&d$OZ>fbPZffnt>+EG(n;-mYV9XSjNamiJwj z+mmdbGAL<70|hwb+0|P*-96TCuTgJj)XvJXHf==%h&7RKdu%_JXFMICPaQK#?%GO} zh1(-W#|KY$^{-abdi(OC4pCXW>>OZNlXa|!MW3-j-;3OHD5lW*wuLj6W&7bAo%<Ry zW};Wq@ug+`bpKSZqd+uaN6DBy^2baJc=eH8cA$FKLCX>8J!a4!V8kGeWD3%^0jMJC zMs=>L1=vx2G-O}g)-r?o5i60ZiSlID8X422WwZ{DQ~~tnp^c@Tp)M5Z6d<n&>IqW0 zdtTE^@bXOC)9-MvYm<&<0mVkv)9KorS{YBfCqw-u!s6W0nwD%`GdXf&tqA~QFbc?; zZXisgGnzHx7bT_-Ytp%Ad+x!I0`-=Mas7s=W42t@J!*Ld&sH*!3s#|bk_DZEgaf>I z*Uu}cEa(Y_-kZy+IKRw+(`*n>F=yww{-=ERbzp*eX+@JFgeQ5TF35kxB5aO~Xd<s3 z;GiXQV!Td?CE0mRA2@R>6%>vt4le<4Bihhp_ekep$&asI(YHzotu0mAROVn=CAz`^ zBW?8jxsS+=xVB&N4aL0a<5|e9IUQ4fOHa1kQ>$y#Ns*!UOIpw|`=A31jw8IEbXix@ zvU;eL4OrC(k-Y<#_79JBJ_5X+HPqzd*@Jz@;yy1P>G0XUilwXiyjIs!>TZArwS=<R zqy#>NpTESkl^VqL8|pIUXDO2+2FLVSDi0>i=(TEEk4&e9CT4b@lCA^9fGvfHdUK0K z&39{BVZ1$iT+{Mu0mqyC%p$=F0;W#ehEk@0#N4w^Hbi6?%|6;X)Fs+ai=USnCMNB= z-lQ$9L&86&y{z$}EB53ML;rilK=YHh`b<JaGNnA9(yKEQgzt=ASj}sRY#8)>U8G-r zbQIV7^L(~6r=PP_zu2cn`w)sAX-s)6qa9@d%=GC1fe%dB*;b3zb+QbAp<iv|$X^_F zl_p|)TSOKKwN1Le3mA2O^-CC6N0r;xb=YBX$2F5SW=>As-a51i&{T`)xiDb*luZ_| zF3f6tc&>Xpr#hn3XGzVUY&Y}*;M4C6^pL5)MvCpBTit=|PxiZ7U;*78LJrv6U!--7 z;N%}1A=)n>qBTP&u$&>??%KYoiGm2)t|F)2U|UfpqIJ}d9$9lcCFRpGy%}WmIuu~B zLI#o2l`PZOd{XbsTiF#DYN%5r@IO5OJjsxYGg;lW2@I#&BH-yFauAZxIf7pv4q>Tl z3qZ6h_cXm93#YWw_Pind=Cx#BSLbs2DShhEqisE6J<@^o9AptBNO@E>jhGq7Gcy`7 zszv-fg0FTU0U>MGBd&c?jcd!dhroUJ7{pHj#%`ggEu3)|Me`8Q+ef9C9S?NukM;AN zI?-ZP189CS@pb06v~f%X8369FHAtS+lo_S;v>(?itJiP>%nPBhjrKJx%;=$4Kxi0g z@vN_p>nF-KN9sc_3-fN1<TNdtluSqVP0BIcGQ$29DRsC*Eg<o%6_R>wCZ(;jm|kH1 zyfRaCb+N)!V~a13w(&YhId2b?g+0^;q?+`|34$-v*WYFJ3M*8Paqbj}=Zp=(8}nJX zbw(S=vNvID>^_LzqUK56TT6DYt_mq6TziPc<Ir@5L!2}N1--}a=+D8HPsoOq(-Ux| zrUchE5c}-@L+~e~Yee#Evyt9RN9rW!)k900L_N1Gus=UB&DVF&Br@F3Fs$F4gD@=4 z=p$79@T9AaaA1#*DNn7HP7YPdpzL?4yO4C5)Rkj*l#1DUgL*uwt5{9Bkz|zuF9T*X zjk*#rsjBJG%*grEV@Sgoqz|=<C}&IS3BC4YcUPB_W%U8aTjfZ%*jCK+T3Vp()tQnm z#P}iuews#<=$<lFF;iR10T7?=p6F$!sBcx`x>AgE7hzzxLHTjcRWhlR#mIQZDXs1y zn3$%D#ys-J^4245Fan0lRd{eq+s7SsXixU^T^af0z-DAyU695#Qu-)m8}~lxUea!1 z0$uc};fSatR7;~d6-zp$uJ`zS1;Wu}=s1cY?Rat;_n7`XffvU^la5*n+x@Au3Z)bd zNf6ayd!*S38Z`3Hb?P)-KXvUXB%RCD;VSEwUm-kvMCm*UySlqH(I!z(ttK@`pO2!J zJ?P|Se0!M2zi_##3zeKIT2T6sMK>vv*gw>5+SL*LcL&7Y4nnt`>!Tz#*aFrW9J=Yg zdS^s!*wZPcu*)Pg6Qt;yC>?C}I!sY704l>`QD2}jUt>`CG4=QhmSA;SP#-#)Kwv*y zTGb9fb-tF-ajv6%diNYV>LHOo<>wt{$Qh1XU`pyS^=yF5Pg$c}WJK*kg+FfeRm&H3 z#@EYh3%aqkL@gibQg#GG^T3)Zi?q^Bn!*3{d++G{>|DRzPV1luJ?x$9813o>`%@Zt zZiX$Od%V930yE$jsi~K!vF2o;muU%UT(RA2Xhdeb00}vS>yC-i(m0_ZTY_jVP@ZwI zWXy;N#qIALo&~ydcmTP;K>*Ct!@7QSl-8&9u11UVTrp4)=bV*%J;B%_)Ybl=Ya0wX zJFCI`j2lnfV-*#M(IVh^i-F-PC00G#*V)#ds$fVLGMik=*`p2aL0D6<{MWC19dUbG z|L-Rs=_AIl2@$Os#S55;dnTcDnMMP>W)F>$vOCnlRocfPW5;!d{TM0B!WPzqBS7hd z{c%;n130(|LO>5sw;%-HTqtt4loomY%@z9tlED4t*kfAIZ;t!=1_MI^_GH_Lt7LT^ z)P2-Jk7hbca^R<&B@N2jA8_rVi`iymzLL=;Tg$R7tb*tn?k7s;lx!GKD)+`oCM!ln gujT$M$;##b1L_e3d9pcM8~^|S07*qoM6N<$f<?Y~2mk;8 literal 0 HcmV?d00001 diff --git a/public/customers/steph-dietz.png b/public/customers/steph-dietz.png new file mode 100644 index 0000000000000000000000000000000000000000..e99f15aa2f7dcf15dfd86618b5da3e3ab6ffd8f3 GIT binary patch literal 7151 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 literal 0 HcmV?d00001 diff --git a/public/customers/steven-tey.png b/public/customers/steven-tey.png new file mode 100644 index 0000000000000000000000000000000000000000..3f5bd7ee821107943d45e5aa29b19721a6cfae4d GIT binary patch literal 7345 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 XBRfi*vO-@%00000NkvXXu0mjf;hzxo literal 0 HcmV?d00001 diff --git a/src/app/dashboard/(overview)/page.tsx b/src/app/dashboard/(overview)/page.tsx index 60a12e0..6d632b5 100644 --- a/src/app/dashboard/(overview)/page.tsx +++ b/src/app/dashboard/(overview)/page.tsx @@ -1,3 +1,8 @@ +import { LatestInvoicesSkeleton, RevenueChartSkeleton } from "@/app/components/skeleton/skeletons"; +import CardWrapper from "@/app/dashboard/components/cards"; +import LatestInvoices from "@/app/dashboard/components/latest-invoices"; +import RevenueChart from "@/app/dashboard/components/revenue-chart"; +import { Suspense } from "react"; export default async function Dashboard() { @@ -7,15 +12,15 @@ export default async function Dashboard() { Dashboard </h1> <div className="grid gap-6 sm:grid-cols-2 lg:grid-cols-4"> - {/* <CardWrapper /> */} + <CardWrapper /> </div> <div className="mt-6 grid grid-cols-1 gap-6 md:grid-cols-4 lg:grid-cols-8"> - {/* <Suspense fallback={<RevenueChartSkeleton />}> + <Suspense fallback={<RevenueChartSkeleton />}> <RevenueChart /> - </Suspense> */} - {/* <Suspense fallback={<LatestInvoicesSkeleton />}> + </Suspense> + <Suspense fallback={<LatestInvoicesSkeleton />}> <LatestInvoices /> - </Suspense> */} + </Suspense> </div> </main> ) diff --git a/src/app/dashboard/components/cards.tsx b/src/app/dashboard/components/cards.tsx new file mode 100644 index 0000000..72bb37b --- /dev/null +++ b/src/app/dashboard/components/cards.tsx @@ -0,0 +1,62 @@ +import { + BanknotesIcon, + ClockIcon, + UserGroupIcon, + InboxIcon, +} from '@heroicons/react/24/outline'; +import { fetchCardData } from '@/app/lib/data'; + +const iconMap = { + collected: BanknotesIcon, + customers: UserGroupIcon, + pending: ClockIcon, + invoices: InboxIcon, +}; + +export default async function CardWrapper() { + const { + numberOfInvoices, + numberOfCustomers, + totalPaidInvoices, + totalPendingInvoices, + } = await fetchCardData(); + + return ( + <> + <Card title="Collected" value={totalPaidInvoices} type="collected" /> + <Card title="Pending" value={totalPendingInvoices} type="pending" /> + <Card title="Total Invoices" value={numberOfInvoices} type="invoices" /> + <Card + title="Total Customers" + value={numberOfCustomers} + type="customers" + /> + </> + ); +} + +export function Card({ + title, + value, + type, +}: { + title: string; + value: number | string; + type: 'invoices' | 'customers' | 'pending' | 'collected'; +}) { + const Icon = iconMap[type]; + + return ( + <div className="rounded-xl bg-gray-50 p-2 shadow-sm"> + <div className="flex p-4"> + {Icon ? <Icon className="h-5 w-5 text-gray-700" /> : null} + <h3 className="ml-2 text-sm font-medium">{title}</h3> + </div> + <p + className="rounded-xl bg-white px-4 py-8 text-center text-2xl" + > + {value} + </p> + </div> + ); +} diff --git a/src/app/dashboard/components/latest-invoices.tsx b/src/app/dashboard/components/latest-invoices.tsx new file mode 100644 index 0000000..5c7cd95 --- /dev/null +++ b/src/app/dashboard/components/latest-invoices.tsx @@ -0,0 +1,60 @@ +import { ArrowPathIcon } from '@heroicons/react/24/outline'; +import clsx from 'clsx'; +import Image from 'next/image'; +import { fetchLatestInvoices } from '@/app/lib/data'; +export default async function LatestInvoices() { + const latestInvoices = await fetchLatestInvoices(); + + return ( + <div className="flex w-full flex-col md:col-span-4"> + <h2 className="mb-4 text-xl md:text-2xl"> + Latest Invoices + </h2> + <div className="flex grow flex-col justify-between rounded-xl bg-gray-50 p-4"> + + <div className="bg-white px-6"> + {latestInvoices.map((invoice, i) => { + return ( + <div + key={invoice.id} + className={clsx( + 'flex flex-row items-center justify-between py-4', + { + 'border-t': i !== 0, + }, + )} + > + <div className="flex items-center"> + <Image + src={invoice.image_url} + alt={`${invoice.name}'s profile picture`} + className="mr-4 rounded-full" + width={32} + height={32} + /> + <div className="min-w-0"> + <p className="truncate text-sm font-semibold md:text-base"> + {invoice.name} + </p> + <p className="hidden text-sm text-gray-500 sm:block"> + {invoice.email} + </p> + </div> + </div> + <p + className="truncate text-sm font-medium md:text-base" + > + {invoice.amount} + </p> + </div> + ); + })} + </div> + <div className="flex items-center pb-2 pt-6"> + <ArrowPathIcon className="h-5 w-5 text-gray-500" /> + <h3 className="ml-2 text-sm text-gray-500 ">Updated just now</h3> + </div> + </div> + </div> + ); +} diff --git a/src/app/dashboard/components/revenue-chart.tsx b/src/app/dashboard/components/revenue-chart.tsx new file mode 100644 index 0000000..49d888c --- /dev/null +++ b/src/app/dashboard/components/revenue-chart.tsx @@ -0,0 +1,53 @@ +import { generateYAxis } from '@/app/lib/utils'; +import { CalendarIcon } from '@heroicons/react/24/outline'; +import { fetchRevenue } from '@/app/lib/data'; + +export default async function RevenueChart() { + const revenue = await fetchRevenue(); + + const chartHeight = 350; + + const { yAxisLabels, topLabel } = generateYAxis(revenue); + + if (!revenue || revenue.length === 0) { + return <p className="mt-4 text-gray-400">No data available.</p>; + } + + return ( + <div className="w-full md:col-span-4"> + <h2 className={` mb-4 text-xl md:text-2xl`}> + Recent Revenue + </h2> + <div className="rounded-xl bg-gray-50 p-4"> + <div className="sm:grid-cols-13 mt-0 grid grid-cols-12 items-end gap-2 rounded-md bg-white p-4 md:gap-4"> + <div + className="mb-6 hidden flex-col justify-between text-sm text-gray-400 sm:flex" + style={{ height: `${chartHeight}px` }} + > + {yAxisLabels.map((label) => ( + <p key={label}>{label}</p> + ))} + </div> + + {revenue.map((month) => ( + <div key={month.month} className="flex flex-col items-center gap-2"> + <div + className="w-full rounded-md bg-blue-300" + style={{ + height: `${(chartHeight / topLabel) * month.revenue}px`, + }} + ></div> + <p className="-rotate-90 text-sm text-gray-400 sm:rotate-0"> + {month.month} + </p> + </div> + ))} + </div> + <div className="flex items-center pb-2 pt-6"> + <CalendarIcon className="h-5 w-5 text-gray-500" /> + <h3 className="ml-2 text-sm text-gray-500 ">Last 12 months</h3> + </div> + </div> + </div> + ); +} diff --git a/src/app/lib/actions.ts b/src/app/lib/actions.ts new file mode 100644 index 0000000..617b4d7 --- /dev/null +++ b/src/app/lib/actions.ts @@ -0,0 +1,117 @@ +'use server'; + +import { z } from 'zod'; +import { revalidatePath } from 'next/cache'; +import { redirect } from 'next/navigation'; +import { sql } from '@/bootstrap/db/db'; + +const FormSchema = z.object({ + id: z.string(), + customerId: z.string({ + invalid_type_error: 'Please select a customer.', + }), + amount: z.coerce.number().gt(0, { message: 'Please enter an amount greater than $0.' }), + status: z.enum(['pending', 'paid'], { + invalid_type_error: 'Please select an invoice status.', + }), + date: z.string(), +}); +const CreateInvoice = FormSchema.omit({ id: true, date: true }); + + + +// This is temporary +export type State = { + errors?: { + customerId?: string[]; + amount?: string[]; + status?: string[]; + }; + message?: string | null; +}; + +export async function createInvoice(_prevState: State, formData: FormData) { + // Validate form fields using Zod + console.log('ffor', formData) + const validatedFields = CreateInvoice.safeParse({ + customerId: formData?.get('customerId') || undefined, + amount: formData?.get('amount') || undefined, + status: formData?.get('status') || undefined, + }); + + // If form validation fails, return errors early. Otherwise, continue. + if (!validatedFields.success) { + return { + errors: validatedFields.error.flatten().fieldErrors, + message: 'Missing Fields. Failed to Create Invoice.', + }; + } + + // Prepare data for insertion into the database + const { customerId, amount, status } = validatedFields.data; + const amountInCents = amount * 100; + const date = new Date().toISOString().split('T')[0]; + + // Insert data into the database + try { + await sql` + INSERT INTO invoices (customer_id, amount, status, date) + VALUES (${customerId}, ${amountInCents}, ${status}, ${date}) + `; + } catch { + // If a database error occurs, return a more specific error. + return { + message: 'Database Error: Failed to Create Invoice.', + }; + } + + // Revalidate the cache for the invoices page and redirect the user. + revalidatePath('/dashboard/invoices'); + redirect('/dashboard/invoices'); +} + +const UpdateInvoice = FormSchema.omit({ id: true, date: true }); +export async function updateInvoice( + id: string, + _prevState: State, + formData: FormData, +) { + const validatedFields = UpdateInvoice.safeParse({ + customerId: formData.get('customerId'), + amount: formData.get('amount'), + status: formData.get('status'), + }); + + if (!validatedFields.success) { + return { + errors: validatedFields.error.flatten().fieldErrors, + message: 'Missing Fields. Failed to Update Invoice.', + }; + } + + const { customerId, amount, status } = validatedFields.data; + const amountInCents = amount * 100; + + try { + await sql` + UPDATE invoices + SET customer_id = ${customerId}, amount = ${amountInCents}, status = ${status} + WHERE id = ${id} + `; + } catch { + return { message: 'Database Error: Failed to Update Invoice.' }; + } + + revalidatePath('/dashboard/invoices'); + redirect('/dashboard/invoices'); +} +export async function deleteInvoice(id: string) { + try { + await sql`DELETE FROM invoices WHERE id = ${id}`; + revalidatePath('/dashboard/invoices'); + return { message: 'Deleted Invoice.' }; + } catch { + return { message: 'Database Error: Failed to Delete Invoice.' }; + } +} + diff --git a/src/app/lib/data.ts b/src/app/lib/data.ts new file mode 100644 index 0000000..c655f10 --- /dev/null +++ b/src/app/lib/data.ts @@ -0,0 +1,254 @@ +import { sql } from '@/bootstrap/db/db'; +import { + CustomerField, + CustomersTableType, + InvoiceForm, + InvoicesTable, + User, + Revenue, + Invoice, + Customer, + LatestInvoice, +} from './definitions'; +import { formatCurrency } from './utils'; +import postgres from 'postgres'; +import { connection } from 'next/server'; + +export async function fetchRevenue() { + // This is equivalent to in fetch(..., {cache: 'no-store'}). + connection() + + try { + // Artificially delay a response for demo purposes. + // Don't do this in production :) + + console.log('Fetching revenue data...'); + await new Promise((resolve) => setTimeout(resolve, 3000)); + + const data = await sql`SELECT * FROM revenue`; + + console.log('Data fetch completed after 3 seconds.'); + + return data as postgres.RowList<Revenue[]>; + } catch (error) { + console.error('Database Error:', error); + throw new Error('Failed to fetch revenue data.'); + } +} + +export async function fetchLatestInvoices() { + // This is equivalent to in fetch(..., {cache: 'no-store'}). + connection() + + try { + const data = await sql` + SELECT invoices.amount, customers.name, customers.image_url, customers.email, invoices.id + FROM invoices + JOIN customers ON invoices.customer_id = customers.id + ORDER BY invoices.date DESC + LIMIT 5` as postgres.RowList<LatestInvoice[]>; + + const latestInvoices = data.map((invoice) => ({ + ...invoice, + amount: formatCurrency(+invoice.amount), + })); + return latestInvoices; + } catch (error) { + console.error('Database Error:', error); + throw new Error('Failed to fetch the latest invoices.'); + } +} + +export async function fetchCardData() { + // This is equivalent to in fetch(..., {cache: 'no-store'}). + connection() + + try { + // You can probably combine these into a single SQL query + // However, we are intentionally splitting them to demonstrate + // how to initialize multiple queries in parallel with JS. + const invoiceCountPromise = sql`SELECT COUNT(*) FROM invoices`; + const customerCountPromise = sql`SELECT COUNT(*) FROM customers`; + const invoiceStatusPromise = sql`SELECT + SUM(CASE WHEN status = 'paid' THEN amount ELSE 0 END) AS "paid", + SUM(CASE WHEN status = 'pending' THEN amount ELSE 0 END) AS "pending" + FROM invoices`; + + const data = await Promise.all([ + invoiceCountPromise, + customerCountPromise, + invoiceStatusPromise, + ]); + + const invoices = data[0] as postgres.RowList<Invoice[]> + const customres = data[1] as postgres.RowList<Customer[]> + const invoiceStatus = data[2] as postgres.RowList<({paid: string, pending: string})[]> + const numberOfInvoices = Number(invoices.count ?? '0'); + const numberOfCustomers = Number(customres.count ?? '0'); + const totalPaidInvoices = formatCurrency(Number(invoiceStatus.at(0)?.paid ?? '0')); + const totalPendingInvoices = formatCurrency(Number(invoiceStatus.at(0)?.pending ?? '0')); + + return { + numberOfCustomers, + numberOfInvoices, + totalPaidInvoices, + totalPendingInvoices, + }; + } catch (error) { + console.error('Database Error:', error); + throw new Error('Failed to fetch card data.'); + } +} + +const ITEMS_PER_PAGE = 6; +export async function fetchFilteredInvoices( + query: string, + currentPage: number, +) { + // This is equivalent to in fetch(..., {cache: 'no-store'}). + connection() + + const offset = (currentPage - 1) * ITEMS_PER_PAGE; + + try { + const invoices = await sql` + SELECT + invoices.id, + invoices.amount, + invoices.date, + invoices.status, + customers.name, + customers.email, + customers.image_url + FROM invoices + JOIN customers ON invoices.customer_id = customers.id + WHERE + customers.name ILIKE ${`%${query}%`} OR + customers.email ILIKE ${`%${query}%`} OR + invoices.amount::text ILIKE ${`%${query}%`} OR + invoices.date::text ILIKE ${`%${query}%`} OR + invoices.status ILIKE ${`%${query}%`} + ORDER BY invoices.date DESC + LIMIT ${ITEMS_PER_PAGE} OFFSET ${offset} + ` as postgres.RowList<InvoicesTable[]>; + + return invoices; + } catch (error) { + console.error('Database Error:', error); + throw new Error('Failed to fetch invoices.'); + } +} + +export async function fetchInvoicesPages(query: string) { + // This is equivalent to in fetch(..., {cache: 'no-store'}). + connection() + try { + const count = await sql`SELECT COUNT(*) + FROM invoices + JOIN customers ON invoices.customer_id = customers.id + WHERE + customers.name ILIKE ${`%${query}%`} OR + customers.email ILIKE ${`%${query}%`} OR + invoices.amount::text ILIKE ${`%${query}%`} OR + invoices.date::text ILIKE ${`%${query}%`} OR + invoices.status ILIKE ${`%${query}%`} + `; + + const totalPages = Math.ceil(Number(count.at(0)?.count) / ITEMS_PER_PAGE); + return totalPages; + } catch (error) { + console.error('Database Error:', error); + throw new Error('Failed to fetch total number of invoices.'); + } +} + +export async function fetchInvoiceById(id: string) { + // This is equivalent to in fetch(..., {cache: 'no-store'}). + connection() + try { + const data = await sql` + SELECT + invoices.id, + invoices.customer_id, + invoices.amount, + invoices.status + FROM invoices + WHERE invoices.id = ${id}; + ` as postgres.RowList<InvoiceForm[]>; + + const invoice = data.map((invoice) => ({ + ...invoice, + // Convert amount from cents to dollars + amount: invoice.amount / 100, + })); + + return invoice[0]; + } catch (error) { + console.error('Database Error:', error); + throw new Error('Failed to fetch invoice.'); + } +} + +export async function fetchCustomers() { + // This is equivalent to in fetch(..., {cache: 'no-store'}). + connection() + try { + const data = await sql` + SELECT + id, + name + FROM customers + ORDER BY name ASC + ` as postgres.RowList<CustomerField[]>; + + return data; + } catch (err) { + console.error('Database Error:', err); + throw new Error('Failed to fetch all customers.'); + } +} + +export async function fetchFilteredCustomers(query: string) { + // This is equivalent to in fetch(..., {cache: 'no-store'}). + connection() + try { + const data = await sql` + SELECT + customers.id, + customers.name, + customers.email, + customers.image_url, + COUNT(invoices.id) AS total_invoices, + SUM(CASE WHEN invoices.status = 'pending' THEN invoices.amount ELSE 0 END) AS total_pending, + SUM(CASE WHEN invoices.status = 'paid' THEN invoices.amount ELSE 0 END) AS total_paid + FROM customers + LEFT JOIN invoices ON customers.id = invoices.customer_id + WHERE + customers.name ILIKE ${`%${query}%`} OR + customers.email ILIKE ${`%${query}%`} + GROUP BY customers.id, customers.name, customers.email, customers.image_url + ORDER BY customers.name ASC + ` as postgres.RowList<CustomersTableType[]>; + + const customers = data.map((customer) => ({ + ...customer, + total_pending: formatCurrency(customer.total_pending), + total_paid: formatCurrency(customer.total_paid), + })); + + return customers; + } catch (err) { + console.error('Database Error:', err); + throw new Error('Failed to fetch customer table.'); + } +} + +export async function getUser(email: string) { + try { + const user = await sql`SELECT * FROM users WHERE email=${email}`; + return user.at(0) as User; + } catch (error) { + console.error('Failed to fetch user:', error); + throw new Error('Failed to fetch user.'); + } +} diff --git a/src/app/lib/definitions.ts b/src/app/lib/definitions.ts new file mode 100644 index 0000000..e439b66 --- /dev/null +++ b/src/app/lib/definitions.ts @@ -0,0 +1,86 @@ +// This file contains type definitions for your data. +// It describes the shape of the data, and what data type each property should accept. +// For simplicity of teaching, we're manually defining these types. +// However, these types are generated automatically if you're using an ORM such as Prisma. +export type User = { + id: string; + name: string; + email: string; + password: string; +}; + +export type Customer = { + id: string; + name: string; + email: string; + image_url: string; +}; + +export type Invoice = { + id: string; // Will be created on the database + customer_id: string; + amount: number; // Stored in cents + status: 'pending' | 'paid'; + date: string; +}; + +export type Revenue = { + month: string; + revenue: number; +}; + +export type LatestInvoice = { + id: string; + name: string; + image_url: string; + email: string; + amount: string; +}; + +// The database returns a number for amount, but we later format it to a string with the formatCurrency function +export type LatestInvoiceRaw = Omit<LatestInvoice, 'amount'> & { + amount: number; +}; + +export type InvoicesTable = { + id: string; + customer_id: string; + name: string; + email: string; + image_url: string; + date: string; + amount: number; + status: 'pending' | 'paid'; +}; + +export type CustomersTableType = { + id: string; + name: string; + email: string; + image_url: string; + total_invoices: number; + total_pending: number; + total_paid: number; +}; + +export type FormattedCustomersTable = { + id: string; + name: string; + email: string; + image_url: string; + total_invoices: number; + total_pending: string; + total_paid: string; +}; + +export type CustomerField = { + id: string; + name: string; +}; + +export type InvoiceForm = { + id: string; + customer_id: string; + amount: number; + status: 'pending' | 'paid'; +}; diff --git a/src/app/lib/placeholder-data.js b/src/app/lib/placeholder-data.js new file mode 100644 index 0000000..15a4156 --- /dev/null +++ b/src/app/lib/placeholder-data.js @@ -0,0 +1,188 @@ +// This file contains placeholder data that you'll be replacing with real data in the Data Fetching chapter: +// https://nextjs.org/learn/dashboard-app/fetching-data +const users = [ + { + id: '410544b2-4001-4271-9855-fec4b6a6442a', + name: 'User', + email: 'user@nextmail.com', + password: '123456', + }, +]; + +const customers = [ + { + id: '3958dc9e-712f-4377-85e9-fec4b6a6442a', + name: 'Delba de Oliveira', + email: 'delba@oliveira.com', + image_url: '/customers/delba-de-oliveira.png', + }, + { + id: '3958dc9e-742f-4377-85e9-fec4b6a6442a', + name: 'Lee Robinson', + email: 'lee@robinson.com', + image_url: '/customers/lee-robinson.png', + }, + { + id: '3958dc9e-737f-4377-85e9-fec4b6a6442a', + name: 'Hector Simpson', + email: 'hector@simpson.com', + image_url: '/customers/hector-simpson.png', + }, + { + id: '50ca3e18-62cd-11ee-8c99-0242ac120002', + name: 'Steven Tey', + email: 'steven@tey.com', + image_url: '/customers/steven-tey.png', + }, + { + id: '3958dc9e-787f-4377-85e9-fec4b6a6442a', + name: 'Steph Dietz', + email: 'steph@dietz.com', + image_url: '/customers/steph-dietz.png', + }, + { + id: '76d65c26-f784-44a2-ac19-586678f7c2f2', + name: 'Michael Novotny', + email: 'michael@novotny.com', + image_url: '/customers/michael-novotny.png', + }, + { + id: 'd6e15727-9fe1-4961-8c5b-ea44a9bd81aa', + name: 'Evil Rabbit', + email: 'evil@rabbit.com', + image_url: '/customers/evil-rabbit.png', + }, + { + id: '126eed9c-c90c-4ef6-a4a8-fcf7408d3c66', + name: 'Emil Kowalski', + email: 'emil@kowalski.com', + image_url: '/customers/emil-kowalski.png', + }, + { + id: 'CC27C14A-0ACF-4F4A-A6C9-D45682C144B9', + name: 'Amy Burns', + email: 'amy@burns.com', + image_url: '/customers/amy-burns.png', + }, + { + id: '13D07535-C59E-4157-A011-F8D2EF4E0CBB', + name: 'Balazs Orban', + email: 'balazs@orban.com', + image_url: '/customers/balazs-orban.png', + }, +]; + +const invoices = [ + { + customer_id: customers[0].id, + amount: 15795, + status: 'pending', + date: '2022-12-06', + }, + { + customer_id: customers[1].id, + amount: 20348, + status: 'pending', + date: '2022-11-14', + }, + { + customer_id: customers[4].id, + amount: 3040, + status: 'paid', + date: '2022-10-29', + }, + { + customer_id: customers[3].id, + amount: 44800, + status: 'paid', + date: '2023-09-10', + }, + { + customer_id: customers[5].id, + amount: 34577, + status: 'pending', + date: '2023-08-05', + }, + { + customer_id: customers[7].id, + amount: 54246, + status: 'pending', + date: '2023-07-16', + }, + { + customer_id: customers[6].id, + amount: 666, + status: 'pending', + date: '2023-06-27', + }, + { + customer_id: customers[3].id, + amount: 32545, + status: 'paid', + date: '2023-06-09', + }, + { + customer_id: customers[4].id, + amount: 1250, + status: 'paid', + date: '2023-06-17', + }, + { + customer_id: customers[5].id, + amount: 8546, + status: 'paid', + date: '2023-06-07', + }, + { + customer_id: customers[1].id, + amount: 500, + status: 'paid', + date: '2023-08-19', + }, + { + customer_id: customers[5].id, + amount: 8945, + status: 'paid', + date: '2023-06-03', + }, + { + customer_id: customers[2].id, + amount: 8945, + status: 'paid', + date: '2023-06-18', + }, + { + customer_id: customers[0].id, + amount: 8945, + status: 'paid', + date: '2023-10-04', + }, + { + customer_id: customers[2].id, + amount: 1000, + status: 'paid', + date: '2022-06-05', + }, +]; + +const revenue = [ + { month: 'Jan', revenue: 2000 }, + { month: 'Feb', revenue: 1800 }, + { month: 'Mar', revenue: 2200 }, + { month: 'Apr', revenue: 2500 }, + { month: 'May', revenue: 2300 }, + { month: 'Jun', revenue: 3200 }, + { month: 'Jul', revenue: 3500 }, + { month: 'Aug', revenue: 3700 }, + { month: 'Sep', revenue: 2500 }, + { month: 'Oct', revenue: 2800 }, + { month: 'Nov', revenue: 3000 }, + { month: 'Dec', revenue: 4800 }, +]; + +module.exports = { + users, + customers, + invoices, + revenue, +}; diff --git a/src/app/lib/utils.ts b/src/app/lib/utils.ts new file mode 100644 index 0000000..b7f7cff --- /dev/null +++ b/src/app/lib/utils.ts @@ -0,0 +1,69 @@ +import { Revenue } from './definitions'; + +export const formatCurrency = (amount: number) => { + return (amount / 100).toLocaleString('en-US', { + style: 'currency', + currency: 'USD', + }); +}; + +export const formatDateToLocal = ( + dateStr: string, + locale: string = 'en-US', +) => { + const date = new Date(dateStr); + const options: Intl.DateTimeFormatOptions = { + day: 'numeric', + month: 'short', + year: 'numeric', + }; + const formatter = new Intl.DateTimeFormat(locale, options); + return formatter.format(date); +}; + +export const generateYAxis = (revenue: Revenue[]) => { + // Calculate what labels we need to display on the y-axis + // based on highest record and in 1000s + const yAxisLabels = []; + const highestRecord = Math.max(...revenue.map((month) => month.revenue)); + const topLabel = Math.ceil(highestRecord / 1000) * 1000; + + for (let i = topLabel; i >= 0; i -= 1000) { + yAxisLabels.push(`$${i / 1000}K`); + } + + return { yAxisLabels, topLabel }; +}; + +export const generatePagination = (currentPage: number, totalPages: number) => { + // If the total number of pages is 7 or less, + // display all pages without any ellipsis. + if (totalPages <= 7) { + return Array.from({ length: totalPages }, (_, i) => i + 1); + } + + // If the current page is among the first 3 pages, + // show the first 3, an ellipsis, and the last 2 pages. + if (currentPage <= 3) { + return [1, 2, 3, '...', totalPages - 1, totalPages]; + } + + // If the current page is among the last 3 pages, + // show the first 2, an ellipsis, and the last 3 pages. + if (currentPage >= totalPages - 2) { + return [1, 2, '...', totalPages - 2, totalPages - 1, totalPages]; + } + + // If the current page is somewhere in the middle, + // show the first page, an ellipsis, the current page and its neighbors, + // another ellipsis, and the last page. + return [ + 1, + '...', + currentPage - 1, + currentPage, + currentPage + 1, + '...', + totalPages, + ]; +}; diff --git a/src/bootstrap/db/db.ts b/src/bootstrap/db/db.ts new file mode 100644 index 0000000..dbcd877 --- /dev/null +++ b/src/bootstrap/db/db.ts @@ -0,0 +1,13 @@ +import postgres from "postgres"; + + +const envs = process.env; +const dbConfigs = { + host: envs.POSTGRES_HOST, + port: Number(envs.POSTGRES_PORT), + username: envs.POSTGRES_USER, + password: envs.POSTGRES_PASS, + database: envs.POSTGRES_DB, +} + +export const sql = postgres(dbConfigs); \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 9b2101a..ee61d15 100644 --- a/yarn.lock +++ b/yarn.lock @@ -46,6 +46,11 @@ resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.57.1.tgz#de633db3ec2ef6a3c89e2f19038063e8a122e2c2" integrity sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q== +"@heroicons/react@^2.1.5": + version "2.1.5" + resolved "https://registry.yarnpkg.com/@heroicons/react/-/react-2.1.5.tgz#1e13f34976cc542deae92353c01c8b3d7942e9ba" + integrity sha512-FuzFN+BsHa+7OxbvAERtgBTNeZpUjgM/MIizfVkSCL2/edriN0Hx/DWRCR//aPYwO5QX/YlgLGXk+E3PcfZwjA== + "@humanwhocodes/config-array@^0.13.0": version "0.13.0" resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.13.0.tgz#fb907624df3256d04b9aa2df50d7aa97ec648748" @@ -3161,3 +3166,8 @@ yocto-queue@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== + +zod@^3.23.8: + version "3.23.8" + resolved "https://registry.yarnpkg.com/zod/-/zod-3.23.8.tgz#e37b957b5d52079769fb8097099b592f0ef4067d" + integrity sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g== -- 2.39.5 From a9bb5883656e5c94611af06cc8a2bd669f47e7ef Mon Sep 17 00:00:00 2001 From: behnam <behnamrahimpour74@gmail.com> Date: Fri, 1 Nov 2024 12:39:02 +0300 Subject: [PATCH 06/37] Update next to latest --- package.json | 2 +- yarn.lock | 110 +++++++++++++++++++++++++-------------------------- 2 files changed, 56 insertions(+), 56 deletions(-) diff --git a/package.json b/package.json index 0cd01c1..a804e40 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,7 @@ "class-variance-authority": "^0.7.0", "clsx": "^2.1.1", "lucide-react": "^0.454.0", - "next": "15.0.1", + "next": "15.0.2", "postgres": "^3.4.5", "react": "19.0.0-rc-69d4b800-20241021", "react-dom": "19.0.0-rc-69d4b800-20241021", diff --git a/yarn.lock b/yarn.lock index ee61d15..80c25e6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -242,10 +242,10 @@ semver "^7.3.5" tar "^6.1.11" -"@next/env@15.0.1": - version "15.0.1" - resolved "https://registry.yarnpkg.com/@next/env/-/env-15.0.1.tgz#660fe9303e255cec112d3f4198d2897a24bc60b3" - integrity sha512-lc4HeDUKO9gxxlM5G2knTRifqhsY6yYpwuHspBZdboZe0Gp+rZHBNNSIjmQKDJIdRXiXGyVnSD6gafrbQPvILQ== +"@next/env@15.0.2": + version "15.0.2" + resolved "https://registry.yarnpkg.com/@next/env/-/env-15.0.2.tgz#4e921af3faf8a16c6be98ec6a81a32a40050a8b7" + integrity sha512-c0Zr0ModK5OX7D4ZV8Jt/wqoXtitLNPwUfG9zElCZztdaZyNVnN40rDXVZ/+FGuR4CcNV5AEfM6N8f+Ener7Dg== "@next/eslint-plugin-next@15.0.1": version "15.0.1" @@ -254,45 +254,45 @@ dependencies: fast-glob "3.3.1" -"@next/swc-darwin-arm64@15.0.1": - version "15.0.1" - resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-15.0.1.tgz#b80a25f1569bd0ca03eca9473f7e93e64937e404" - integrity sha512-C9k/Xv4sxkQRTA37Z6MzNq3Yb1BJMmSqjmwowoWEpbXTkAdfOwnoKOpAb71ItSzoA26yUTIo6ZhN8rKGu4ExQw== +"@next/swc-darwin-arm64@15.0.2": + version "15.0.2" + resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-15.0.2.tgz#66f84083f1f564d09bbacff8d6b24bd833783bef" + integrity sha512-GK+8w88z+AFlmt+ondytZo2xpwlfAR8U6CRwXancHImh6EdGfHMIrTSCcx5sOSBei00GyLVL0ioo1JLKTfprgg== -"@next/swc-darwin-x64@15.0.1": - version "15.0.1" - resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-15.0.1.tgz#00dcf79ec7c638a85c3b9ff2e2de2bfb09c1c250" - integrity sha512-uHl13HXOuq1G7ovWFxCACDJHTSDVbn/sbLv8V1p+7KIvTrYQ5HNoSmKBdYeEKRRCbEmd+OohOgg9YOp8Ux3MBg== +"@next/swc-darwin-x64@15.0.2": + version "15.0.2" + resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-15.0.2.tgz#1aef085642f363b89acf264cf1b9848632b52914" + integrity sha512-KUpBVxIbjzFiUZhiLIpJiBoelqzQtVZbdNNsehhUn36e2YzKHphnK8eTUW1s/4aPy5kH/UTid8IuVbaOpedhpw== -"@next/swc-linux-arm64-gnu@15.0.1": - version "15.0.1" - resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-15.0.1.tgz#faab5f7ffcc6d1a15e8dea1cb9953966658b39bf" - integrity sha512-LvyhvxHOihFTEIbb35KxOc3q8w8G4xAAAH/AQnsYDEnOvwawjL2eawsB59AX02ki6LJdgDaHoTEnC54Gw+82xw== +"@next/swc-linux-arm64-gnu@15.0.2": + version "15.0.2" + resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-15.0.2.tgz#203b41742e60642587e004773a8c203053b6832e" + integrity sha512-9J7TPEcHNAZvwxXRzOtiUvwtTD+fmuY0l7RErf8Yyc7kMpE47MIQakl+3jecmkhOoIyi/Rp+ddq7j4wG6JDskQ== -"@next/swc-linux-arm64-musl@15.0.1": - version "15.0.1" - resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-15.0.1.tgz#97abada9a782ab5b3cb42cf0d4799cbc2e733351" - integrity sha512-vFmCGUFNyk/A5/BYcQNhAQqPIw01RJaK6dRO+ZEhz0DncoW+hJW1kZ8aH2UvTX27zPq3m85zN5waMSbZEmANcQ== +"@next/swc-linux-arm64-musl@15.0.2": + version "15.0.2" + resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-15.0.2.tgz#d256932ec11051f376348862508be9017b23f3d8" + integrity sha512-BjH4ZSzJIoTTZRh6rG+a/Ry4SW0HlizcPorqNBixBWc3wtQtj4Sn9FnRZe22QqrPnzoaW0ctvSz4FaH4eGKMww== -"@next/swc-linux-x64-gnu@15.0.1": - version "15.0.1" - resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-15.0.1.tgz#548bd47c49fe6d819302139aff8766eb704322e2" - integrity sha512-5by7IYq0NCF8rouz6Qg9T97jYU68kaClHPfGpQG2lCZpSYHtSPQF1kjnqBTd34RIqPKMbCa4DqCufirgr8HM5w== +"@next/swc-linux-x64-gnu@15.0.2": + version "15.0.2" + resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-15.0.2.tgz#06c52a23a7e13d5ccd0ded1cf295b32df58e0932" + integrity sha512-i3U2TcHgo26sIhcwX/Rshz6avM6nizrZPvrDVDY1bXcLH1ndjbO8zuC7RoHp0NSK7wjJMPYzm7NYL1ksSKFreA== -"@next/swc-linux-x64-musl@15.0.1": - version "15.0.1" - resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-15.0.1.tgz#84423fbd3a058dd6ae8322e530878f0ec7a1027a" - integrity sha512-lmYr6H3JyDNBJLzklGXLfbehU3ay78a+b6UmBGlHls4xhDXBNZfgb0aI67sflrX+cGBnv1LgmWzFlYrAYxS1Qw== +"@next/swc-linux-x64-musl@15.0.2": + version "15.0.2" + resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-15.0.2.tgz#eb70a81a1c66d4935d50bf6fe1021e440f27fe9f" + integrity sha512-AMfZfSVOIR8fa+TXlAooByEF4OB00wqnms1sJ1v+iu8ivwvtPvnkwdzzFMpsK5jA2S9oNeeQ04egIWVb4QWmtQ== -"@next/swc-win32-arm64-msvc@15.0.1": - version "15.0.1" - resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-15.0.1.tgz#723c2ced12a998fb40dc901b8faea9170e788c2f" - integrity sha512-DS8wQtl6diAj0eZTdH0sefykm4iXMbHT4MOvLwqZiIkeezKpkgPFcEdFlz3vKvXa2R/2UEgMh48z1nEpNhjeOQ== +"@next/swc-win32-arm64-msvc@15.0.2": + version "15.0.2" + resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-15.0.2.tgz#29a763bdc3a1281633af10cf8428e916e02f079a" + integrity sha512-JkXysDT0/hEY47O+Hvs8PbZAeiCQVxKfGtr4GUpNAhlG2E0Mkjibuo8ryGD29Qb5a3IOnKYNoZlh/MyKd2Nbww== -"@next/swc-win32-x64-msvc@15.0.1": - version "15.0.1" - resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.0.1.tgz#ec7e3befc0bcc47527537b1eda2b3745beb15a09" - integrity sha512-4Ho2ggvDdMKlZ/0e9HNdZ9ngeaBwtc+2VS5oCeqrbXqOgutX6I4U2X/42VBw0o+M5evn4/7v3zKgGHo+9v/VjA== +"@next/swc-win32-x64-msvc@15.0.2": + version "15.0.2" + resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.0.2.tgz#0f70d8146990886a85099875353539fc6dd68338" + integrity sha512-foaUL0NqJY/dX0Pi/UcZm5zsmSk5MtP/gxx3xOPyREkMFN+CTjctPfu3QaqrQHinaKdPnMWPJDKt4VjDfTBe/Q== "@nodelib/fs.scandir@2.1.5": version "2.1.5" @@ -745,9 +745,9 @@ camelcase-css@^2.0.1: integrity sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA== caniuse-lite@^1.0.30001579: - version "1.0.30001674" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001674.tgz#eb200a716c3e796d33d30b9c8890517a72f862c8" - integrity sha512-jOsKlZVRnzfhLojb+Ykb+gyUSp9Xb57So+fAiFlLzzTKpqg8xxSav0e40c8/4F/v9N8QSvrRRaLeVzQbLqomYw== + version "1.0.30001676" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001676.tgz#fe133d41fe74af8f7cc93b8a714c3e86a86e6f04" + integrity sha512-Qz6zwGCiPghQXGJvgQAem79esjitvJ+CxSbSQkW9H/UX5hg8XM88d4lp2W+MEQ81j+Hip58Il+jGVdazk1z9cw== chalk@^4.0.0: version "4.1.2" @@ -2104,12 +2104,12 @@ natural-compare@^1.4.0: resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== -next@15.0.1: - version "15.0.1" - resolved "https://registry.yarnpkg.com/next/-/next-15.0.1.tgz#a0e8eda35d803cb7f8092b2a2eb9d072e22bf21d" - integrity sha512-PSkFkr/w7UnFWm+EP8y/QpHrJXMqpZzAXpergB/EqLPOh4SGPJXv1wj4mslr2hUZBAS9pX7/9YLIdxTv6fwytw== +next@15.0.2: + version "15.0.2" + resolved "https://registry.yarnpkg.com/next/-/next-15.0.2.tgz#4a2224c007856118010b8cef5e9b2383cd743388" + integrity sha512-rxIWHcAu4gGSDmwsELXacqAPUk+j8dV/A9cDF5fsiCMpkBDYkO2AEaL1dfD+nNmDiU6QMCFN8Q30VEKapT9UHQ== dependencies: - "@next/env" "15.0.1" + "@next/env" "15.0.2" "@swc/counter" "0.1.3" "@swc/helpers" "0.5.13" busboy "1.6.0" @@ -2117,14 +2117,14 @@ next@15.0.1: postcss "8.4.31" styled-jsx "5.1.6" optionalDependencies: - "@next/swc-darwin-arm64" "15.0.1" - "@next/swc-darwin-x64" "15.0.1" - "@next/swc-linux-arm64-gnu" "15.0.1" - "@next/swc-linux-arm64-musl" "15.0.1" - "@next/swc-linux-x64-gnu" "15.0.1" - "@next/swc-linux-x64-musl" "15.0.1" - "@next/swc-win32-arm64-msvc" "15.0.1" - "@next/swc-win32-x64-msvc" "15.0.1" + "@next/swc-darwin-arm64" "15.0.2" + "@next/swc-darwin-x64" "15.0.2" + "@next/swc-linux-arm64-gnu" "15.0.2" + "@next/swc-linux-arm64-musl" "15.0.2" + "@next/swc-linux-x64-gnu" "15.0.2" + "@next/swc-linux-x64-musl" "15.0.2" + "@next/swc-win32-arm64-msvc" "15.0.2" + "@next/swc-win32-x64-msvc" "15.0.2" sharp "^0.33.5" node-addon-api@^5.0.0: @@ -2948,9 +2948,9 @@ tslib@^1.9.3: integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== tslib@^2.4.0: - version "2.8.0" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.0.tgz#d124c86c3c05a40a91e6fdea4021bd31d377971b" - integrity sha512-jWVzBLplnCmoaTr13V9dYbiQ99wvZRd0vNWaDRg+aVYRcjDF3nDksxFDE/+fkXnKhpnUUkmx5pK/v8mCtLVqZA== + version "2.8.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" + integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== tsyringe@^4.8.0: version "4.8.0" -- 2.39.5 From 7b2ec83068c5ad05b99d12d15c0fb00394cacee9 Mon Sep 17 00:00:00 2001 From: behnam <behnamrahimpour74@gmail.com> Date: Fri, 1 Nov 2024 14:54:59 +0300 Subject: [PATCH 07/37] Add domain of customer --- package.json | 10 +- src/app/lib/data.ts | 31 - src/app/lib/definitions.ts | 16 - src/feature/common/server-di.ts | 5 +- src/feature/customer/customer-key.ts | 1 + .../customer/data/module/customer-di.ts | 13 + .../customer/domain/entity/customer.ts | 37 + .../customer/domain/i-repo/customer-repo.ts | 7 + .../domain/usecase/fetch-customers-usecase.ts | 12 + .../customer/customer-fake-factory.ts | 21 + src/test/common/mock/mock-di.ts | 7 + src/test/common/mock/mock-factory.ts | 5 + src/test/setup.ts | 1 + .../usecase/fetch-customers-usecase.test.ts | 48 + tsconfig.json | 1 + vite.config.ts | 15 + yarn.lock | 1125 ++++++++++++++++- 17 files changed, 1291 insertions(+), 64 deletions(-) create mode 100644 src/feature/customer/customer-key.ts create mode 100644 src/feature/customer/data/module/customer-di.ts create mode 100644 src/feature/customer/domain/entity/customer.ts create mode 100644 src/feature/customer/domain/i-repo/customer-repo.ts create mode 100644 src/feature/customer/domain/usecase/fetch-customers-usecase.ts create mode 100644 src/test/common/fake-factory/customer/customer-fake-factory.ts create mode 100644 src/test/common/mock/mock-di.ts create mode 100644 src/test/common/mock/mock-factory.ts create mode 100644 src/test/setup.ts create mode 100644 src/test/unit/feature/customer/domain/usecase/fetch-customers-usecase.test.ts create mode 100644 vite.config.ts diff --git a/package.json b/package.json index a804e40..2a11c38 100644 --- a/package.json +++ b/package.json @@ -7,6 +7,7 @@ "build": "next build", "start": "next start --port 4000", "lint": "next lint", + "test": "vitest", "seed": "node -r dotenv/config ./src/bootstrap/db/seed.js" }, "dependencies": { @@ -26,15 +27,22 @@ "zod": "^3.23.8" }, "devDependencies": { + "@faker-js/faker": "^9.1.0", + "@testing-library/dom": "^10.4.0", + "@testing-library/react": "^16.0.1", "@types/node": "^20", "@types/react": "^18", "@types/react-dom": "^18", + "@vitejs/plugin-react": "^4.3.3", "bcrypt": "^5.1.1", "dotenv": "^16.4.5", "eslint": "^8", "eslint-config-next": "15.0.1", + "jsdom": "^25.0.1", + "moq.ts": "^10.0.8", "postcss": "^8", "tailwindcss": "^3.4.1", - "typescript": "^5" + "typescript": "^5", + "vitest": "^2.1.4" } } diff --git a/src/app/lib/data.ts b/src/app/lib/data.ts index c655f10..3afe7f1 100644 --- a/src/app/lib/data.ts +++ b/src/app/lib/data.ts @@ -1,10 +1,8 @@ import { sql } from '@/bootstrap/db/db'; import { - CustomerField, CustomersTableType, InvoiceForm, InvoicesTable, - User, Revenue, Invoice, Customer, @@ -189,25 +187,6 @@ export async function fetchInvoiceById(id: string) { } } -export async function fetchCustomers() { - // This is equivalent to in fetch(..., {cache: 'no-store'}). - connection() - try { - const data = await sql` - SELECT - id, - name - FROM customers - ORDER BY name ASC - ` as postgres.RowList<CustomerField[]>; - - return data; - } catch (err) { - console.error('Database Error:', err); - throw new Error('Failed to fetch all customers.'); - } -} - export async function fetchFilteredCustomers(query: string) { // This is equivalent to in fetch(..., {cache: 'no-store'}). connection() @@ -242,13 +221,3 @@ export async function fetchFilteredCustomers(query: string) { throw new Error('Failed to fetch customer table.'); } } - -export async function getUser(email: string) { - try { - const user = await sql`SELECT * FROM users WHERE email=${email}`; - return user.at(0) as User; - } catch (error) { - console.error('Failed to fetch user:', error); - throw new Error('Failed to fetch user.'); - } -} diff --git a/src/app/lib/definitions.ts b/src/app/lib/definitions.ts index e439b66..0860139 100644 --- a/src/app/lib/definitions.ts +++ b/src/app/lib/definitions.ts @@ -1,14 +1,3 @@ -// This file contains type definitions for your data. -// It describes the shape of the data, and what data type each property should accept. -// For simplicity of teaching, we're manually defining these types. -// However, these types are generated automatically if you're using an ORM such as Prisma. -export type User = { - id: string; - name: string; - email: string; - password: string; -}; - export type Customer = { id: string; name: string; @@ -73,11 +62,6 @@ export type FormattedCustomersTable = { total_paid: string; }; -export type CustomerField = { - id: string; - name: string; -}; - export type InvoiceForm = { id: string; customer_id: string; diff --git a/src/feature/common/server-di.ts b/src/feature/common/server-di.ts index 54200bd..78095a9 100644 --- a/src/feature/common/server-di.ts +++ b/src/feature/common/server-di.ts @@ -1,10 +1,13 @@ +import { customerKey } from "@/feature/customer/customer-key"; +import getCustomerDi from "@/feature/customer/data/module/customer-di"; import { testModuleKey } from "@/feature/domain/test/test-module-key"; import getTestModule from "@/feature/infra/test/module/test-module"; import { DependencyContainer } from "tsyringe"; export default function serverDi(module: string): DependencyContainer { const getDi = { - [testModuleKey]: getTestModule + [testModuleKey]: getTestModule, + [customerKey]: getCustomerDi }[module] if (!getDi) throw new Error("Server Di didn't found for module: " + module) diff --git a/src/feature/customer/customer-key.ts b/src/feature/customer/customer-key.ts new file mode 100644 index 0000000..9ae5f45 --- /dev/null +++ b/src/feature/customer/customer-key.ts @@ -0,0 +1 @@ +export const customerKey = "customerKey" \ No newline at end of file diff --git a/src/feature/customer/data/module/customer-di.ts b/src/feature/customer/data/module/customer-di.ts new file mode 100644 index 0000000..05df3ae --- /dev/null +++ b/src/feature/customer/data/module/customer-di.ts @@ -0,0 +1,13 @@ +import di from "@/bootstrap/di/init-di"; +import fetchCustomersUsecase from "@/feature/customer/domain/usecase/fetch-customers-usecase"; +import { DependencyContainer } from "tsyringe"; + +export default function getCustomerDi(): DependencyContainer { + const customerDi = di.createChildContainer() + + customerDi.register(fetchCustomersUsecase.name, { + useValue: fetchCustomersUsecase + }) + + return customerDi +} \ No newline at end of file diff --git a/src/feature/customer/domain/entity/customer.ts b/src/feature/customer/domain/entity/customer.ts new file mode 100644 index 0000000..3b13a69 --- /dev/null +++ b/src/feature/customer/domain/entity/customer.ts @@ -0,0 +1,37 @@ +export type CustomersTableType = { + id: string; + name: string; + email: string; + image_url: string; + total_invoices: number; + total_pending: number; + total_paid: number; +}; + +export default class Customer { + id: string; + name: string; + email: string; + imageUrl: string; + totalInvoices: number; + totalPending: number; + totalPaid: number; + + constructor({ + id, + email, + imageUrl, + name, + totalInvoices, + totalPaid, + totalPending + }: Customer) { + this.id = id; + this.name = name; + this.email = email; + this.imageUrl = imageUrl; + this.totalInvoices = totalInvoices; + this.totalPaid = totalPaid; + this.totalPending = totalPending; + } +} \ No newline at end of file diff --git a/src/feature/customer/domain/i-repo/customer-repo.ts b/src/feature/customer/domain/i-repo/customer-repo.ts new file mode 100644 index 0000000..5c9cbf2 --- /dev/null +++ b/src/feature/customer/domain/i-repo/customer-repo.ts @@ -0,0 +1,7 @@ +import Customer from "@/feature/customer/domain/entity/customer" + +export default interface CustomerRepo { + fetchList(query: string): Promise<Customer[]> +} + +export const customerRepoKey = "customerRepoKey" \ No newline at end of file diff --git a/src/feature/customer/domain/usecase/fetch-customers-usecase.ts b/src/feature/customer/domain/usecase/fetch-customers-usecase.ts new file mode 100644 index 0000000..bf95239 --- /dev/null +++ b/src/feature/customer/domain/usecase/fetch-customers-usecase.ts @@ -0,0 +1,12 @@ +"use server" + +import serverDi from "@/feature/common/server-di"; +import { customerKey } from "@/feature/customer/customer-key"; +import Customer from "@/feature/customer/domain/entity/customer"; +import CustomerRepo, { customerRepoKey } from "@/feature/customer/domain/i-repo/customer-repo"; + +export default function fetchCustomersUsecase(query: string): Promise<Customer[]> { + const repo = serverDi(customerKey).resolve<CustomerRepo>(customerRepoKey) + + return repo.fetchList(query) +} \ No newline at end of file diff --git a/src/test/common/fake-factory/customer/customer-fake-factory.ts b/src/test/common/fake-factory/customer/customer-fake-factory.ts new file mode 100644 index 0000000..be69bec --- /dev/null +++ b/src/test/common/fake-factory/customer/customer-fake-factory.ts @@ -0,0 +1,21 @@ +import Customer from "@/feature/customer/domain/entity/customer"; +import { faker } from "@faker-js/faker"; + +export default class CustomerFakeFactory { + static getFakeCustomer(): Customer { + return new Customer({ + id: faker.string.uuid(), + name: faker.person.fullName(), + email: faker.internet.email(), + imageUrl: faker.image.url(), + totalInvoices: faker.number.int(), + totalPaid: faker.number.int(), + totalPending: faker.number.int(), + }) + } + + + static getFakeCustomerList(length: number = 10): Customer[] { + return Array.from({length}).map(() => CustomerFakeFactory.getFakeCustomer()) + } +} \ No newline at end of file diff --git a/src/test/common/mock/mock-di.ts b/src/test/common/mock/mock-di.ts new file mode 100644 index 0000000..3bb7d4e --- /dev/null +++ b/src/test/common/mock/mock-di.ts @@ -0,0 +1,7 @@ +import di from "@/bootstrap/di/init-di" +import * as serverDi from "@/feature/common/server-di" + +export default function mockDi() { + vi.spyOn(serverDi, "default").mockReturnValue(di) + return di +} \ No newline at end of file diff --git a/src/test/common/mock/mock-factory.ts b/src/test/common/mock/mock-factory.ts new file mode 100644 index 0000000..8635c9e --- /dev/null +++ b/src/test/common/mock/mock-factory.ts @@ -0,0 +1,5 @@ +import { Mock } from "moq.ts"; + +export function getMock<T>() { + return new Mock<T>(); +} diff --git a/src/test/setup.ts b/src/test/setup.ts new file mode 100644 index 0000000..48d5e07 --- /dev/null +++ b/src/test/setup.ts @@ -0,0 +1 @@ +import "reflect-metadata"; \ No newline at end of file diff --git a/src/test/unit/feature/customer/domain/usecase/fetch-customers-usecase.test.ts b/src/test/unit/feature/customer/domain/usecase/fetch-customers-usecase.test.ts new file mode 100644 index 0000000..7178ac2 --- /dev/null +++ b/src/test/unit/feature/customer/domain/usecase/fetch-customers-usecase.test.ts @@ -0,0 +1,48 @@ +import CustomerRepo, { customerRepoKey } from "@/feature/customer/domain/i-repo/customer-repo"; +import { getMock } from "@/test/common/mock/mock-factory"; +import { describe } from "vitest"; +import { faker } from "@faker-js/faker"; +import CustomerFakeFactory from "@/test/common/fake-factory/customer/customer-fake-factory"; +import fetchCustomersUsecase from "@/feature/customer/domain/usecase/fetch-customers-usecase"; +import mockDi from "@/test/common/mock/mock-di"; +/* -------------------------------------------------------------------------- */ +/* Faking */ +/* -------------------------------------------------------------------------- */ +const fakedCustomerList = CustomerFakeFactory.getFakeCustomerList() +/* -------------------------------------------------------------------------- */ +/* Mocking */ +/* -------------------------------------------------------------------------- */ +const customerDi = mockDi() + +const mockedFetchList = vi.fn<CustomerRepo['fetchList']>() +const MockedRepo = getMock<CustomerRepo>() +MockedRepo.setup((instance) => instance.fetchList).returns(mockedFetchList) +/* -------------------------------------------------------------------------- */ +/* DI */ +/* -------------------------------------------------------------------------- */ +customerDi.register(fetchCustomersUsecase.name, { + useValue: fetchCustomersUsecase +}) +customerDi.register(customerRepoKey, { + useValue: MockedRepo.object() +}) +/* -------------------------------------------------------------------------- */ +/* Testing */ +/* -------------------------------------------------------------------------- */ +const usecase = customerDi.resolve<typeof fetchCustomersUsecase>(fetchCustomersUsecase.name) +describe("Fetch customers", () => { + describe("On given query string", () => { + const fakedQuery = faker.person.fullName(); + describe("And returning list from repo", () => { + beforeEach(() => { + mockedFetchList.mockResolvedValue(fakedCustomerList) + }) + it("Then should return correct list of customers", async () => { + // ! Act + const response = await usecase(fakedQuery) + // ? Assert + expect(response).toEqual(fakedCustomerList) + }) + }); + }); +}); \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index d42c189..ef29509 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -15,6 +15,7 @@ "isolatedModules": true, "jsx": "preserve", "incremental": true, + "types": ["vitest/globals"], "plugins": [ { "name": "next" diff --git a/vite.config.ts b/vite.config.ts new file mode 100644 index 0000000..3676ec2 --- /dev/null +++ b/vite.config.ts @@ -0,0 +1,15 @@ +/// <reference types="vitest" /> +import { defineConfig } from "vitest/config"; +import path from 'path'; + +export default defineConfig({ + test: { + globals: true, + setupFiles: 'src/test/setup.ts', + }, + resolve: { + alias: { + '@': path.resolve(__dirname, './src'), + }, + }, +}) \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 80c25e6..1a06bc5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7,6 +7,174 @@ resolved "https://registry.yarnpkg.com/@alloc/quick-lru/-/quick-lru-5.2.0.tgz#7bf68b20c0a350f936915fcae06f58e32007ce30" integrity sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw== +"@ampproject/remapping@^2.2.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.3.0.tgz#ed441b6fa600072520ce18b43d2c8cc8caecc7f4" + integrity sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw== + dependencies: + "@jridgewell/gen-mapping" "^0.3.5" + "@jridgewell/trace-mapping" "^0.3.24" + +"@babel/code-frame@^7.10.4", "@babel/code-frame@^7.25.9", "@babel/code-frame@^7.26.0": + version "7.26.2" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.26.2.tgz#4b5fab97d33338eff916235055f0ebc21e573a85" + integrity sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ== + dependencies: + "@babel/helper-validator-identifier" "^7.25.9" + js-tokens "^4.0.0" + picocolors "^1.0.0" + +"@babel/compat-data@^7.25.9": + version "7.26.2" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.26.2.tgz#278b6b13664557de95b8f35b90d96785850bb56e" + integrity sha512-Z0WgzSEa+aUcdiJuCIqgujCshpMWgUpgOxXotrYPSA53hA3qopNaqcJpyr0hVb1FeWdnqFA35/fUtXgBK8srQg== + +"@babel/core@^7.25.2": + version "7.26.0" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.26.0.tgz#d78b6023cc8f3114ccf049eb219613f74a747b40" + integrity sha512-i1SLeK+DzNnQ3LL/CswPCa/E5u4lh1k6IAEphON8F+cXt0t9euTshDru0q7/IqMa1PMPz5RnHuHscF8/ZJsStg== + dependencies: + "@ampproject/remapping" "^2.2.0" + "@babel/code-frame" "^7.26.0" + "@babel/generator" "^7.26.0" + "@babel/helper-compilation-targets" "^7.25.9" + "@babel/helper-module-transforms" "^7.26.0" + "@babel/helpers" "^7.26.0" + "@babel/parser" "^7.26.0" + "@babel/template" "^7.25.9" + "@babel/traverse" "^7.25.9" + "@babel/types" "^7.26.0" + convert-source-map "^2.0.0" + debug "^4.1.0" + gensync "^1.0.0-beta.2" + json5 "^2.2.3" + semver "^6.3.1" + +"@babel/generator@^7.25.9", "@babel/generator@^7.26.0": + version "7.26.2" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.26.2.tgz#87b75813bec87916210e5e01939a4c823d6bb74f" + integrity sha512-zevQbhbau95nkoxSq3f/DC/SC+EEOUZd3DYqfSkMhY2/wfSeaHV1Ew4vk8e+x8lja31IbyuUa2uQ3JONqKbysw== + dependencies: + "@babel/parser" "^7.26.2" + "@babel/types" "^7.26.0" + "@jridgewell/gen-mapping" "^0.3.5" + "@jridgewell/trace-mapping" "^0.3.25" + jsesc "^3.0.2" + +"@babel/helper-compilation-targets@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.9.tgz#55af025ce365be3cdc0c1c1e56c6af617ce88875" + integrity sha512-j9Db8Suy6yV/VHa4qzrj9yZfZxhLWQdVnRlXxmKLYlhWUVB1sB2G5sxuWYXk/whHD9iW76PmNzxZ4UCnTQTVEQ== + dependencies: + "@babel/compat-data" "^7.25.9" + "@babel/helper-validator-option" "^7.25.9" + browserslist "^4.24.0" + lru-cache "^5.1.1" + semver "^6.3.1" + +"@babel/helper-module-imports@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz#e7f8d20602ebdbf9ebbea0a0751fb0f2a4141715" + integrity sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw== + dependencies: + "@babel/traverse" "^7.25.9" + "@babel/types" "^7.25.9" + +"@babel/helper-module-transforms@^7.26.0": + version "7.26.0" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz#8ce54ec9d592695e58d84cd884b7b5c6a2fdeeae" + integrity sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw== + dependencies: + "@babel/helper-module-imports" "^7.25.9" + "@babel/helper-validator-identifier" "^7.25.9" + "@babel/traverse" "^7.25.9" + +"@babel/helper-plugin-utils@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.25.9.tgz#9cbdd63a9443a2c92a725cca7ebca12cc8dd9f46" + integrity sha512-kSMlyUVdWe25rEsRGviIgOWnoT/nfABVWlqt9N19/dIPWViAOW2s9wznP5tURbs/IDuNk4gPy3YdYRgH3uxhBw== + +"@babel/helper-string-parser@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz#1aabb72ee72ed35789b4bbcad3ca2862ce614e8c" + integrity sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA== + +"@babel/helper-validator-identifier@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz#24b64e2c3ec7cd3b3c547729b8d16871f22cbdc7" + integrity sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ== + +"@babel/helper-validator-option@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz#86e45bd8a49ab7e03f276577f96179653d41da72" + integrity sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw== + +"@babel/helpers@^7.26.0": + version "7.26.0" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.26.0.tgz#30e621f1eba5aa45fe6f4868d2e9154d884119a4" + integrity sha512-tbhNuIxNcVb21pInl3ZSjksLCvgdZy9KwJ8brv993QtIVKJBBkYXz4q4ZbAv31GdnC+R90np23L5FbEBlthAEw== + dependencies: + "@babel/template" "^7.25.9" + "@babel/types" "^7.26.0" + +"@babel/parser@^7.1.0", "@babel/parser@^7.20.7", "@babel/parser@^7.25.9", "@babel/parser@^7.26.0", "@babel/parser@^7.26.2": + version "7.26.2" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.26.2.tgz#fd7b6f487cfea09889557ef5d4eeb9ff9a5abd11" + integrity sha512-DWMCZH9WA4Maitz2q21SRKHo9QXZxkDsbNZoVD62gusNtNBBqDg9i7uOhASfTfIGNzW+O+r7+jAlM8dwphcJKQ== + dependencies: + "@babel/types" "^7.26.0" + +"@babel/plugin-transform-react-jsx-self@^7.24.7": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.25.9.tgz#c0b6cae9c1b73967f7f9eb2fca9536ba2fad2858" + integrity sha512-y8quW6p0WHkEhmErnfe58r7x0A70uKphQm8Sp8cV7tjNQwK56sNVK0M73LK3WuYmsuyrftut4xAkjjgU0twaMg== + dependencies: + "@babel/helper-plugin-utils" "^7.25.9" + +"@babel/plugin-transform-react-jsx-source@^7.24.7": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.25.9.tgz#4c6b8daa520b5f155b5fb55547d7c9fa91417503" + integrity sha512-+iqjT8xmXhhYv4/uiYd8FNQsraMFZIfxVSqxxVSZP0WbbSAWvBXAul0m/zu+7Vv4O/3WtApy9pmaTMiumEZgfg== + dependencies: + "@babel/helper-plugin-utils" "^7.25.9" + +"@babel/runtime@^7.12.5": + version "7.26.0" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.26.0.tgz#8600c2f595f277c60815256418b85356a65173c1" + integrity sha512-FDSOghenHTiToteC/QRlv2q3DhPZ/oOXTBoirfWNx1Cx3TMVcGWQtMMmQcSvb/JjpNeGzx8Pq/b4fKEJuWm1sw== + dependencies: + regenerator-runtime "^0.14.0" + +"@babel/template@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.25.9.tgz#ecb62d81a8a6f5dc5fe8abfc3901fc52ddf15016" + integrity sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg== + dependencies: + "@babel/code-frame" "^7.25.9" + "@babel/parser" "^7.25.9" + "@babel/types" "^7.25.9" + +"@babel/traverse@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.25.9.tgz#a50f8fe49e7f69f53de5bea7e413cd35c5e13c84" + integrity sha512-ZCuvfwOwlz/bawvAuvcj8rrithP2/N55Tzz342AkTvq4qaWbGfmCk/tKhNaV2cthijKrPAA8SRJV5WWe7IBMJw== + dependencies: + "@babel/code-frame" "^7.25.9" + "@babel/generator" "^7.25.9" + "@babel/parser" "^7.25.9" + "@babel/template" "^7.25.9" + "@babel/types" "^7.25.9" + debug "^4.3.1" + globals "^11.1.0" + +"@babel/types@^7.0.0", "@babel/types@^7.20.7", "@babel/types@^7.25.9", "@babel/types@^7.26.0": + version "7.26.0" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.26.0.tgz#deabd08d6b753bc8e0f198f8709fb575e31774ff" + integrity sha512-Z/yiTPj+lDVnF7lWeKCIJzaIkI0vYO87dMpZ4bg4TDrFe4XXLFWL1TbXU27gBP3QccxV9mZICCrnjnYlJjXHOA== + dependencies: + "@babel/helper-string-parser" "^7.25.9" + "@babel/helper-validator-identifier" "^7.25.9" + "@emnapi/runtime@^1.2.0": version "1.3.1" resolved "https://registry.yarnpkg.com/@emnapi/runtime/-/runtime-1.3.1.tgz#0fcaa575afc31f455fd33534c19381cfce6c6f60" @@ -14,6 +182,121 @@ dependencies: tslib "^2.4.0" +"@esbuild/aix-ppc64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz#c7184a326533fcdf1b8ee0733e21c713b975575f" + integrity sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ== + +"@esbuild/android-arm64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz#09d9b4357780da9ea3a7dfb833a1f1ff439b4052" + integrity sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A== + +"@esbuild/android-arm@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.21.5.tgz#9b04384fb771926dfa6d7ad04324ecb2ab9b2e28" + integrity sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg== + +"@esbuild/android-x64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.21.5.tgz#29918ec2db754cedcb6c1b04de8cd6547af6461e" + integrity sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA== + +"@esbuild/darwin-arm64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz#e495b539660e51690f3928af50a76fb0a6ccff2a" + integrity sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ== + +"@esbuild/darwin-x64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz#c13838fa57372839abdddc91d71542ceea2e1e22" + integrity sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw== + +"@esbuild/freebsd-arm64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz#646b989aa20bf89fd071dd5dbfad69a3542e550e" + integrity sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g== + +"@esbuild/freebsd-x64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz#aa615cfc80af954d3458906e38ca22c18cf5c261" + integrity sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ== + +"@esbuild/linux-arm64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz#70ac6fa14f5cb7e1f7f887bcffb680ad09922b5b" + integrity sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q== + +"@esbuild/linux-arm@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz#fc6fd11a8aca56c1f6f3894f2bea0479f8f626b9" + integrity sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA== + +"@esbuild/linux-ia32@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz#3271f53b3f93e3d093d518d1649d6d68d346ede2" + integrity sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg== + +"@esbuild/linux-loong64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz#ed62e04238c57026aea831c5a130b73c0f9f26df" + integrity sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg== + +"@esbuild/linux-mips64el@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz#e79b8eb48bf3b106fadec1ac8240fb97b4e64cbe" + integrity sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg== + +"@esbuild/linux-ppc64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz#5f2203860a143b9919d383ef7573521fb154c3e4" + integrity sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w== + +"@esbuild/linux-riscv64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz#07bcafd99322d5af62f618cb9e6a9b7f4bb825dc" + integrity sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA== + +"@esbuild/linux-s390x@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz#b7ccf686751d6a3e44b8627ababc8be3ef62d8de" + integrity sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A== + +"@esbuild/linux-x64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz#6d8f0c768e070e64309af8004bb94e68ab2bb3b0" + integrity sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ== + +"@esbuild/netbsd-x64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz#bbe430f60d378ecb88decb219c602667387a6047" + integrity sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg== + +"@esbuild/openbsd-x64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz#99d1cf2937279560d2104821f5ccce220cb2af70" + integrity sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow== + +"@esbuild/sunos-x64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz#08741512c10d529566baba837b4fe052c8f3487b" + integrity sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg== + +"@esbuild/win32-arm64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz#675b7385398411240735016144ab2e99a60fc75d" + integrity sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A== + +"@esbuild/win32-ia32@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz#1bfc3ce98aa6ca9a0969e4d2af72144c59c1193b" + integrity sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA== + +"@esbuild/win32-x64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz#acad351d582d157bb145535db2a6ff53dd514b5c" + integrity sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw== + "@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0": version "4.4.1" resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz#d1145bf2c20132d6400495d6df4bf59362fd9d56" @@ -46,6 +329,11 @@ resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.57.1.tgz#de633db3ec2ef6a3c89e2f19038063e8a122e2c2" integrity sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q== +"@faker-js/faker@^9.1.0": + version "9.1.0" + resolved "https://registry.yarnpkg.com/@faker-js/faker/-/faker-9.1.0.tgz#5d7957df87e2fb0eee5dcfd311ba83b34ec8eead" + integrity sha512-GJvX9iM9PBtKScJVlXQ0tWpihK3i0pha/XAhzQa1hPK/ILLa1Wq3I63Ij7lRtqTwmdTxRCyrUhLC5Sly9SLbug== + "@heroicons/react@^2.1.5": version "2.1.5" resolved "https://registry.yarnpkg.com/@heroicons/react/-/react-2.1.5.tgz#1e13f34976cc542deae92353c01c8b3d7942e9ba" @@ -195,7 +483,7 @@ wrap-ansi "^8.1.0" wrap-ansi-cjs "npm:wrap-ansi@^7.0.0" -"@jridgewell/gen-mapping@^0.3.2": +"@jridgewell/gen-mapping@^0.3.2", "@jridgewell/gen-mapping@^0.3.5": version "0.3.5" resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz#dcce6aff74bdf6dad1a95802b69b04a2fcb1fb36" integrity sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg== @@ -214,12 +502,12 @@ resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.2.1.tgz#558fb6472ed16a4c850b889530e6b36438c49280" integrity sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A== -"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14": +"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14", "@jridgewell/sourcemap-codec@^1.5.0": version "1.5.0" resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz#3188bcb273a414b0d215fd22a58540b989b9409a" integrity sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ== -"@jridgewell/trace-mapping@^0.3.24": +"@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.25": version "0.3.25" resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz#15f190e98895f3fc23276ee14bc76b675c2e50f0" integrity sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ== @@ -330,6 +618,96 @@ resolved "https://registry.yarnpkg.com/@radix-ui/react-icons/-/react-icons-1.3.1.tgz#462c85fd726a77854cd5956e29eb19a575aa7ce5" integrity sha512-QvYompk0X+8Yjlo/Fv4McrzxohDdM5GgLHyQcPpcsPvlOSXCGFjdbuyGL5dzRbg0GpknAjQJJZzdiRK7iWVuFQ== +"@rollup/rollup-android-arm-eabi@4.24.3": + version "4.24.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.24.3.tgz#49a2a9808074f2683667992aa94b288e0b54fc82" + integrity sha512-ufb2CH2KfBWPJok95frEZZ82LtDl0A6QKTa8MoM+cWwDZvVGl5/jNb79pIhRvAalUu+7LD91VYR0nwRD799HkQ== + +"@rollup/rollup-android-arm64@4.24.3": + version "4.24.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.24.3.tgz#197e3bc01c228d3c23591e0fcedca91f8f398ec1" + integrity sha512-iAHpft/eQk9vkWIV5t22V77d90CRofgR2006UiCjHcHJFVI1E0oBkQIAbz+pLtthFw3hWEmVB4ilxGyBf48i2Q== + +"@rollup/rollup-darwin-arm64@4.24.3": + version "4.24.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.24.3.tgz#16772c0309d0dc3cca716580cdac7a1c560ddf46" + integrity sha512-QPW2YmkWLlvqmOa2OwrfqLJqkHm7kJCIMq9kOz40Zo9Ipi40kf9ONG5Sz76zszrmIZZ4hgRIkez69YnTHgEz1w== + +"@rollup/rollup-darwin-x64@4.24.3": + version "4.24.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.24.3.tgz#4e98120a1c4cda7d4043ccce72347cee53784140" + integrity sha512-KO0pN5x3+uZm1ZXeIfDqwcvnQ9UEGN8JX5ufhmgH5Lz4ujjZMAnxQygZAVGemFWn+ZZC0FQopruV4lqmGMshow== + +"@rollup/rollup-freebsd-arm64@4.24.3": + version "4.24.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.24.3.tgz#27145e414986e216e0d9b9a8d488028f33c39566" + integrity sha512-CsC+ZdIiZCZbBI+aRlWpYJMSWvVssPuWqrDy/zi9YfnatKKSLFCe6fjna1grHuo/nVaHG+kiglpRhyBQYRTK4A== + +"@rollup/rollup-freebsd-x64@4.24.3": + version "4.24.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.24.3.tgz#67e75fd87a903090f038b212273c492e5ca6b32f" + integrity sha512-F0nqiLThcfKvRQhZEzMIXOQG4EeX61im61VYL1jo4eBxv4aZRmpin6crnBJQ/nWnCsjH5F6J3W6Stdm0mBNqBg== + +"@rollup/rollup-linux-arm-gnueabihf@4.24.3": + version "4.24.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.24.3.tgz#bb45ebadbb9496298ab5461373bde357e8f33e88" + integrity sha512-KRSFHyE/RdxQ1CSeOIBVIAxStFC/hnBgVcaiCkQaVC+EYDtTe4X7z5tBkFyRoBgUGtB6Xg6t9t2kulnX6wJc6A== + +"@rollup/rollup-linux-arm-musleabihf@4.24.3": + version "4.24.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.24.3.tgz#384276c23feb0a4d6ffa603a9a760decce8b4118" + integrity sha512-h6Q8MT+e05zP5BxEKz0vi0DhthLdrNEnspdLzkoFqGwnmOzakEHSlXfVyA4HJ322QtFy7biUAVFPvIDEDQa6rw== + +"@rollup/rollup-linux-arm64-gnu@4.24.3": + version "4.24.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.24.3.tgz#89e5a4570ddd9eca908324a6de60bd64f904e3f0" + integrity sha512-fKElSyXhXIJ9pqiYRqisfirIo2Z5pTTve5K438URf08fsypXrEkVmShkSfM8GJ1aUyvjakT+fn2W7Czlpd/0FQ== + +"@rollup/rollup-linux-arm64-musl@4.24.3": + version "4.24.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.24.3.tgz#9ffd7cd6c6c6670d8c039056d6a49ad9f1f66949" + integrity sha512-YlddZSUk8G0px9/+V9PVilVDC6ydMz7WquxozToozSnfFK6wa6ne1ATUjUvjin09jp34p84milxlY5ikueoenw== + +"@rollup/rollup-linux-powerpc64le-gnu@4.24.3": + version "4.24.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.24.3.tgz#4d32ce982e2d25e3b8116336ad5ce6e270b5a024" + integrity sha512-yNaWw+GAO8JjVx3s3cMeG5Esz1cKVzz8PkTJSfYzE5u7A+NvGmbVFEHP+BikTIyYWuz0+DX9kaA3pH9Sqxp69g== + +"@rollup/rollup-linux-riscv64-gnu@4.24.3": + version "4.24.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.24.3.tgz#f43d4e0572397e3d3acd82d77d79ce021dea3310" + integrity sha512-lWKNQfsbpv14ZCtM/HkjCTm4oWTKTfxPmr7iPfp3AHSqyoTz5AgLemYkWLwOBWc+XxBbrU9SCokZP0WlBZM9lA== + +"@rollup/rollup-linux-s390x-gnu@4.24.3": + version "4.24.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.24.3.tgz#264f8a4c206173945bdab2a676d638b7945106a9" + integrity sha512-HoojGXTC2CgCcq0Woc/dn12wQUlkNyfH0I1ABK4Ni9YXyFQa86Fkt2Q0nqgLfbhkyfQ6003i3qQk9pLh/SpAYw== + +"@rollup/rollup-linux-x64-gnu@4.24.3": + version "4.24.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.24.3.tgz#e86172a407b2edd41540ec2ae636e497fadccff6" + integrity sha512-mnEOh4iE4USSccBOtcrjF5nj+5/zm6NcNhbSEfR3Ot0pxBwvEn5QVUXcuOwwPkapDtGZ6pT02xLoPaNv06w7KQ== + +"@rollup/rollup-linux-x64-musl@4.24.3": + version "4.24.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.24.3.tgz#8ae9bf78986d1b16ccbc89ab6f2dfa96807d3178" + integrity sha512-rMTzawBPimBQkG9NKpNHvquIUTQPzrnPxPbCY1Xt+mFkW7pshvyIS5kYgcf74goxXOQk0CP3EoOC1zcEezKXhw== + +"@rollup/rollup-win32-arm64-msvc@4.24.3": + version "4.24.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.24.3.tgz#11d6a59f651a3c2a9e5eaab0a99367b77a29c319" + integrity sha512-2lg1CE305xNvnH3SyiKwPVsTVLCg4TmNCF1z7PSHX2uZY2VbUpdkgAllVoISD7JO7zu+YynpWNSKAtOrX3AiuA== + +"@rollup/rollup-win32-ia32-msvc@4.24.3": + version "4.24.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.24.3.tgz#7ff146e53dc6e388b60329b7ec3335501d2b0f98" + integrity sha512-9SjYp1sPyxJsPWuhOCX6F4jUMXGbVVd5obVpoVEi8ClZqo52ViZewA6eFz85y8ezuOA+uJMP5A5zo6Oz4S5rVQ== + +"@rollup/rollup-win32-x64-msvc@4.24.3": + version "4.24.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.24.3.tgz#7687335781efe6bee14d6ed8eff9746a9f24c9cd" + integrity sha512-HGZgRFFYrMrP3TJlq58nR1xy8zHKId25vhmm5S9jETEfDf6xybPxsavFTJaufe2zgOGYJBskGlj49CwtEuFhWQ== + "@rtsao/scc@^1.1.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@rtsao/scc/-/scc-1.1.0.tgz#927dd2fae9bc3361403ac2c7a00c32ddce9ad7e8" @@ -352,6 +730,70 @@ dependencies: tslib "^2.4.0" +"@testing-library/dom@^10.4.0": + version "10.4.0" + resolved "https://registry.yarnpkg.com/@testing-library/dom/-/dom-10.4.0.tgz#82a9d9462f11d240ecadbf406607c6ceeeff43a8" + integrity sha512-pemlzrSESWbdAloYml3bAJMEfNh1Z7EduzqPKprCH5S341frlpYnUEW0H72dLxa6IsYr+mPno20GiSm+h9dEdQ== + dependencies: + "@babel/code-frame" "^7.10.4" + "@babel/runtime" "^7.12.5" + "@types/aria-query" "^5.0.1" + aria-query "5.3.0" + chalk "^4.1.0" + dom-accessibility-api "^0.5.9" + lz-string "^1.5.0" + pretty-format "^27.0.2" + +"@testing-library/react@^16.0.1": + version "16.0.1" + resolved "https://registry.yarnpkg.com/@testing-library/react/-/react-16.0.1.tgz#29c0ee878d672703f5e7579f239005e4e0faa875" + integrity sha512-dSmwJVtJXmku+iocRhWOUFbrERC76TX2Mnf0ATODz8brzAZrMBbzLwQixlBSanZxR6LddK3eiwpSFZgDET1URg== + dependencies: + "@babel/runtime" "^7.12.5" + +"@types/aria-query@^5.0.1": + version "5.0.4" + resolved "https://registry.yarnpkg.com/@types/aria-query/-/aria-query-5.0.4.tgz#1a31c3d378850d2778dabb6374d036dcba4ba708" + integrity sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw== + +"@types/babel__core@^7.20.5": + version "7.20.5" + resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.20.5.tgz#3df15f27ba85319caa07ba08d0721889bb39c017" + integrity sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA== + dependencies: + "@babel/parser" "^7.20.7" + "@babel/types" "^7.20.7" + "@types/babel__generator" "*" + "@types/babel__template" "*" + "@types/babel__traverse" "*" + +"@types/babel__generator@*": + version "7.6.8" + resolved "https://registry.yarnpkg.com/@types/babel__generator/-/babel__generator-7.6.8.tgz#f836c61f48b1346e7d2b0d93c6dacc5b9535d3ab" + integrity sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw== + dependencies: + "@babel/types" "^7.0.0" + +"@types/babel__template@*": + version "7.4.4" + resolved "https://registry.yarnpkg.com/@types/babel__template/-/babel__template-7.4.4.tgz#5672513701c1b2199bc6dad636a9d7491586766f" + integrity sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A== + dependencies: + "@babel/parser" "^7.1.0" + "@babel/types" "^7.0.0" + +"@types/babel__traverse@*": + version "7.20.6" + resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.20.6.tgz#8dc9f0ae0f202c08d8d4dab648912c8d6038e3f7" + integrity sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg== + dependencies: + "@babel/types" "^7.20.7" + +"@types/estree@1.0.6", "@types/estree@^1.0.0": + version "1.0.6" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.6.tgz#628effeeae2064a1b4e79f78e81d87b7e5fc7b50" + integrity sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw== + "@types/json5@^0.0.29": version "0.0.29" resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" @@ -470,6 +912,76 @@ resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.2.0.tgz#756641adb587851b5ccb3e095daf27ae581c8406" integrity sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ== +"@vitejs/plugin-react@^4.3.3": + version "4.3.3" + resolved "https://registry.yarnpkg.com/@vitejs/plugin-react/-/plugin-react-4.3.3.tgz#28301ac6d7aaf20b73a418ee5c65b05519b4836c" + integrity sha512-NooDe9GpHGqNns1i8XDERg0Vsg5SSYRhRxxyTGogUdkdNt47jal+fbuYi+Yfq6pzRCKXyoPcWisfxE6RIM3GKA== + dependencies: + "@babel/core" "^7.25.2" + "@babel/plugin-transform-react-jsx-self" "^7.24.7" + "@babel/plugin-transform-react-jsx-source" "^7.24.7" + "@types/babel__core" "^7.20.5" + react-refresh "^0.14.2" + +"@vitest/expect@2.1.4": + version "2.1.4" + resolved "https://registry.yarnpkg.com/@vitest/expect/-/expect-2.1.4.tgz#48f4f53a01092a3bdc118cff245f79ef388bdd8e" + integrity sha512-DOETT0Oh1avie/D/o2sgMHGrzYUFFo3zqESB2Hn70z6QB1HrS2IQ9z5DfyTqU8sg4Bpu13zZe9V4+UTNQlUeQA== + dependencies: + "@vitest/spy" "2.1.4" + "@vitest/utils" "2.1.4" + chai "^5.1.2" + tinyrainbow "^1.2.0" + +"@vitest/mocker@2.1.4": + version "2.1.4" + resolved "https://registry.yarnpkg.com/@vitest/mocker/-/mocker-2.1.4.tgz#0dc07edb9114f7f080a0181fbcdb16cd4a2d855d" + integrity sha512-Ky/O1Lc0QBbutJdW0rqLeFNbuLEyS+mIPiNdlVlp2/yhJ0SbyYqObS5IHdhferJud8MbbwMnexg4jordE5cCoQ== + dependencies: + "@vitest/spy" "2.1.4" + estree-walker "^3.0.3" + magic-string "^0.30.12" + +"@vitest/pretty-format@2.1.4", "@vitest/pretty-format@^2.1.4": + version "2.1.4" + resolved "https://registry.yarnpkg.com/@vitest/pretty-format/-/pretty-format-2.1.4.tgz#fc31993bdc1ef5a6c1a4aa6844e7ba55658a4f9f" + integrity sha512-L95zIAkEuTDbUX1IsjRl+vyBSLh3PwLLgKpghl37aCK9Jvw0iP+wKwIFhfjdUtA2myLgjrG6VU6JCFLv8q/3Ww== + dependencies: + tinyrainbow "^1.2.0" + +"@vitest/runner@2.1.4": + version "2.1.4" + resolved "https://registry.yarnpkg.com/@vitest/runner/-/runner-2.1.4.tgz#f9346500bdd0be1c926daaac5d683bae87ceda2c" + integrity sha512-sKRautINI9XICAMl2bjxQM8VfCMTB0EbsBc/EDFA57V6UQevEKY/TOPOF5nzcvCALltiLfXWbq4MaAwWx/YxIA== + dependencies: + "@vitest/utils" "2.1.4" + pathe "^1.1.2" + +"@vitest/snapshot@2.1.4": + version "2.1.4" + resolved "https://registry.yarnpkg.com/@vitest/snapshot/-/snapshot-2.1.4.tgz#ef8c3f605fbc23a32773256d37d3fdfd9b23d353" + integrity sha512-3Kab14fn/5QZRog5BPj6Rs8dc4B+mim27XaKWFWHWA87R56AKjHTGcBFKpvZKDzC4u5Wd0w/qKsUIio3KzWW4Q== + dependencies: + "@vitest/pretty-format" "2.1.4" + magic-string "^0.30.12" + pathe "^1.1.2" + +"@vitest/spy@2.1.4": + version "2.1.4" + resolved "https://registry.yarnpkg.com/@vitest/spy/-/spy-2.1.4.tgz#4e90f9783437c5841a27c80f8fd84d7289a6100a" + integrity sha512-4JOxa+UAizJgpZfaCPKK2smq9d8mmjZVPMt2kOsg/R8QkoRzydHH1qHxIYNvr1zlEaFj4SXiaaJWxq/LPLKaLg== + dependencies: + tinyspy "^3.0.2" + +"@vitest/utils@2.1.4": + version "2.1.4" + resolved "https://registry.yarnpkg.com/@vitest/utils/-/utils-2.1.4.tgz#6d67ac966647a21ce8bc497472ce230de3b64537" + integrity sha512-MXDnZn0Awl2S86PSNIim5PWXgIAx8CIkzu35mBdSApUip6RFOGXBCf3YFyeEu8n1IHk4bWD46DeYFu9mQlFIRg== + dependencies: + "@vitest/pretty-format" "2.1.4" + loupe "^3.1.2" + tinyrainbow "^1.2.0" + abbrev@1: version "1.1.1" resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" @@ -492,6 +1004,13 @@ agent-base@6: dependencies: debug "4" +agent-base@^7.0.2, agent-base@^7.1.0: + version "7.1.1" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-7.1.1.tgz#bdbded7dfb096b751a2a087eeeb9664725b2e317" + integrity sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA== + dependencies: + debug "^4.3.4" + ajv@^6.12.4: version "6.12.6" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" @@ -519,6 +1038,11 @@ ansi-styles@^4.0.0, ansi-styles@^4.1.0: dependencies: color-convert "^2.0.1" +ansi-styles@^5.0.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b" + integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA== + ansi-styles@^6.1.0: version "6.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5" @@ -560,6 +1084,13 @@ argparse@^2.0.1: resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== +aria-query@5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-5.3.0.tgz#650c569e41ad90b51b3d7df5e5eed1c7549c103e" + integrity sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A== + dependencies: + dequal "^2.0.3" + aria-query@^5.3.2: version "5.3.2" resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-5.3.2.tgz#93f81a43480e33a338f19163a3d10a50c01dcd59" @@ -654,11 +1185,21 @@ arraybuffer.prototype.slice@^1.0.3: is-array-buffer "^3.0.4" is-shared-array-buffer "^1.0.2" +assertion-error@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-2.0.1.tgz#f641a196b335690b1070bf00b6e7593fec190bf7" + integrity sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA== + ast-types-flow@^0.0.8: version "0.0.8" resolved "https://registry.yarnpkg.com/ast-types-flow/-/ast-types-flow-0.0.8.tgz#0a85e1c92695769ac13a428bb653e7538bea27d6" integrity sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ== +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== + available-typed-arrays@^1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz#a5cc375d6a03c2efc87a553f3e0b1522def14846" @@ -716,6 +1257,16 @@ braces@^3.0.3, braces@~3.0.2: dependencies: fill-range "^7.1.1" +browserslist@^4.24.0: + version "4.24.2" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.24.2.tgz#f5845bc91069dbd55ee89faf9822e1d885d16580" + integrity sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg== + dependencies: + caniuse-lite "^1.0.30001669" + electron-to-chromium "^1.5.41" + node-releases "^2.0.18" + update-browserslist-db "^1.1.1" + busboy@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/busboy/-/busboy-1.6.0.tgz#966ea36a9502e43cdb9146962523b92f531f6893" @@ -723,6 +1274,11 @@ busboy@1.6.0: dependencies: streamsearch "^1.1.0" +cac@^6.7.14: + version "6.7.14" + resolved "https://registry.yarnpkg.com/cac/-/cac-6.7.14.tgz#804e1e6f506ee363cb0e3ccbb09cad5dd9870959" + integrity sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ== + call-bind@^1.0.2, call-bind@^1.0.5, call-bind@^1.0.6, call-bind@^1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.7.tgz#06016599c40c56498c18769d2730be242b6fa3b9" @@ -744,12 +1300,23 @@ camelcase-css@^2.0.1: resolved "https://registry.yarnpkg.com/camelcase-css/-/camelcase-css-2.0.1.tgz#ee978f6947914cc30c6b44741b6ed1df7f043fd5" integrity sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA== -caniuse-lite@^1.0.30001579: +caniuse-lite@^1.0.30001579, caniuse-lite@^1.0.30001669: version "1.0.30001676" resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001676.tgz#fe133d41fe74af8f7cc93b8a714c3e86a86e6f04" integrity sha512-Qz6zwGCiPghQXGJvgQAem79esjitvJ+CxSbSQkW9H/UX5hg8XM88d4lp2W+MEQ81j+Hip58Il+jGVdazk1z9cw== -chalk@^4.0.0: +chai@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/chai/-/chai-5.1.2.tgz#3afbc340b994ae3610ca519a6c70ace77ad4378d" + integrity sha512-aGtmf24DW6MLHHG5gCx4zaI3uBq3KRtxeVs0DjFH6Z0rDNbsvTxFASFvdj79pxjxZ8/5u3PIiN3IwEIQkiiuPw== + dependencies: + assertion-error "^2.0.1" + check-error "^2.1.1" + deep-eql "^5.0.1" + loupe "^3.1.0" + pathval "^2.0.0" + +chalk@^4.0.0, chalk@^4.1.0: version "4.1.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== @@ -757,6 +1324,11 @@ chalk@^4.0.0: ansi-styles "^4.1.0" supports-color "^7.1.0" +check-error@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/check-error/-/check-error-2.1.1.tgz#87eb876ae71ee388fa0471fe423f494be1d96ccc" + integrity sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw== + chokidar@^3.5.3: version "3.6.0" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b" @@ -832,6 +1404,13 @@ color@^4.2.3: color-convert "^2.0.1" color-string "^1.9.0" +combined-stream@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" + integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== + dependencies: + delayed-stream "~1.0.0" + commander@^4.0.0: version "4.1.1" resolved "https://registry.yarnpkg.com/commander/-/commander-4.1.1.tgz#9fd602bd936294e9e9ef46a3f4d6964044b18068" @@ -847,6 +1426,11 @@ console-control-strings@^1.0.0, console-control-strings@^1.1.0: resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" integrity sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ== +convert-source-map@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a" + integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg== + cross-spawn@^7.0.0, cross-spawn@^7.0.2: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" @@ -861,6 +1445,13 @@ cssesc@^3.0.0: resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg== +cssstyle@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/cssstyle/-/cssstyle-4.1.0.tgz#161faee382af1bafadb6d3867a92a19bcb4aea70" + integrity sha512-h66W1URKpBS5YMI/V8PyXvTMFT8SupJ1IzoIV8IeBC/ji8WVmrO8dGlTi+2dh6whmdk6BiKJLD/ZBkhWbcg6nA== + dependencies: + rrweb-cssom "^0.7.1" + csstype@^3.0.2: version "3.1.3" resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.3.tgz#d80ff294d114fb0e6ac500fbf85b60137d7eff81" @@ -871,6 +1462,14 @@ damerau-levenshtein@^1.0.8: resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz#b43d286ccbd36bc5b2f7ed41caf2d0aba1f8a6e7" integrity sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA== +data-urls@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-5.0.0.tgz#2f76906bce1824429ffecb6920f45a0b30f00dde" + integrity sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg== + dependencies: + whatwg-mimetype "^4.0.0" + whatwg-url "^14.0.0" + data-view-buffer@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/data-view-buffer/-/data-view-buffer-1.0.1.tgz#8ea6326efec17a2e42620696e671d7d5a8bc66b2" @@ -898,7 +1497,7 @@ data-view-byte-offset@^1.0.0: es-errors "^1.3.0" is-data-view "^1.0.1" -debug@4, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4, debug@^4.3.5: +debug@4, debug@^4.1.0, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4, debug@^4.3.5, debug@^4.3.7: version "4.3.7" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.7.tgz#87945b4151a011d76d95a198d7111c865c360a52" integrity sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ== @@ -912,6 +1511,16 @@ debug@^3.2.7: dependencies: ms "^2.1.1" +decimal.js@^10.4.3: + version "10.4.3" + resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.4.3.tgz#1044092884d245d1b7f65725fa4ad4c6f781cc23" + integrity sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA== + +deep-eql@^5.0.1: + version "5.0.2" + resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-5.0.2.tgz#4b756d8d770a9257300825d52a2c2cff99c3a341" + integrity sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q== + deep-is@^0.1.3: version "0.1.4" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" @@ -935,11 +1544,21 @@ define-properties@^1.1.3, define-properties@^1.2.0, define-properties@^1.2.1: has-property-descriptors "^1.0.0" object-keys "^1.1.1" +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== + delegates@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" integrity sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ== +dequal@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/dequal/-/dequal-2.0.3.tgz#2644214f1997d39ed0ee0ece72335490a7ac67be" + integrity sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA== + detect-libc@^2.0.0, detect-libc@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-2.0.3.tgz#f0cd503b40f9939b894697d19ad50895e30cf700" @@ -969,6 +1588,11 @@ doctrine@^3.0.0: dependencies: esutils "^2.0.2" +dom-accessibility-api@^0.5.9: + version "0.5.16" + resolved "https://registry.yarnpkg.com/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz#5a7429e6066eb3664d911e33fb0e45de8eb08453" + integrity sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg== + dotenv@^16.4.5: version "16.4.5" resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.4.5.tgz#cdd3b3b604cb327e286b4762e13502f717cb099f" @@ -979,6 +1603,11 @@ eastasianwidth@^0.2.0: resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA== +electron-to-chromium@^1.5.41: + version "1.5.50" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.50.tgz#d9ba818da7b2b5ef1f3dd32bce7046feb7e93234" + integrity sha512-eMVObiUQ2LdgeO1F/ySTXsvqvxb6ZH2zPGaMYsWzRDdOddUa77tdmI0ltg+L16UpbWdhPmuF3wIQYyQq65WfZw== + emoji-regex@^8.0.0: version "8.0.0" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" @@ -997,6 +1626,11 @@ enhanced-resolve@^5.15.0: graceful-fs "^4.2.4" tapable "^2.2.0" +entities@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/entities/-/entities-4.5.0.tgz#5d268ea5e7113ec74c4d033b79ea5a35a488fb48" + integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw== + es-abstract@^1.17.5, es-abstract@^1.22.1, es-abstract@^1.22.3, es-abstract@^1.23.0, es-abstract@^1.23.1, es-abstract@^1.23.2, es-abstract@^1.23.3: version "1.23.3" resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.23.3.tgz#8f0c5a35cd215312573c5a27c87dfd6c881a0aa0" @@ -1113,6 +1747,40 @@ es-to-primitive@^1.2.1: is-date-object "^1.0.1" is-symbol "^1.0.2" +esbuild@^0.21.3: + version "0.21.5" + resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.21.5.tgz#9ca301b120922959b766360d8ac830da0d02997d" + integrity sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw== + optionalDependencies: + "@esbuild/aix-ppc64" "0.21.5" + "@esbuild/android-arm" "0.21.5" + "@esbuild/android-arm64" "0.21.5" + "@esbuild/android-x64" "0.21.5" + "@esbuild/darwin-arm64" "0.21.5" + "@esbuild/darwin-x64" "0.21.5" + "@esbuild/freebsd-arm64" "0.21.5" + "@esbuild/freebsd-x64" "0.21.5" + "@esbuild/linux-arm" "0.21.5" + "@esbuild/linux-arm64" "0.21.5" + "@esbuild/linux-ia32" "0.21.5" + "@esbuild/linux-loong64" "0.21.5" + "@esbuild/linux-mips64el" "0.21.5" + "@esbuild/linux-ppc64" "0.21.5" + "@esbuild/linux-riscv64" "0.21.5" + "@esbuild/linux-s390x" "0.21.5" + "@esbuild/linux-x64" "0.21.5" + "@esbuild/netbsd-x64" "0.21.5" + "@esbuild/openbsd-x64" "0.21.5" + "@esbuild/sunos-x64" "0.21.5" + "@esbuild/win32-arm64" "0.21.5" + "@esbuild/win32-ia32" "0.21.5" + "@esbuild/win32-x64" "0.21.5" + +escalade@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.2.0.tgz#011a3f69856ba189dffa7dc8fcce99d2a87903e5" + integrity sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA== + escape-string-regexp@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" @@ -1324,11 +1992,23 @@ estraverse@^5.1.0, estraverse@^5.2.0, estraverse@^5.3.0: resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== +estree-walker@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-3.0.3.tgz#67c3e549ec402a487b4fc193d1953a524752340d" + integrity sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g== + dependencies: + "@types/estree" "^1.0.0" + esutils@^2.0.2: version "2.0.3" resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== +expect-type@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/expect-type/-/expect-type-1.1.0.tgz#a146e414250d13dfc49eafcfd1344a4060fa4c75" + integrity sha512-bFi65yM+xZgk+u/KRIpekdSYkTB5W1pEf0Lt8Q8Msh7b+eQ7LXVtIB1Bkm4fvclDEL1b2CZkMhv2mOeF8tMdkA== + fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" @@ -1424,6 +2104,15 @@ foreground-child@^3.1.0: cross-spawn "^7.0.0" signal-exit "^4.0.1" +form-data@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.1.tgz#ba1076daaaa5bfd7e99c1a6cb02aa0a5cff90d48" + integrity sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + mime-types "^2.1.12" + fs-minipass@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb" @@ -1436,7 +2125,7 @@ fs.realpath@^1.0.0: resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== -fsevents@~2.3.2: +fsevents@~2.3.2, fsevents@~2.3.3: version "2.3.3" resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== @@ -1476,6 +2165,11 @@ gauge@^3.0.0: strip-ansi "^6.0.1" wide-align "^1.1.2" +gensync@^1.0.0-beta.2: + version "1.0.0-beta.2" + resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" + integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== + get-intrinsic@^1.1.3, get-intrinsic@^1.2.1, get-intrinsic@^1.2.3, get-intrinsic@^1.2.4: version "1.2.4" resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.4.tgz#e385f5a4b5227d449c3eabbad05494ef0abbeadd" @@ -1541,6 +2235,11 @@ glob@^7.1.3: once "^1.3.0" path-is-absolute "^1.0.0" +globals@^11.1.0: + version "11.12.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" + integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== + globals@^13.19.0: version "13.24.0" resolved "https://registry.yarnpkg.com/globals/-/globals-13.24.0.tgz#8432a19d78ce0c1e833949c36adb345400bb1171" @@ -1619,6 +2318,21 @@ hasown@^2.0.0, hasown@^2.0.1, hasown@^2.0.2: dependencies: function-bind "^1.1.2" +html-encoding-sniffer@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz#696df529a7cfd82446369dc5193e590a3735b448" + integrity sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ== + dependencies: + whatwg-encoding "^3.1.1" + +http-proxy-agent@^7.0.2: + version "7.0.2" + resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz#9a8b1f246866c028509486585f62b8f2c18c270e" + integrity sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig== + dependencies: + agent-base "^7.1.0" + debug "^4.3.4" + https-proxy-agent@^5.0.0: version "5.0.1" resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6" @@ -1627,6 +2341,21 @@ https-proxy-agent@^5.0.0: agent-base "6" debug "4" +https-proxy-agent@^7.0.5: + version "7.0.5" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz#9e8b5013873299e11fab6fd548405da2d6c602b2" + integrity sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw== + dependencies: + agent-base "^7.0.2" + debug "4" + +iconv-lite@0.6.3: + version "0.6.3" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501" + integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw== + dependencies: + safer-buffer ">= 2.1.2 < 3.0.0" + ignore@^5.2.0, ignore@^5.3.1: version "5.3.2" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.2.tgz#3cd40e729f3643fd87cb04e50bf0eb722bc596f5" @@ -1800,6 +2529,11 @@ is-path-inside@^3.0.3: resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== +is-potential-custom-element-name@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz#171ed6f19e3ac554394edf78caa05784a45bebb5" + integrity sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ== + is-regex@^1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" @@ -1896,7 +2630,7 @@ jiti@^1.21.0: resolved "https://registry.yarnpkg.com/jiti/-/jiti-1.21.6.tgz#6c7f7398dd4b3142767f9a168af2f317a428d268" integrity sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w== -"js-tokens@^3.0.0 || ^4.0.0": +"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== @@ -1908,6 +2642,38 @@ js-yaml@^4.1.0: dependencies: argparse "^2.0.1" +jsdom@^25.0.1: + version "25.0.1" + resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-25.0.1.tgz#536ec685c288fc8a5773a65f82d8b44badcc73ef" + integrity sha512-8i7LzZj7BF8uplX+ZyOlIz86V6TAsSs+np6m1kpW9u0JWi4z/1t+FzcK1aek+ybTnAC4KhBL4uXCNT0wcUIeCw== + dependencies: + cssstyle "^4.1.0" + data-urls "^5.0.0" + decimal.js "^10.4.3" + form-data "^4.0.0" + html-encoding-sniffer "^4.0.0" + http-proxy-agent "^7.0.2" + https-proxy-agent "^7.0.5" + is-potential-custom-element-name "^1.0.1" + nwsapi "^2.2.12" + parse5 "^7.1.2" + rrweb-cssom "^0.7.1" + saxes "^6.0.0" + symbol-tree "^3.2.4" + tough-cookie "^5.0.0" + w3c-xmlserializer "^5.0.0" + webidl-conversions "^7.0.0" + whatwg-encoding "^3.1.1" + whatwg-mimetype "^4.0.0" + whatwg-url "^14.0.0" + ws "^8.18.0" + xml-name-validator "^5.0.0" + +jsesc@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-3.0.2.tgz#bb8b09a6597ba426425f2e4a07245c3d00b9343e" + integrity sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g== + json-buffer@3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" @@ -1930,6 +2696,11 @@ json5@^1.0.2: dependencies: minimist "^1.2.0" +json5@^2.2.3: + version "2.2.3" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" + integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== + "jsx-ast-utils@^2.4.1 || ^3.0.0", jsx-ast-utils@^3.3.5: version "3.3.5" resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz#4766bd05a8e2a11af222becd19e15575e52a853a" @@ -2001,16 +2772,40 @@ loose-envify@^1.4.0: dependencies: js-tokens "^3.0.0 || ^4.0.0" +loupe@^3.1.0, loupe@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/loupe/-/loupe-3.1.2.tgz#c86e0696804a02218f2206124c45d8b15291a240" + integrity sha512-23I4pFZHmAemUnz8WZXbYRSKYj801VDaNv9ETuMh7IrMc7VuVVSo+Z9iLE3ni30+U48iDWfi30d3twAXBYmnCg== + lru-cache@^10.2.0: version "10.4.3" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.4.3.tgz#410fc8a17b70e598013df257c2446b7f3383f119" integrity sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ== +lru-cache@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" + integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== + dependencies: + yallist "^3.0.2" + lucide-react@^0.454.0: version "0.454.0" resolved "https://registry.yarnpkg.com/lucide-react/-/lucide-react-0.454.0.tgz#a81b9c482018720f07ead0503ae502d94d528444" integrity sha512-hw7zMDwykCLnEzgncEEjHeA6+45aeEzRYuKHuyRSOPkhko+J3ySGjGIzu+mmMfDFG1vazHepMaYFYHbTFAZAAQ== +lz-string@^1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/lz-string/-/lz-string-1.5.0.tgz#c1ab50f77887b712621201ba9fd4e3a6ed099941" + integrity sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ== + +magic-string@^0.30.12: + version "0.30.12" + resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.12.tgz#9eb11c9d072b9bcb4940a5b2c2e1a217e4ee1a60" + integrity sha512-Ea8I3sQMVXr8JhN4z+H/d8zwo+tYDgHE9+5G4Wnrwhs0gaK9fXTKx0Tw5Xwsd/bCPTTZNRAdpyzvoeORe9LYpw== + dependencies: + "@jridgewell/sourcemap-codec" "^1.5.0" + make-dir@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" @@ -2031,6 +2826,18 @@ micromatch@^4.0.4, micromatch@^4.0.5: braces "^3.0.3" picomatch "^2.3.1" +mime-db@1.52.0: + version "1.52.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== + +mime-types@^2.1.12: + version "2.1.35" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" + integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== + dependencies: + mime-db "1.52.0" + minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" @@ -2080,6 +2887,13 @@ mkdirp@^1.0.3: resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== +moq.ts@^10.0.8: + version "10.0.8" + resolved "https://registry.yarnpkg.com/moq.ts/-/moq.ts-10.0.8.tgz#844f317c09a3450469e4fb3cc95252a6ed631581" + integrity sha512-9zAJcsqhVCNczXz8xfDHSjU0SYq6umAFRB1CDRpgE1vwK7EMqc+DAUV6vUS+Ttl8CAQFFtTiWB46g3axdcrzmQ== + dependencies: + tslib "*" + ms@^2.1.1, ms@^2.1.3: version "2.1.3" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" @@ -2139,6 +2953,11 @@ node-fetch@^2.6.7: dependencies: whatwg-url "^5.0.0" +node-releases@^2.0.18: + version "2.0.18" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.18.tgz#f010e8d35e2fe8d6b2944f03f70213ecedc4ca3f" + integrity sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g== + nopt@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/nopt/-/nopt-5.0.0.tgz#530942bb58a512fccafe53fe210f13a25355dc88" @@ -2161,6 +2980,11 @@ npmlog@^5.0.1: gauge "^3.0.0" set-blocking "^2.0.0" +nwsapi@^2.2.12: + version "2.2.13" + resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.13.tgz#e56b4e98960e7a040e5474536587e599c4ff4655" + integrity sha512-cTGB9ptp9dY9A5VbMSe7fQBcl/tt22Vcqdq8+eN93rblOuE0aCFu4aZ2vMwct/2t+lFnosm8RkQW1I0Omb1UtQ== + object-assign@^4.0.1, object-assign@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" @@ -2273,6 +3097,13 @@ parent-module@^1.0.0: dependencies: callsites "^3.0.0" +parse5@^7.1.2: + version "7.2.1" + resolved "https://registry.yarnpkg.com/parse5/-/parse5-7.2.1.tgz#8928f55915e6125f430cc44309765bf17556a33a" + integrity sha512-BuBYQYlv1ckiPdQi/ohiivi9Sagc9JG+Ozs0r7b/0iK3sKmrb0b9FdWdBbOdx6hBCM/F9Ir82ofnBhtZOjCRPQ== + dependencies: + entities "^4.5.0" + path-exists@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" @@ -2301,6 +3132,16 @@ path-scurry@^1.11.1: lru-cache "^10.2.0" minipass "^5.0.0 || ^6.0.2 || ^7.0.0" +pathe@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/pathe/-/pathe-1.1.2.tgz#6c4cb47a945692e48a1ddd6e4094d170516437ec" + integrity sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ== + +pathval@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/pathval/-/pathval-2.0.0.tgz#7e2550b422601d4f6b8e26f1301bc8f15a741a25" + integrity sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA== + picocolors@^1.0.0, picocolors@^1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b" @@ -2379,7 +3220,7 @@ postcss@8.4.31: picocolors "^1.0.0" source-map-js "^1.0.2" -postcss@^8, postcss@^8.4.23: +postcss@^8, postcss@^8.4.23, postcss@^8.4.43: version "8.4.47" resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.47.tgz#5bf6c9a010f3e724c503bf03ef7947dcb0fea365" integrity sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ== @@ -2398,6 +3239,15 @@ prelude-ls@^1.2.1: resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== +pretty-format@^27.0.2: + version "27.5.1" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-27.5.1.tgz#2181879fdea51a7a5851fb39d920faa63f01d88e" + integrity sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ== + dependencies: + ansi-regex "^5.0.1" + ansi-styles "^5.0.0" + react-is "^17.0.1" + prop-types@^15.8.1: version "15.8.1" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" @@ -2407,7 +3257,7 @@ prop-types@^15.8.1: object-assign "^4.1.1" react-is "^16.13.1" -punycode@^2.1.0: +punycode@^2.1.0, punycode@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== @@ -2429,6 +3279,16 @@ react-is@^16.13.1: resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== +react-is@^17.0.1: + version "17.0.2" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0" + integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w== + +react-refresh@^0.14.2: + version "0.14.2" + resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.14.2.tgz#3833da01ce32da470f1f936b9d477da5c7028bf9" + integrity sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA== + react@19.0.0-rc-69d4b800-20241021: version "19.0.0-rc-69d4b800-20241021" resolved "https://registry.yarnpkg.com/react/-/react-19.0.0-rc-69d4b800-20241021.tgz#2c3ce2a581df8c4c9e4059189af29b89022edd41" @@ -2475,6 +3335,11 @@ reflect.getprototypeof@^1.0.4: globalthis "^1.0.3" which-builtin-type "^1.1.3" +regenerator-runtime@^0.14.0: + version "0.14.1" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz#356ade10263f685dda125100cd862c1db895327f" + integrity sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw== + regexp.prototype.flags@^1.5.2: version "1.5.3" resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.5.3.tgz#b3ae40b1d2499b8350ab2c3fe6ef3845d3a96f42" @@ -2525,6 +3390,38 @@ rimraf@^3.0.2: dependencies: glob "^7.1.3" +rollup@^4.20.0: + version "4.24.3" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.24.3.tgz#8b259063740af60b0030315f88665ba2041789b8" + integrity sha512-HBW896xR5HGmoksbi3JBDtmVzWiPAYqp7wip50hjQ67JbDz61nyoMPdqu1DvVW9asYb2M65Z20ZHsyJCMqMyDg== + dependencies: + "@types/estree" "1.0.6" + optionalDependencies: + "@rollup/rollup-android-arm-eabi" "4.24.3" + "@rollup/rollup-android-arm64" "4.24.3" + "@rollup/rollup-darwin-arm64" "4.24.3" + "@rollup/rollup-darwin-x64" "4.24.3" + "@rollup/rollup-freebsd-arm64" "4.24.3" + "@rollup/rollup-freebsd-x64" "4.24.3" + "@rollup/rollup-linux-arm-gnueabihf" "4.24.3" + "@rollup/rollup-linux-arm-musleabihf" "4.24.3" + "@rollup/rollup-linux-arm64-gnu" "4.24.3" + "@rollup/rollup-linux-arm64-musl" "4.24.3" + "@rollup/rollup-linux-powerpc64le-gnu" "4.24.3" + "@rollup/rollup-linux-riscv64-gnu" "4.24.3" + "@rollup/rollup-linux-s390x-gnu" "4.24.3" + "@rollup/rollup-linux-x64-gnu" "4.24.3" + "@rollup/rollup-linux-x64-musl" "4.24.3" + "@rollup/rollup-win32-arm64-msvc" "4.24.3" + "@rollup/rollup-win32-ia32-msvc" "4.24.3" + "@rollup/rollup-win32-x64-msvc" "4.24.3" + fsevents "~2.3.2" + +rrweb-cssom@^0.7.1: + version "0.7.1" + resolved "https://registry.yarnpkg.com/rrweb-cssom/-/rrweb-cssom-0.7.1.tgz#c73451a484b86dd7cfb1e0b2898df4b703183e4b" + integrity sha512-TrEMa7JGdVm0UThDJSx7ddw5nVm3UJS9o9CCIZ72B1vSyEZoziDqBYP3XIoi/12lKrJR8rE3jeFHMok2F/Mnsg== + run-parallel@^1.1.9: version "1.2.0" resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" @@ -2556,6 +3453,18 @@ safe-regex-test@^1.0.3: es-errors "^1.3.0" is-regex "^1.1.4" +"safer-buffer@>= 2.1.2 < 3.0.0": + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + +saxes@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/saxes/-/saxes-6.0.0.tgz#fe5b4a4768df4f14a201b1ba6a65c1f3d9988cc5" + integrity sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA== + dependencies: + xmlchars "^2.2.0" + scheduler@0.25.0-rc-69d4b800-20241021: version "0.25.0-rc-69d4b800-20241021" resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.25.0-rc-69d4b800-20241021.tgz#336e47ef2bd5eddb0ebacfd910b5df1b236d92bd" @@ -2649,6 +3558,11 @@ side-channel@^1.0.4, side-channel@^1.0.6: get-intrinsic "^1.2.4" object-inspect "^1.13.1" +siginfo@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/siginfo/-/siginfo-2.0.0.tgz#32e76c70b79724e3bb567cb9d543eb858ccfaf30" + integrity sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g== + signal-exit@^3.0.0: version "3.0.7" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" @@ -2671,6 +3585,16 @@ source-map-js@^1.0.2, source-map-js@^1.2.1: resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.1.tgz#1ce5650fddd87abc099eda37dcff024c2667ae46" integrity sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA== +stackback@0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/stackback/-/stackback-0.0.2.tgz#1ac8a0d9483848d1695e418b6d031a3c3ce68e3b" + integrity sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw== + +std-env@^3.7.0: + version "3.7.0" + resolved "https://registry.yarnpkg.com/std-env/-/std-env-3.7.0.tgz#c9f7386ced6ecf13360b6c6c55b8aaa4ef7481d2" + integrity sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg== + streamsearch@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-1.1.0.tgz#404dd1e2247ca94af554e841a8ef0eaa238da764" @@ -2836,6 +3760,11 @@ supports-preserve-symlinks-flag@^1.0.0: resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== +symbol-tree@^3.2.4: + version "3.2.4" + resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2" + integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw== + tailwind-merge@^2.5.4: version "2.5.4" resolved "https://registry.yarnpkg.com/tailwind-merge/-/tailwind-merge-2.5.4.tgz#4bf574e81fa061adeceba099ae4df56edcee78d1" @@ -2910,6 +3839,43 @@ thenify-all@^1.0.0: dependencies: any-promise "^1.0.0" +tinybench@^2.9.0: + version "2.9.0" + resolved "https://registry.yarnpkg.com/tinybench/-/tinybench-2.9.0.tgz#103c9f8ba6d7237a47ab6dd1dcff77251863426b" + integrity sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg== + +tinyexec@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/tinyexec/-/tinyexec-0.3.1.tgz#0ab0daf93b43e2c211212396bdb836b468c97c98" + integrity sha512-WiCJLEECkO18gwqIp6+hJg0//p23HXp4S+gGtAKu3mI2F2/sXC4FvHvXvB0zJVVaTPhx1/tOwdbRsa1sOBIKqQ== + +tinypool@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/tinypool/-/tinypool-1.0.1.tgz#c64233c4fac4304e109a64340178760116dbe1fe" + integrity sha512-URZYihUbRPcGv95En+sz6MfghfIc2OJ1sv/RmhWZLouPY0/8Vo80viwPvg3dlaS9fuq7fQMEfgRRK7BBZThBEA== + +tinyrainbow@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/tinyrainbow/-/tinyrainbow-1.2.0.tgz#5c57d2fc0fb3d1afd78465c33ca885d04f02abb5" + integrity sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ== + +tinyspy@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/tinyspy/-/tinyspy-3.0.2.tgz#86dd3cf3d737b15adcf17d7887c84a75201df20a" + integrity sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q== + +tldts-core@^6.1.57: + version "6.1.57" + resolved "https://registry.yarnpkg.com/tldts-core/-/tldts-core-6.1.57.tgz#2cc6e6af3d0807ad616900300083930efa81b57d" + integrity sha512-lXnRhuQpx3zU9EONF9F7HfcRLvN1uRYUBIiKL+C/gehC/77XTU+Jye6ui86GA3rU6FjlJ0triD1Tkjt2F/2lEg== + +tldts@^6.1.32: + version "6.1.57" + resolved "https://registry.yarnpkg.com/tldts/-/tldts-6.1.57.tgz#5d91d257ac945837358fe3954343fc01122fbad7" + integrity sha512-Oy7yDXK8meJl8vPMOldzA+MtueAJ5BrH4l4HXwZuj2AtfoQbLjmTJmjNWPUcAo+E/ibHn7QlqMS0BOcXJFJyHQ== + dependencies: + tldts-core "^6.1.57" + to-regex-range@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" @@ -2917,6 +3883,20 @@ to-regex-range@^5.0.1: dependencies: is-number "^7.0.0" +tough-cookie@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-5.0.0.tgz#6b6518e2b5c070cf742d872ee0f4f92d69eac1af" + integrity sha512-FRKsF7cz96xIIeMZ82ehjC3xW2E+O2+v11udrDYewUbszngYhsGa8z6YUMMzO9QJZzzyd0nGGXnML/TReX6W8Q== + dependencies: + tldts "^6.1.32" + +tr46@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-5.0.0.tgz#3b46d583613ec7283020d79019f1335723801cec" + integrity sha512-tk2G5R2KRwBd+ZN0zaEXpmzdKyOYksXwywulIX95MBODjSzMIuQnQ3m8JxgbhnL1LeVo7lqQKsYa1O3Htl7K5g== + dependencies: + punycode "^2.3.1" + tr46@~0.0.3: version "0.0.3" resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" @@ -2942,16 +3922,16 @@ tsconfig-paths@^3.15.0: minimist "^1.2.6" strip-bom "^3.0.0" +tslib@*, tslib@^2.4.0: + version "2.8.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" + integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== + tslib@^1.9.3: version "1.14.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== -tslib@^2.4.0: - version "2.8.1" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" - integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== - tsyringe@^4.8.0: version "4.8.0" resolved "https://registry.yarnpkg.com/tsyringe/-/tsyringe-4.8.0.tgz#d599651b36793ba872870fee4f845bd484a5cac1" @@ -3035,6 +4015,14 @@ undici-types@~6.19.2: resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.19.8.tgz#35111c9d1437ab83a7cdc0abae2f26d88eda0a02" integrity sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw== +update-browserslist-db@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz#80846fba1d79e82547fb661f8d141e0945755fe5" + integrity sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A== + dependencies: + escalade "^3.2.0" + picocolors "^1.1.0" + uri-js@^4.2.2: version "4.4.1" resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" @@ -3047,11 +4035,90 @@ util-deprecate@^1.0.1, util-deprecate@^1.0.2: resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== +vite-node@2.1.4: + version "2.1.4" + resolved "https://registry.yarnpkg.com/vite-node/-/vite-node-2.1.4.tgz#97ffb6de913fd8d42253afe441f9512e9dbdfd5c" + integrity sha512-kqa9v+oi4HwkG6g8ufRnb5AeplcRw8jUF6/7/Qz1qRQOXHImG8YnLbB+LLszENwFnoBl9xIf9nVdCFzNd7GQEg== + dependencies: + cac "^6.7.14" + debug "^4.3.7" + pathe "^1.1.2" + vite "^5.0.0" + +vite@^5.0.0: + version "5.4.10" + resolved "https://registry.yarnpkg.com/vite/-/vite-5.4.10.tgz#d358a7bd8beda6cf0f3b7a450a8c7693a4f80c18" + integrity sha512-1hvaPshuPUtxeQ0hsVH3Mud0ZanOLwVTneA1EgbAM5LhaZEqyPWGRQ7BtaMvUrTDeEaC8pxtj6a6jku3x4z6SQ== + dependencies: + esbuild "^0.21.3" + postcss "^8.4.43" + rollup "^4.20.0" + optionalDependencies: + fsevents "~2.3.3" + +vitest@^2.1.4: + version "2.1.4" + resolved "https://registry.yarnpkg.com/vitest/-/vitest-2.1.4.tgz#ba8f4589fb639cf5a9e6af54781667312b3e8230" + integrity sha512-eDjxbVAJw1UJJCHr5xr/xM86Zx+YxIEXGAR+bmnEID7z9qWfoxpHw0zdobz+TQAFOLT+nEXz3+gx6nUJ7RgmlQ== + dependencies: + "@vitest/expect" "2.1.4" + "@vitest/mocker" "2.1.4" + "@vitest/pretty-format" "^2.1.4" + "@vitest/runner" "2.1.4" + "@vitest/snapshot" "2.1.4" + "@vitest/spy" "2.1.4" + "@vitest/utils" "2.1.4" + chai "^5.1.2" + debug "^4.3.7" + expect-type "^1.1.0" + magic-string "^0.30.12" + pathe "^1.1.2" + std-env "^3.7.0" + tinybench "^2.9.0" + tinyexec "^0.3.1" + tinypool "^1.0.1" + tinyrainbow "^1.2.0" + vite "^5.0.0" + vite-node "2.1.4" + why-is-node-running "^2.3.0" + +w3c-xmlserializer@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz#f925ba26855158594d907313cedd1476c5967f6c" + integrity sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA== + dependencies: + xml-name-validator "^5.0.0" + webidl-conversions@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== +webidl-conversions@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-7.0.0.tgz#256b4e1882be7debbf01d05f0aa2039778ea080a" + integrity sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g== + +whatwg-encoding@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz#d0f4ef769905d426e1688f3e34381a99b60b76e5" + integrity sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ== + dependencies: + iconv-lite "0.6.3" + +whatwg-mimetype@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz#bc1bf94a985dc50388d54a9258ac405c3ca2fc0a" + integrity sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg== + +whatwg-url@^14.0.0: + version "14.0.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-14.0.0.tgz#00baaa7fd198744910c4b1ef68378f2200e4ceb6" + integrity sha512-1lfMEm2IEr7RIV+f4lUNPOqfFL+pO+Xw3fJSqmjX9AbXcXcYOkCe1P6+9VBZB6n94af16NfZf+sSk0JCBZC9aw== + dependencies: + tr46 "^5.0.0" + webidl-conversions "^7.0.0" + whatwg-url@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" @@ -3117,6 +4184,14 @@ which@^2.0.1: dependencies: isexe "^2.0.0" +why-is-node-running@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/why-is-node-running/-/why-is-node-running-2.3.0.tgz#a3f69a97107f494b3cdc3bdddd883a7d65cebf04" + integrity sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w== + dependencies: + siginfo "^2.0.0" + stackback "0.0.2" + wide-align@^1.1.2: version "1.1.5" resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.5.tgz#df1d4c206854369ecf3c9a4898f1b23fbd9d15d3" @@ -3152,6 +4227,26 @@ wrappy@1: resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== +ws@^8.18.0: + version "8.18.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.18.0.tgz#0d7505a6eafe2b0e712d232b42279f53bc289bbc" + integrity sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw== + +xml-name-validator@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-5.0.0.tgz#82be9b957f7afdacf961e5980f1bf227c0bf7673" + integrity sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg== + +xmlchars@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb" + integrity sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw== + +yallist@^3.0.2: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" + integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== + yallist@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" -- 2.39.5 From 46bbb9f8da607083979584592004d18e2b0e2e66 Mon Sep 17 00:00:00 2001 From: behnam <behnamrahimpour74@gmail.com> Date: Fri, 1 Nov 2024 15:34:04 +0300 Subject: [PATCH 08/37] Add fetch list of customer invoice --- src/app/lib/data.ts | 129 +----------------- src/app/lib/definitions.ts | 36 ----- .../data/module/customer-di.ts | 16 +++ .../data/repo/customer-invoice-db-repo.ts | 51 +++++++ .../domain/entity/customer-invoice.ts | 21 +++ .../domain/i-repo/customer-invoice-repo.ts | 7 + .../fetch-customer-invoices-usecase.ts | 11 ++ .../customer-invoice/invoice-module-key.ts | 1 + .../customer/data/module/customer-di.ts | 3 + .../customer/data/repo/customer-db-repo.ts | 66 +++++++++ .../customer/domain/entity/customer.ts | 16 +-- .../customer/customer-fake-factory.ts | 6 +- 12 files changed, 183 insertions(+), 180 deletions(-) create mode 100644 src/feature/customer-invoice/data/module/customer-di.ts create mode 100644 src/feature/customer-invoice/data/repo/customer-invoice-db-repo.ts create mode 100644 src/feature/customer-invoice/domain/entity/customer-invoice.ts create mode 100644 src/feature/customer-invoice/domain/i-repo/customer-invoice-repo.ts create mode 100644 src/feature/customer-invoice/domain/usecase/fetch-customer-invoices-usecase.ts create mode 100644 src/feature/customer-invoice/invoice-module-key.ts create mode 100644 src/feature/customer/data/repo/customer-db-repo.ts diff --git a/src/app/lib/data.ts b/src/app/lib/data.ts index 3afe7f1..d76cf24 100644 --- a/src/app/lib/data.ts +++ b/src/app/lib/data.ts @@ -1,8 +1,5 @@ import { sql } from '@/bootstrap/db/db'; import { - CustomersTableType, - InvoiceForm, - InvoicesTable, Revenue, Invoice, Customer, @@ -59,7 +56,7 @@ export async function fetchLatestInvoices() { export async function fetchCardData() { // This is equivalent to in fetch(..., {cache: 'no-store'}). - connection() + connection() try { // You can probably combine these into a single SQL query @@ -97,127 +94,3 @@ export async function fetchCardData() { throw new Error('Failed to fetch card data.'); } } - -const ITEMS_PER_PAGE = 6; -export async function fetchFilteredInvoices( - query: string, - currentPage: number, -) { - // This is equivalent to in fetch(..., {cache: 'no-store'}). - connection() - - const offset = (currentPage - 1) * ITEMS_PER_PAGE; - - try { - const invoices = await sql` - SELECT - invoices.id, - invoices.amount, - invoices.date, - invoices.status, - customers.name, - customers.email, - customers.image_url - FROM invoices - JOIN customers ON invoices.customer_id = customers.id - WHERE - customers.name ILIKE ${`%${query}%`} OR - customers.email ILIKE ${`%${query}%`} OR - invoices.amount::text ILIKE ${`%${query}%`} OR - invoices.date::text ILIKE ${`%${query}%`} OR - invoices.status ILIKE ${`%${query}%`} - ORDER BY invoices.date DESC - LIMIT ${ITEMS_PER_PAGE} OFFSET ${offset} - ` as postgres.RowList<InvoicesTable[]>; - - return invoices; - } catch (error) { - console.error('Database Error:', error); - throw new Error('Failed to fetch invoices.'); - } -} - -export async function fetchInvoicesPages(query: string) { - // This is equivalent to in fetch(..., {cache: 'no-store'}). - connection() - try { - const count = await sql`SELECT COUNT(*) - FROM invoices - JOIN customers ON invoices.customer_id = customers.id - WHERE - customers.name ILIKE ${`%${query}%`} OR - customers.email ILIKE ${`%${query}%`} OR - invoices.amount::text ILIKE ${`%${query}%`} OR - invoices.date::text ILIKE ${`%${query}%`} OR - invoices.status ILIKE ${`%${query}%`} - `; - - const totalPages = Math.ceil(Number(count.at(0)?.count) / ITEMS_PER_PAGE); - return totalPages; - } catch (error) { - console.error('Database Error:', error); - throw new Error('Failed to fetch total number of invoices.'); - } -} - -export async function fetchInvoiceById(id: string) { - // This is equivalent to in fetch(..., {cache: 'no-store'}). - connection() - try { - const data = await sql` - SELECT - invoices.id, - invoices.customer_id, - invoices.amount, - invoices.status - FROM invoices - WHERE invoices.id = ${id}; - ` as postgres.RowList<InvoiceForm[]>; - - const invoice = data.map((invoice) => ({ - ...invoice, - // Convert amount from cents to dollars - amount: invoice.amount / 100, - })); - - return invoice[0]; - } catch (error) { - console.error('Database Error:', error); - throw new Error('Failed to fetch invoice.'); - } -} - -export async function fetchFilteredCustomers(query: string) { - // This is equivalent to in fetch(..., {cache: 'no-store'}). - connection() - try { - const data = await sql` - SELECT - customers.id, - customers.name, - customers.email, - customers.image_url, - COUNT(invoices.id) AS total_invoices, - SUM(CASE WHEN invoices.status = 'pending' THEN invoices.amount ELSE 0 END) AS total_pending, - SUM(CASE WHEN invoices.status = 'paid' THEN invoices.amount ELSE 0 END) AS total_paid - FROM customers - LEFT JOIN invoices ON customers.id = invoices.customer_id - WHERE - customers.name ILIKE ${`%${query}%`} OR - customers.email ILIKE ${`%${query}%`} - GROUP BY customers.id, customers.name, customers.email, customers.image_url - ORDER BY customers.name ASC - ` as postgres.RowList<CustomersTableType[]>; - - const customers = data.map((customer) => ({ - ...customer, - total_pending: formatCurrency(customer.total_pending), - total_paid: formatCurrency(customer.total_paid), - })); - - return customers; - } catch (err) { - console.error('Database Error:', err); - throw new Error('Failed to fetch customer table.'); - } -} diff --git a/src/app/lib/definitions.ts b/src/app/lib/definitions.ts index 0860139..e4cf179 100644 --- a/src/app/lib/definitions.ts +++ b/src/app/lib/definitions.ts @@ -26,42 +26,6 @@ export type LatestInvoice = { amount: string; }; -// The database returns a number for amount, but we later format it to a string with the formatCurrency function -export type LatestInvoiceRaw = Omit<LatestInvoice, 'amount'> & { - amount: number; -}; - -export type InvoicesTable = { - id: string; - customer_id: string; - name: string; - email: string; - image_url: string; - date: string; - amount: number; - status: 'pending' | 'paid'; -}; - -export type CustomersTableType = { - id: string; - name: string; - email: string; - image_url: string; - total_invoices: number; - total_pending: number; - total_paid: number; -}; - -export type FormattedCustomersTable = { - id: string; - name: string; - email: string; - image_url: string; - total_invoices: number; - total_pending: string; - total_paid: string; -}; - export type InvoiceForm = { id: string; customer_id: string; diff --git a/src/feature/customer-invoice/data/module/customer-di.ts b/src/feature/customer-invoice/data/module/customer-di.ts new file mode 100644 index 0000000..4d153a8 --- /dev/null +++ b/src/feature/customer-invoice/data/module/customer-di.ts @@ -0,0 +1,16 @@ +import di from "@/bootstrap/di/init-di"; +import CustomerDbRepo from "@/feature/customer/data/repo/customer-db-repo"; +import { customerRepoKey } from "@/feature/customer/domain/i-repo/customer-repo"; +import fetchCustomersUsecase from "@/feature/customer/domain/usecase/fetch-customers-usecase"; +import { DependencyContainer } from "tsyringe"; + +export default function getCustomerDi(): DependencyContainer { + const customerDi = di.createChildContainer() + + customerDi.register(fetchCustomersUsecase.name, { + useValue: fetchCustomersUsecase + }) + + customerDi.register(customerRepoKey, CustomerDbRepo) + return customerDi +} \ No newline at end of file diff --git a/src/feature/customer-invoice/data/repo/customer-invoice-db-repo.ts b/src/feature/customer-invoice/data/repo/customer-invoice-db-repo.ts new file mode 100644 index 0000000..bd52acc --- /dev/null +++ b/src/feature/customer-invoice/data/repo/customer-invoice-db-repo.ts @@ -0,0 +1,51 @@ +import { formatCurrency } from "@/app/lib/utils"; +import { sql } from "@/bootstrap/db/db"; +import CustomerInvoice from "@/feature/customer-invoice/domain/entity/customer-invoice"; +import CustomerInvoiceRepo from "@/feature/customer-invoice/domain/i-repo/customer-invoice-repo"; +import { connection } from "next/server"; +import postgres from "postgres"; + +type customerInvoiceDbResponse = { + id: string; + name: string; + image_url: string; + email: string; + amount: string; +} + +export default class CustomerDbRepo implements CustomerInvoiceRepo { + async fetchList(): Promise<CustomerInvoice[]> { + // This is equivalent to in fetch(..., {cache: 'no-store'}). + connection() + + try { + const data = await sql` + SELECT invoices.amount, customers.name, customers.image_url, customers.email, invoices.id + FROM invoices + JOIN customers ON invoices.customer_id = customers.id + ORDER BY invoices.date DESC + LIMIT 5` as postgres.RowList<customerInvoiceDbResponse[]>; + + return this.customerInvoicesDto(data) + } catch (error) { + console.error('Database Error:', error); + throw new Error('Failed to fetch the latest invoices.'); + } + } + + + private customerInvoicesDto(dbCustomers: customerInvoiceDbResponse[]): CustomerInvoice[] { + return dbCustomers.map((customer) => this.customerInvoiceDto(customer)); + } + + private customerInvoiceDto(dbCustomer: customerInvoiceDbResponse): CustomerInvoice { + return new CustomerInvoice({ + id: dbCustomer.id, + customerName: dbCustomer.name, + customerEmail: dbCustomer.email, + customerImageUrl: dbCustomer.image_url, + invoicesAmount: formatCurrency(+dbCustomer.amount), + }) + } + +} \ No newline at end of file diff --git a/src/feature/customer-invoice/domain/entity/customer-invoice.ts b/src/feature/customer-invoice/domain/entity/customer-invoice.ts new file mode 100644 index 0000000..783654c --- /dev/null +++ b/src/feature/customer-invoice/domain/entity/customer-invoice.ts @@ -0,0 +1,21 @@ +export default class CustomerInvoice { + id: string; + customerName: string; + customerImageUrl: string; + customerEmail: string; + invoicesAmount: string; + + constructor({ + id, + customerEmail, + customerImageUrl, + customerName, + invoicesAmount + }: CustomerInvoice) { + this.id = id; + this.customerEmail = customerEmail + this.customerImageUrl = customerImageUrl + this.customerName = customerName + this.invoicesAmount = invoicesAmount + } +} \ No newline at end of file diff --git a/src/feature/customer-invoice/domain/i-repo/customer-invoice-repo.ts b/src/feature/customer-invoice/domain/i-repo/customer-invoice-repo.ts new file mode 100644 index 0000000..f3f5eba --- /dev/null +++ b/src/feature/customer-invoice/domain/i-repo/customer-invoice-repo.ts @@ -0,0 +1,7 @@ +import CustomerInvoice from "@/feature/customer-invoice/domain/entity/customer-invoice" + +export default interface CustomerInvoiceRepo { + fetchList(): Promise<CustomerInvoice[]> +} + +export const customerInvoiceRepoKey = "customerInvoiceRepoKey" \ No newline at end of file diff --git a/src/feature/customer-invoice/domain/usecase/fetch-customer-invoices-usecase.ts b/src/feature/customer-invoice/domain/usecase/fetch-customer-invoices-usecase.ts new file mode 100644 index 0000000..1f16825 --- /dev/null +++ b/src/feature/customer-invoice/domain/usecase/fetch-customer-invoices-usecase.ts @@ -0,0 +1,11 @@ +"use server" +import serverDi from "@/feature/common/server-di"; +import CustomerInvoice from "@/feature/customer-invoice/domain/entity/customer-invoice"; +import CustomerInvoiceRepo, { customerInvoiceRepoKey } from "@/feature/customer-invoice/domain/i-repo/customer-invoice-repo"; +import { customerInvoiceModuleKey } from "@/feature/customer-invoice/invoice-module-key"; + +export default function fetchCustomerInvoicesUsecase(): Promise<CustomerInvoice[]> { + const repo = serverDi(customerInvoiceModuleKey).resolve<CustomerInvoiceRepo>(customerInvoiceRepoKey) + + return repo.fetchList() +} \ No newline at end of file diff --git a/src/feature/customer-invoice/invoice-module-key.ts b/src/feature/customer-invoice/invoice-module-key.ts new file mode 100644 index 0000000..6ab1512 --- /dev/null +++ b/src/feature/customer-invoice/invoice-module-key.ts @@ -0,0 +1 @@ +export const customerInvoiceModuleKey = "customerInvoiceModuleKey" \ No newline at end of file diff --git a/src/feature/customer/data/module/customer-di.ts b/src/feature/customer/data/module/customer-di.ts index 05df3ae..4d153a8 100644 --- a/src/feature/customer/data/module/customer-di.ts +++ b/src/feature/customer/data/module/customer-di.ts @@ -1,4 +1,6 @@ import di from "@/bootstrap/di/init-di"; +import CustomerDbRepo from "@/feature/customer/data/repo/customer-db-repo"; +import { customerRepoKey } from "@/feature/customer/domain/i-repo/customer-repo"; import fetchCustomersUsecase from "@/feature/customer/domain/usecase/fetch-customers-usecase"; import { DependencyContainer } from "tsyringe"; @@ -9,5 +11,6 @@ export default function getCustomerDi(): DependencyContainer { useValue: fetchCustomersUsecase }) + customerDi.register(customerRepoKey, CustomerDbRepo) return customerDi } \ No newline at end of file diff --git a/src/feature/customer/data/repo/customer-db-repo.ts b/src/feature/customer/data/repo/customer-db-repo.ts new file mode 100644 index 0000000..fec27e1 --- /dev/null +++ b/src/feature/customer/data/repo/customer-db-repo.ts @@ -0,0 +1,66 @@ +import { formatCurrency } from "@/app/lib/utils"; +import { sql } from "@/bootstrap/db/db"; +import Customer from "@/feature/customer/domain/entity/customer"; +import CustomerRepo from "@/feature/customer/domain/i-repo/customer-repo"; +import { connection } from "next/server"; +import postgres from "postgres"; + +type customerDbResponse = { + id: string; + name: string; + email: string; + image_url: string; + total_invoices: string; + total_pending: string; + total_paid: string; +} + +export default class CustomerDbRepo implements CustomerRepo { + async fetchList(query: string): Promise<Customer[]> { + // This is equivalent to in fetch(..., {cache: 'no-store'}). + connection() + try { + const data = await sql` + SELECT + customers.id, + customers.name, + customers.email, + customers.image_url, + COUNT(invoices.id) AS total_invoices, + SUM(CASE WHEN invoices.status = 'pending' THEN invoices.amount ELSE 0 END) AS total_pending, + SUM(CASE WHEN invoices.status = 'paid' THEN invoices.amount ELSE 0 END) AS total_paid + FROM customers + LEFT JOIN invoices ON customers.id = invoices.customer_id + WHERE + customers.name ILIKE ${`%${query}%`} OR + customers.email ILIKE ${`%${query}%`} + GROUP BY customers.id, customers.name, customers.email, customers.image_url + ORDER BY customers.name ASC + ` as postgres.RowList<customerDbResponse[]>; + + + return this.customersDto(data); + } catch (err) { + console.error('Database Error:', err); + throw new Error('Failed to fetch customer table.'); + } + } + + + private customersDto(dbCustomers: customerDbResponse[]): Customer[] { + return dbCustomers.map((customer) => this.customerDto(customer)); + } + + private customerDto(dbCustomer: customerDbResponse): Customer { + return new Customer({ + id: dbCustomer.id, + name: dbCustomer.name, + email: dbCustomer.email, + imageUrl: dbCustomer.image_url, + totalInvoices: dbCustomer.total_invoices, + totalPending: formatCurrency(Number(dbCustomer.total_pending)), + totalPaid: formatCurrency(Number(dbCustomer.total_paid)), + }) + } + +} \ No newline at end of file diff --git a/src/feature/customer/domain/entity/customer.ts b/src/feature/customer/domain/entity/customer.ts index 3b13a69..6f32ec3 100644 --- a/src/feature/customer/domain/entity/customer.ts +++ b/src/feature/customer/domain/entity/customer.ts @@ -1,21 +1,11 @@ -export type CustomersTableType = { - id: string; - name: string; - email: string; - image_url: string; - total_invoices: number; - total_pending: number; - total_paid: number; -}; - export default class Customer { id: string; name: string; email: string; imageUrl: string; - totalInvoices: number; - totalPending: number; - totalPaid: number; + totalInvoices: string; + totalPending: string; + totalPaid: string; constructor({ id, diff --git a/src/test/common/fake-factory/customer/customer-fake-factory.ts b/src/test/common/fake-factory/customer/customer-fake-factory.ts index be69bec..cf7a53c 100644 --- a/src/test/common/fake-factory/customer/customer-fake-factory.ts +++ b/src/test/common/fake-factory/customer/customer-fake-factory.ts @@ -8,9 +8,9 @@ export default class CustomerFakeFactory { name: faker.person.fullName(), email: faker.internet.email(), imageUrl: faker.image.url(), - totalInvoices: faker.number.int(), - totalPaid: faker.number.int(), - totalPending: faker.number.int(), + totalInvoices: faker.number.int().toLocaleString(), + totalPaid: faker.finance.amount(), + totalPending: faker.number.int().toLocaleString(), }) } -- 2.39.5 From 67be77ab9c8e1e470e5b3897e0aeb0a3b23cb2c5 Mon Sep 17 00:00:00 2001 From: behnam <behnamrahimpour74@gmail.com> Date: Fri, 1 Nov 2024 15:45:53 +0300 Subject: [PATCH 09/37] Add fetch amount of invoice module --- src/app/lib/data.ts | 24 ------------------- src/app/lib/definitions.ts | 8 ------- src/feature/common/server-di.ts | 8 ++++++- .../data/module/customer-di.ts | 16 ------------- .../data/module/customer-invoice-di.ts | 16 +++++++++++++ src/feature/invoice/data/module/invoice-di.ts | 16 +++++++++++++ .../invoice/data/repo/invoice-db-repo.ts | 11 +++++++++ .../invoice/domain/i-repo/invoice-repo.ts | 6 +++++ .../fetch-all-invoices-amount-usecase.ts | 10 ++++++++ src/feature/invoice/invoice-module-key.ts | 1 + 10 files changed, 67 insertions(+), 49 deletions(-) delete mode 100644 src/feature/customer-invoice/data/module/customer-di.ts create mode 100644 src/feature/customer-invoice/data/module/customer-invoice-di.ts create mode 100644 src/feature/invoice/data/module/invoice-di.ts create mode 100644 src/feature/invoice/data/repo/invoice-db-repo.ts create mode 100644 src/feature/invoice/domain/i-repo/invoice-repo.ts create mode 100644 src/feature/invoice/domain/usecase/fetch-all-invoices-amount-usecase.ts create mode 100644 src/feature/invoice/invoice-module-key.ts diff --git a/src/app/lib/data.ts b/src/app/lib/data.ts index d76cf24..b28fcb0 100644 --- a/src/app/lib/data.ts +++ b/src/app/lib/data.ts @@ -3,7 +3,6 @@ import { Revenue, Invoice, Customer, - LatestInvoice, } from './definitions'; import { formatCurrency } from './utils'; import postgres from 'postgres'; @@ -31,29 +30,6 @@ export async function fetchRevenue() { } } -export async function fetchLatestInvoices() { - // This is equivalent to in fetch(..., {cache: 'no-store'}). - connection() - - try { - const data = await sql` - SELECT invoices.amount, customers.name, customers.image_url, customers.email, invoices.id - FROM invoices - JOIN customers ON invoices.customer_id = customers.id - ORDER BY invoices.date DESC - LIMIT 5` as postgres.RowList<LatestInvoice[]>; - - const latestInvoices = data.map((invoice) => ({ - ...invoice, - amount: formatCurrency(+invoice.amount), - })); - return latestInvoices; - } catch (error) { - console.error('Database Error:', error); - throw new Error('Failed to fetch the latest invoices.'); - } -} - export async function fetchCardData() { // This is equivalent to in fetch(..., {cache: 'no-store'}). connection() diff --git a/src/app/lib/definitions.ts b/src/app/lib/definitions.ts index e4cf179..b26dd32 100644 --- a/src/app/lib/definitions.ts +++ b/src/app/lib/definitions.ts @@ -18,14 +18,6 @@ export type Revenue = { revenue: number; }; -export type LatestInvoice = { - id: string; - name: string; - image_url: string; - email: string; - amount: string; -}; - export type InvoiceForm = { id: string; customer_id: string; diff --git a/src/feature/common/server-di.ts b/src/feature/common/server-di.ts index 78095a9..bd28b80 100644 --- a/src/feature/common/server-di.ts +++ b/src/feature/common/server-di.ts @@ -1,13 +1,19 @@ +import getCustomerInvoiceDi from "@/feature/customer-invoice/data/module/customer-invoice-di"; +import { customerInvoiceModuleKey } from "@/feature/customer-invoice/invoice-module-key"; import { customerKey } from "@/feature/customer/customer-key"; import getCustomerDi from "@/feature/customer/data/module/customer-di"; import { testModuleKey } from "@/feature/domain/test/test-module-key"; import getTestModule from "@/feature/infra/test/module/test-module"; +import getInvoiceDi from "@/feature/invoice/data/module/invoice-di"; +import { invoiceModuleKey } from "@/feature/invoice/invoice-module-key"; import { DependencyContainer } from "tsyringe"; export default function serverDi(module: string): DependencyContainer { const getDi = { [testModuleKey]: getTestModule, - [customerKey]: getCustomerDi + [customerKey]: getCustomerDi, + [customerInvoiceModuleKey]: getCustomerInvoiceDi, + [invoiceModuleKey]: getInvoiceDi, }[module] if (!getDi) throw new Error("Server Di didn't found for module: " + module) diff --git a/src/feature/customer-invoice/data/module/customer-di.ts b/src/feature/customer-invoice/data/module/customer-di.ts deleted file mode 100644 index 4d153a8..0000000 --- a/src/feature/customer-invoice/data/module/customer-di.ts +++ /dev/null @@ -1,16 +0,0 @@ -import di from "@/bootstrap/di/init-di"; -import CustomerDbRepo from "@/feature/customer/data/repo/customer-db-repo"; -import { customerRepoKey } from "@/feature/customer/domain/i-repo/customer-repo"; -import fetchCustomersUsecase from "@/feature/customer/domain/usecase/fetch-customers-usecase"; -import { DependencyContainer } from "tsyringe"; - -export default function getCustomerDi(): DependencyContainer { - const customerDi = di.createChildContainer() - - customerDi.register(fetchCustomersUsecase.name, { - useValue: fetchCustomersUsecase - }) - - customerDi.register(customerRepoKey, CustomerDbRepo) - return customerDi -} \ No newline at end of file diff --git a/src/feature/customer-invoice/data/module/customer-invoice-di.ts b/src/feature/customer-invoice/data/module/customer-invoice-di.ts new file mode 100644 index 0000000..fa6712e --- /dev/null +++ b/src/feature/customer-invoice/data/module/customer-invoice-di.ts @@ -0,0 +1,16 @@ +import di from "@/bootstrap/di/init-di"; +import { customerInvoiceRepoKey } from "@/feature/customer-invoice/domain/i-repo/customer-invoice-repo"; +import fetchCustomerInvoicesUsecase from "@/feature/customer-invoice/domain/usecase/fetch-customer-invoices-usecase"; +import CustomerDbRepo from "@/feature/customer/data/repo/customer-db-repo"; +import { DependencyContainer } from "tsyringe"; + +export default function getCustomerInvoiceInvoiceDi(): DependencyContainer { + const customerInvoiceDi = di.createChildContainer() + + customerInvoiceDi.register(fetchCustomerInvoicesUsecase.name, { + useValue: fetchCustomerInvoicesUsecase + }) + + customerInvoiceDi.register(customerInvoiceRepoKey, CustomerDbRepo) + return customerInvoiceDi +} \ No newline at end of file diff --git a/src/feature/invoice/data/module/invoice-di.ts b/src/feature/invoice/data/module/invoice-di.ts new file mode 100644 index 0000000..28ce2e0 --- /dev/null +++ b/src/feature/invoice/data/module/invoice-di.ts @@ -0,0 +1,16 @@ +import di from "@/bootstrap/di/init-di"; +import invoiceDbRepo from "@/feature/invoice/data/repo/invoice-db-repo"; +import { invoiceRepoKey } from "@/feature/invoice/domain/i-repo/invoice-repo"; +import fetchAllInvoicesAmountUsecase from "@/feature/invoice/domain/usecase/fetch-all-invoices-amount-usecase"; +import { DependencyContainer } from "tsyringe"; + +export default function getInvoiceDi(): DependencyContainer { + const invoiceDi = di.createChildContainer() + + invoiceDi.register(fetchAllInvoicesAmountUsecase.name, { + useValue: fetchAllInvoicesAmountUsecase + }) + + invoiceDi.register(invoiceRepoKey, invoiceDbRepo) + return invoiceDi +} \ No newline at end of file diff --git a/src/feature/invoice/data/repo/invoice-db-repo.ts b/src/feature/invoice/data/repo/invoice-db-repo.ts new file mode 100644 index 0000000..5191d67 --- /dev/null +++ b/src/feature/invoice/data/repo/invoice-db-repo.ts @@ -0,0 +1,11 @@ +import { sql } from "@/bootstrap/db/db"; +import InvoiceRepo from "@/feature/invoice/domain/i-repo/invoice-repo"; +import postgres from "postgres"; + +export default class InvoiceDbRepo implements InvoiceRepo { + async fetchAllInvoicesAmount(): Promise<number> { + const data = await sql`SELECT COUNT(*) FROM invoices` as postgres.RowList<unknown[]>; + + return data.count ?? 0 + } +} \ No newline at end of file diff --git a/src/feature/invoice/domain/i-repo/invoice-repo.ts b/src/feature/invoice/domain/i-repo/invoice-repo.ts new file mode 100644 index 0000000..fb4c8a2 --- /dev/null +++ b/src/feature/invoice/domain/i-repo/invoice-repo.ts @@ -0,0 +1,6 @@ + +export default interface InvoiceRepo { + fetchAllInvoicesAmount(): Promise<number> +} + +export const invoiceRepoKey = "invoiceRepoKey" \ No newline at end of file diff --git a/src/feature/invoice/domain/usecase/fetch-all-invoices-amount-usecase.ts b/src/feature/invoice/domain/usecase/fetch-all-invoices-amount-usecase.ts new file mode 100644 index 0000000..1922f81 --- /dev/null +++ b/src/feature/invoice/domain/usecase/fetch-all-invoices-amount-usecase.ts @@ -0,0 +1,10 @@ +"use server" +import serverDi from "@/feature/common/server-di"; +import InvoiceRepo, { invoiceRepoKey } from "@/feature/invoice/domain/i-repo/invoice-repo"; +import { invoiceModuleKey } from "@/feature/invoice/invoice-module-key"; + +export default function fetchAllInvoicesAmountUsecase(): Promise<number> { + const repo = serverDi(invoiceModuleKey).resolve<InvoiceRepo>(invoiceRepoKey) + + return repo.fetchAllInvoicesAmount() +} \ No newline at end of file diff --git a/src/feature/invoice/invoice-module-key.ts b/src/feature/invoice/invoice-module-key.ts new file mode 100644 index 0000000..c9cafd9 --- /dev/null +++ b/src/feature/invoice/invoice-module-key.ts @@ -0,0 +1 @@ +export const invoiceModuleKey = "invoiceModuleKey" \ No newline at end of file -- 2.39.5 From 5704cf6ff95a50a8a1e36ac891b312c8a758f23b Mon Sep 17 00:00:00 2001 From: behnam <behnamrahimpour74@gmail.com> Date: Fri, 1 Nov 2024 16:02:29 +0300 Subject: [PATCH 10/37] Add fetch invoices status summary module --- src/app/lib/data.ts | 3 ++- .../data/module/customer-invoice-di.ts | 2 +- src/feature/invoice/data/module/invoice-di.ts | 5 ----- .../invoice/data/repo/invoice-db-repo.ts | 22 ++++++++++++++++++- .../invoice/domain/i-repo/invoice-repo.ts | 2 ++ .../usecase/fetch-invoices-status-summary.ts | 9 ++++++++ .../domain/value-object/invoice-status.ts | 12 ++++++++++ 7 files changed, 47 insertions(+), 8 deletions(-) create mode 100644 src/feature/invoice/domain/usecase/fetch-invoices-status-summary.ts create mode 100644 src/feature/invoice/domain/value-object/invoice-status.ts diff --git a/src/app/lib/data.ts b/src/app/lib/data.ts index b28fcb0..6326383 100644 --- a/src/app/lib/data.ts +++ b/src/app/lib/data.ts @@ -41,6 +41,7 @@ export async function fetchCardData() { const invoiceCountPromise = sql`SELECT COUNT(*) FROM invoices`; const customerCountPromise = sql`SELECT COUNT(*) FROM customers`; const invoiceStatusPromise = sql`SELECT + id, SUM(CASE WHEN status = 'paid' THEN amount ELSE 0 END) AS "paid", SUM(CASE WHEN status = 'pending' THEN amount ELSE 0 END) AS "pending" FROM invoices`; @@ -53,7 +54,7 @@ export async function fetchCardData() { const invoices = data[0] as postgres.RowList<Invoice[]> const customres = data[1] as postgres.RowList<Customer[]> - const invoiceStatus = data[2] as postgres.RowList<({paid: string, pending: string})[]> + const invoiceStatus = data[2] as postgres.RowList<({id: string; paid: string, pending: string})[]> const numberOfInvoices = Number(invoices.count ?? '0'); const numberOfCustomers = Number(customres.count ?? '0'); const totalPaidInvoices = formatCurrency(Number(invoiceStatus.at(0)?.paid ?? '0')); diff --git a/src/feature/customer-invoice/data/module/customer-invoice-di.ts b/src/feature/customer-invoice/data/module/customer-invoice-di.ts index fa6712e..d1a93f1 100644 --- a/src/feature/customer-invoice/data/module/customer-invoice-di.ts +++ b/src/feature/customer-invoice/data/module/customer-invoice-di.ts @@ -4,7 +4,7 @@ import fetchCustomerInvoicesUsecase from "@/feature/customer-invoice/domain/usec import CustomerDbRepo from "@/feature/customer/data/repo/customer-db-repo"; import { DependencyContainer } from "tsyringe"; -export default function getCustomerInvoiceInvoiceDi(): DependencyContainer { +export default function getCustomerInvoiceDi(): DependencyContainer { const customerInvoiceDi = di.createChildContainer() customerInvoiceDi.register(fetchCustomerInvoicesUsecase.name, { diff --git a/src/feature/invoice/data/module/invoice-di.ts b/src/feature/invoice/data/module/invoice-di.ts index 28ce2e0..c7c133a 100644 --- a/src/feature/invoice/data/module/invoice-di.ts +++ b/src/feature/invoice/data/module/invoice-di.ts @@ -1,16 +1,11 @@ import di from "@/bootstrap/di/init-di"; import invoiceDbRepo from "@/feature/invoice/data/repo/invoice-db-repo"; import { invoiceRepoKey } from "@/feature/invoice/domain/i-repo/invoice-repo"; -import fetchAllInvoicesAmountUsecase from "@/feature/invoice/domain/usecase/fetch-all-invoices-amount-usecase"; import { DependencyContainer } from "tsyringe"; export default function getInvoiceDi(): DependencyContainer { const invoiceDi = di.createChildContainer() - invoiceDi.register(fetchAllInvoicesAmountUsecase.name, { - useValue: fetchAllInvoicesAmountUsecase - }) - invoiceDi.register(invoiceRepoKey, invoiceDbRepo) return invoiceDi } \ No newline at end of file diff --git a/src/feature/invoice/data/repo/invoice-db-repo.ts b/src/feature/invoice/data/repo/invoice-db-repo.ts index 5191d67..bc7c2a8 100644 --- a/src/feature/invoice/data/repo/invoice-db-repo.ts +++ b/src/feature/invoice/data/repo/invoice-db-repo.ts @@ -1,11 +1,31 @@ +import { formatCurrency } from "@/app/lib/utils"; import { sql } from "@/bootstrap/db/db"; import InvoiceRepo from "@/feature/invoice/domain/i-repo/invoice-repo"; +import InvoiceStatusSummary from "@/feature/invoice/domain/value-object/invoice-status"; import postgres from "postgres"; +type InvoiceSummaryDbResponse = {paid: string, pending: string} export default class InvoiceDbRepo implements InvoiceRepo { async fetchAllInvoicesAmount(): Promise<number> { const data = await sql`SELECT COUNT(*) FROM invoices` as postgres.RowList<unknown[]>; - + return data.count ?? 0 } + + async fetchInvoicesStatusSummary(): Promise<InvoiceStatusSummary> { + const invoiceStatusPromise = await sql`SELECT + SUM(CASE WHEN status = 'paid' THEN amount ELSE 0 END) AS "paid", + SUM(CASE WHEN status = 'pending' THEN amount ELSE 0 END) AS "pending" + FROM invoices` as postgres.RowList<InvoiceSummaryDbResponse[]>; + + return this.invoiceSummaryDto(invoiceStatusPromise.at(0)) + + } + + private invoiceSummaryDto(dbResponse?: InvoiceSummaryDbResponse): InvoiceStatusSummary { + return new InvoiceStatusSummary({ + paid: formatCurrency(Number(dbResponse?.paid ?? '0')), + pending: formatCurrency(Number(dbResponse?.pending ?? '0')) + }) + } } \ No newline at end of file diff --git a/src/feature/invoice/domain/i-repo/invoice-repo.ts b/src/feature/invoice/domain/i-repo/invoice-repo.ts index fb4c8a2..085421c 100644 --- a/src/feature/invoice/domain/i-repo/invoice-repo.ts +++ b/src/feature/invoice/domain/i-repo/invoice-repo.ts @@ -1,6 +1,8 @@ +import InvoiceStatusSummary from "@/feature/invoice/domain/value-object/invoice-status" export default interface InvoiceRepo { fetchAllInvoicesAmount(): Promise<number> + fetchInvoicesStatusSummary(): Promise<InvoiceStatusSummary> } export const invoiceRepoKey = "invoiceRepoKey" \ No newline at end of file diff --git a/src/feature/invoice/domain/usecase/fetch-invoices-status-summary.ts b/src/feature/invoice/domain/usecase/fetch-invoices-status-summary.ts new file mode 100644 index 0000000..f35a4dc --- /dev/null +++ b/src/feature/invoice/domain/usecase/fetch-invoices-status-summary.ts @@ -0,0 +1,9 @@ +import serverDi from "@/feature/common/server-di"; +import InvoiceRepo, { invoiceRepoKey } from "@/feature/invoice/domain/i-repo/invoice-repo"; +import InvoiceStatusSummary from "@/feature/invoice/domain/value-object/invoice-status"; +import { invoiceModuleKey } from "@/feature/invoice/invoice-module-key"; + +export default function fetchInvoicesStatusSummary(): Promise<InvoiceStatusSummary> { + const repo = serverDi(invoiceModuleKey).resolve<InvoiceRepo>(invoiceRepoKey) + return repo.fetchInvoicesStatusSummary() +} \ No newline at end of file diff --git a/src/feature/invoice/domain/value-object/invoice-status.ts b/src/feature/invoice/domain/value-object/invoice-status.ts new file mode 100644 index 0000000..b2c393c --- /dev/null +++ b/src/feature/invoice/domain/value-object/invoice-status.ts @@ -0,0 +1,12 @@ +export default class InvoiceStatusSummary { + paid: string; + pending: string; + + constructor({ + paid, + pending + }: InvoiceStatusSummary) { + this.paid = paid; + this.pending = pending; + } +} \ No newline at end of file -- 2.39.5 From b6a15e0579a9c834a7c46925869ae1d41d4b7e11 Mon Sep 17 00:00:00 2001 From: behnam <behnamrahimpour74@gmail.com> Date: Fri, 1 Nov 2024 16:06:43 +0300 Subject: [PATCH 11/37] Add fetch all customers module --- src/feature/customer/data/repo/customer-db-repo.ts | 5 +++++ src/feature/customer/domain/i-repo/customer-repo.ts | 1 + .../domain/usecase/fetch-customers-amount-usecase.ts | 8 ++++++++ 3 files changed, 14 insertions(+) create mode 100644 src/feature/customer/domain/usecase/fetch-customers-amount-usecase.ts diff --git a/src/feature/customer/data/repo/customer-db-repo.ts b/src/feature/customer/data/repo/customer-db-repo.ts index fec27e1..f69239a 100644 --- a/src/feature/customer/data/repo/customer-db-repo.ts +++ b/src/feature/customer/data/repo/customer-db-repo.ts @@ -46,6 +46,11 @@ export default class CustomerDbRepo implements CustomerRepo { } } + async fetchCustomersAmount(): Promise<number> { + const data = await sql`SELECT COUNT(*) FROM customers`as postgres.RowList<unknown[]>; + return Number(data.count ?? '0'); + } + private customersDto(dbCustomers: customerDbResponse[]): Customer[] { return dbCustomers.map((customer) => this.customerDto(customer)); diff --git a/src/feature/customer/domain/i-repo/customer-repo.ts b/src/feature/customer/domain/i-repo/customer-repo.ts index 5c9cbf2..08e8226 100644 --- a/src/feature/customer/domain/i-repo/customer-repo.ts +++ b/src/feature/customer/domain/i-repo/customer-repo.ts @@ -2,6 +2,7 @@ import Customer from "@/feature/customer/domain/entity/customer" export default interface CustomerRepo { fetchList(query: string): Promise<Customer[]> + fetchCustomersAmount(): Promise<number> } export const customerRepoKey = "customerRepoKey" \ No newline at end of file diff --git a/src/feature/customer/domain/usecase/fetch-customers-amount-usecase.ts b/src/feature/customer/domain/usecase/fetch-customers-amount-usecase.ts new file mode 100644 index 0000000..608ae37 --- /dev/null +++ b/src/feature/customer/domain/usecase/fetch-customers-amount-usecase.ts @@ -0,0 +1,8 @@ +import serverDi from "@/feature/common/server-di"; +import { customerKey } from "@/feature/customer/customer-key"; +import CustomerRepo, { customerRepoKey } from "@/feature/customer/domain/i-repo/customer-repo"; + +export default function fetchCustomersAmountUsecase(): Promise<number> { + const repo = serverDi(customerKey).resolve<CustomerRepo>(customerRepoKey) + return repo.fetchCustomersAmount() +} \ No newline at end of file -- 2.39.5 From 2d8774ae3634570721e9440e50f0cb798b61d209 Mon Sep 17 00:00:00 2001 From: behnam <behnamrahimpour74@gmail.com> Date: Fri, 1 Nov 2024 16:08:19 +0300 Subject: [PATCH 12/37] Add core subdomain and fix location of domains in feature layer --- src/feature/common/server-di.ts | 12 ++++++------ .../data/module/customer-invoice-di.ts | 6 +++--- .../data/repo/customer-invoice-db-repo.ts | 4 ++-- .../domain/entity/customer-invoice.ts | 0 .../domain/i-repo/customer-invoice-repo.ts | 7 +++++++ .../usecase/fetch-customer-invoices-usecase.ts | 6 +++--- .../customer-invoice/invoice-module-key.ts | 0 src/feature/{ => core}/customer/customer-key.ts | 0 .../{ => core}/customer/data/module/customer-di.ts | 6 +++--- .../customer/data/repo/customer-db-repo.ts | 4 ++-- .../{ => core}/customer/domain/entity/customer.ts | 0 .../customer/domain/i-repo/customer-repo.ts | 2 +- .../domain/usecase/fetch-customers-amount-usecase.ts | 4 ++-- .../domain/usecase/fetch-customers-usecase.ts | 6 +++--- .../{ => core}/invoice/data/module/invoice-di.ts | 4 ++-- .../{ => core}/invoice/data/repo/invoice-db-repo.ts | 4 ++-- .../{ => core}/invoice/domain/i-repo/invoice-repo.ts | 2 +- .../usecase/fetch-all-invoices-amount-usecase.ts | 4 ++-- .../domain/usecase/fetch-invoices-status-summary.ts | 9 +++++++++ .../invoice/domain/value-object/invoice-status.ts | 0 src/feature/{ => core}/invoice/invoice-module-key.ts | 0 .../domain/i-repo/customer-invoice-repo.ts | 7 ------- .../domain/usecase/fetch-invoices-status-summary.ts | 9 --------- .../fake-factory/customer/customer-fake-factory.ts | 2 +- .../domain/usecase/fetch-customers-usecase.test.ts | 4 ++-- 25 files changed, 51 insertions(+), 51 deletions(-) rename src/feature/{ => core}/customer-invoice/data/module/customer-invoice-di.ts (58%) rename src/feature/{ => core}/customer-invoice/data/repo/customer-invoice-db-repo.ts (89%) rename src/feature/{ => core}/customer-invoice/domain/entity/customer-invoice.ts (100%) create mode 100644 src/feature/core/customer-invoice/domain/i-repo/customer-invoice-repo.ts rename src/feature/{ => core}/customer-invoice/domain/usecase/fetch-customer-invoices-usecase.ts (57%) rename src/feature/{ => core}/customer-invoice/invoice-module-key.ts (100%) rename src/feature/{ => core}/customer/customer-key.ts (100%) rename src/feature/{ => core}/customer/data/module/customer-di.ts (58%) rename src/feature/{ => core}/customer/data/repo/customer-db-repo.ts (94%) rename src/feature/{ => core}/customer/domain/entity/customer.ts (100%) rename src/feature/{ => core}/customer/domain/i-repo/customer-repo.ts (53%) rename src/feature/{ => core}/customer/domain/usecase/fetch-customers-amount-usecase.ts (58%) rename src/feature/{ => core}/customer/domain/usecase/fetch-customers-usecase.ts (52%) rename src/feature/{ => core}/invoice/data/module/invoice-di.ts (62%) rename src/feature/{ => core}/invoice/data/repo/invoice-db-repo.ts (87%) rename src/feature/{ => core}/invoice/domain/i-repo/invoice-repo.ts (52%) rename src/feature/{ => core}/invoice/domain/usecase/fetch-all-invoices-amount-usecase.ts (59%) create mode 100644 src/feature/core/invoice/domain/usecase/fetch-invoices-status-summary.ts rename src/feature/{ => core}/invoice/domain/value-object/invoice-status.ts (100%) rename src/feature/{ => core}/invoice/invoice-module-key.ts (100%) delete mode 100644 src/feature/customer-invoice/domain/i-repo/customer-invoice-repo.ts delete mode 100644 src/feature/invoice/domain/usecase/fetch-invoices-status-summary.ts diff --git a/src/feature/common/server-di.ts b/src/feature/common/server-di.ts index bd28b80..af68905 100644 --- a/src/feature/common/server-di.ts +++ b/src/feature/common/server-di.ts @@ -1,11 +1,11 @@ -import getCustomerInvoiceDi from "@/feature/customer-invoice/data/module/customer-invoice-di"; -import { customerInvoiceModuleKey } from "@/feature/customer-invoice/invoice-module-key"; -import { customerKey } from "@/feature/customer/customer-key"; -import getCustomerDi from "@/feature/customer/data/module/customer-di"; +import getCustomerInvoiceDi from "@/feature/core/customer-invoice/data/module/customer-invoice-di"; +import { customerInvoiceModuleKey } from "@/feature/core/customer-invoice/invoice-module-key"; +import { customerKey } from "@/feature/core/customer/customer-key"; +import getCustomerDi from "@/feature/core/customer/data/module/customer-di"; import { testModuleKey } from "@/feature/domain/test/test-module-key"; import getTestModule from "@/feature/infra/test/module/test-module"; -import getInvoiceDi from "@/feature/invoice/data/module/invoice-di"; -import { invoiceModuleKey } from "@/feature/invoice/invoice-module-key"; +import getInvoiceDi from "@/feature/core/invoice/data/module/invoice-di"; +import { invoiceModuleKey } from "@/feature/core/invoice/invoice-module-key"; import { DependencyContainer } from "tsyringe"; export default function serverDi(module: string): DependencyContainer { diff --git a/src/feature/customer-invoice/data/module/customer-invoice-di.ts b/src/feature/core/customer-invoice/data/module/customer-invoice-di.ts similarity index 58% rename from src/feature/customer-invoice/data/module/customer-invoice-di.ts rename to src/feature/core/customer-invoice/data/module/customer-invoice-di.ts index d1a93f1..76a7453 100644 --- a/src/feature/customer-invoice/data/module/customer-invoice-di.ts +++ b/src/feature/core/customer-invoice/data/module/customer-invoice-di.ts @@ -1,7 +1,7 @@ import di from "@/bootstrap/di/init-di"; -import { customerInvoiceRepoKey } from "@/feature/customer-invoice/domain/i-repo/customer-invoice-repo"; -import fetchCustomerInvoicesUsecase from "@/feature/customer-invoice/domain/usecase/fetch-customer-invoices-usecase"; -import CustomerDbRepo from "@/feature/customer/data/repo/customer-db-repo"; +import { customerInvoiceRepoKey } from "@/feature/core/customer-invoice/domain/i-repo/customer-invoice-repo"; +import fetchCustomerInvoicesUsecase from "@/feature/core/customer-invoice/domain/usecase/fetch-customer-invoices-usecase"; +import CustomerDbRepo from "@/feature/core/customer/data/repo/customer-db-repo"; import { DependencyContainer } from "tsyringe"; export default function getCustomerInvoiceDi(): DependencyContainer { diff --git a/src/feature/customer-invoice/data/repo/customer-invoice-db-repo.ts b/src/feature/core/customer-invoice/data/repo/customer-invoice-db-repo.ts similarity index 89% rename from src/feature/customer-invoice/data/repo/customer-invoice-db-repo.ts rename to src/feature/core/customer-invoice/data/repo/customer-invoice-db-repo.ts index bd52acc..45ec6ab 100644 --- a/src/feature/customer-invoice/data/repo/customer-invoice-db-repo.ts +++ b/src/feature/core/customer-invoice/data/repo/customer-invoice-db-repo.ts @@ -1,7 +1,7 @@ import { formatCurrency } from "@/app/lib/utils"; import { sql } from "@/bootstrap/db/db"; -import CustomerInvoice from "@/feature/customer-invoice/domain/entity/customer-invoice"; -import CustomerInvoiceRepo from "@/feature/customer-invoice/domain/i-repo/customer-invoice-repo"; +import CustomerInvoice from "@/feature/core/customer-invoice/domain/entity/customer-invoice"; +import CustomerInvoiceRepo from "@/feature/core/customer-invoice/domain/i-repo/customer-invoice-repo"; import { connection } from "next/server"; import postgres from "postgres"; diff --git a/src/feature/customer-invoice/domain/entity/customer-invoice.ts b/src/feature/core/customer-invoice/domain/entity/customer-invoice.ts similarity index 100% rename from src/feature/customer-invoice/domain/entity/customer-invoice.ts rename to src/feature/core/customer-invoice/domain/entity/customer-invoice.ts diff --git a/src/feature/core/customer-invoice/domain/i-repo/customer-invoice-repo.ts b/src/feature/core/customer-invoice/domain/i-repo/customer-invoice-repo.ts new file mode 100644 index 0000000..0a8c993 --- /dev/null +++ b/src/feature/core/customer-invoice/domain/i-repo/customer-invoice-repo.ts @@ -0,0 +1,7 @@ +import CustomerInvoice from "@/feature/core/customer-invoice/domain/entity/customer-invoice" + +export default interface CustomerInvoiceRepo { + fetchList(): Promise<CustomerInvoice[]> +} + +export const customerInvoiceRepoKey = "customerInvoiceRepoKey" \ No newline at end of file diff --git a/src/feature/customer-invoice/domain/usecase/fetch-customer-invoices-usecase.ts b/src/feature/core/customer-invoice/domain/usecase/fetch-customer-invoices-usecase.ts similarity index 57% rename from src/feature/customer-invoice/domain/usecase/fetch-customer-invoices-usecase.ts rename to src/feature/core/customer-invoice/domain/usecase/fetch-customer-invoices-usecase.ts index 1f16825..fd97f46 100644 --- a/src/feature/customer-invoice/domain/usecase/fetch-customer-invoices-usecase.ts +++ b/src/feature/core/customer-invoice/domain/usecase/fetch-customer-invoices-usecase.ts @@ -1,8 +1,8 @@ "use server" import serverDi from "@/feature/common/server-di"; -import CustomerInvoice from "@/feature/customer-invoice/domain/entity/customer-invoice"; -import CustomerInvoiceRepo, { customerInvoiceRepoKey } from "@/feature/customer-invoice/domain/i-repo/customer-invoice-repo"; -import { customerInvoiceModuleKey } from "@/feature/customer-invoice/invoice-module-key"; +import CustomerInvoice from "@/feature/core/customer-invoice/domain/entity/customer-invoice"; +import CustomerInvoiceRepo, { customerInvoiceRepoKey } from "@/feature/core/customer-invoice/domain/i-repo/customer-invoice-repo"; +import { customerInvoiceModuleKey } from "@/feature/core/customer-invoice/invoice-module-key"; export default function fetchCustomerInvoicesUsecase(): Promise<CustomerInvoice[]> { const repo = serverDi(customerInvoiceModuleKey).resolve<CustomerInvoiceRepo>(customerInvoiceRepoKey) diff --git a/src/feature/customer-invoice/invoice-module-key.ts b/src/feature/core/customer-invoice/invoice-module-key.ts similarity index 100% rename from src/feature/customer-invoice/invoice-module-key.ts rename to src/feature/core/customer-invoice/invoice-module-key.ts diff --git a/src/feature/customer/customer-key.ts b/src/feature/core/customer/customer-key.ts similarity index 100% rename from src/feature/customer/customer-key.ts rename to src/feature/core/customer/customer-key.ts diff --git a/src/feature/customer/data/module/customer-di.ts b/src/feature/core/customer/data/module/customer-di.ts similarity index 58% rename from src/feature/customer/data/module/customer-di.ts rename to src/feature/core/customer/data/module/customer-di.ts index 4d153a8..1fa4398 100644 --- a/src/feature/customer/data/module/customer-di.ts +++ b/src/feature/core/customer/data/module/customer-di.ts @@ -1,7 +1,7 @@ import di from "@/bootstrap/di/init-di"; -import CustomerDbRepo from "@/feature/customer/data/repo/customer-db-repo"; -import { customerRepoKey } from "@/feature/customer/domain/i-repo/customer-repo"; -import fetchCustomersUsecase from "@/feature/customer/domain/usecase/fetch-customers-usecase"; +import CustomerDbRepo from "@/feature/core/customer/data/repo/customer-db-repo"; +import { customerRepoKey } from "@/feature/core/customer/domain/i-repo/customer-repo"; +import fetchCustomersUsecase from "@/feature/core/customer/domain/usecase/fetch-customers-usecase"; import { DependencyContainer } from "tsyringe"; export default function getCustomerDi(): DependencyContainer { diff --git a/src/feature/customer/data/repo/customer-db-repo.ts b/src/feature/core/customer/data/repo/customer-db-repo.ts similarity index 94% rename from src/feature/customer/data/repo/customer-db-repo.ts rename to src/feature/core/customer/data/repo/customer-db-repo.ts index f69239a..82c0494 100644 --- a/src/feature/customer/data/repo/customer-db-repo.ts +++ b/src/feature/core/customer/data/repo/customer-db-repo.ts @@ -1,7 +1,7 @@ import { formatCurrency } from "@/app/lib/utils"; import { sql } from "@/bootstrap/db/db"; -import Customer from "@/feature/customer/domain/entity/customer"; -import CustomerRepo from "@/feature/customer/domain/i-repo/customer-repo"; +import Customer from "@/feature/core/customer/domain/entity/customer"; +import CustomerRepo from "@/feature/core/customer/domain/i-repo/customer-repo"; import { connection } from "next/server"; import postgres from "postgres"; diff --git a/src/feature/customer/domain/entity/customer.ts b/src/feature/core/customer/domain/entity/customer.ts similarity index 100% rename from src/feature/customer/domain/entity/customer.ts rename to src/feature/core/customer/domain/entity/customer.ts diff --git a/src/feature/customer/domain/i-repo/customer-repo.ts b/src/feature/core/customer/domain/i-repo/customer-repo.ts similarity index 53% rename from src/feature/customer/domain/i-repo/customer-repo.ts rename to src/feature/core/customer/domain/i-repo/customer-repo.ts index 08e8226..d48fdde 100644 --- a/src/feature/customer/domain/i-repo/customer-repo.ts +++ b/src/feature/core/customer/domain/i-repo/customer-repo.ts @@ -1,4 +1,4 @@ -import Customer from "@/feature/customer/domain/entity/customer" +import Customer from "@/feature/core/customer/domain/entity/customer" export default interface CustomerRepo { fetchList(query: string): Promise<Customer[]> diff --git a/src/feature/customer/domain/usecase/fetch-customers-amount-usecase.ts b/src/feature/core/customer/domain/usecase/fetch-customers-amount-usecase.ts similarity index 58% rename from src/feature/customer/domain/usecase/fetch-customers-amount-usecase.ts rename to src/feature/core/customer/domain/usecase/fetch-customers-amount-usecase.ts index 608ae37..f90d5c3 100644 --- a/src/feature/customer/domain/usecase/fetch-customers-amount-usecase.ts +++ b/src/feature/core/customer/domain/usecase/fetch-customers-amount-usecase.ts @@ -1,6 +1,6 @@ import serverDi from "@/feature/common/server-di"; -import { customerKey } from "@/feature/customer/customer-key"; -import CustomerRepo, { customerRepoKey } from "@/feature/customer/domain/i-repo/customer-repo"; +import { customerKey } from "@/feature/core/customer/customer-key"; +import CustomerRepo, { customerRepoKey } from "@/feature/core/customer/domain/i-repo/customer-repo"; export default function fetchCustomersAmountUsecase(): Promise<number> { const repo = serverDi(customerKey).resolve<CustomerRepo>(customerRepoKey) diff --git a/src/feature/customer/domain/usecase/fetch-customers-usecase.ts b/src/feature/core/customer/domain/usecase/fetch-customers-usecase.ts similarity index 52% rename from src/feature/customer/domain/usecase/fetch-customers-usecase.ts rename to src/feature/core/customer/domain/usecase/fetch-customers-usecase.ts index bf95239..60bd0c5 100644 --- a/src/feature/customer/domain/usecase/fetch-customers-usecase.ts +++ b/src/feature/core/customer/domain/usecase/fetch-customers-usecase.ts @@ -1,9 +1,9 @@ "use server" import serverDi from "@/feature/common/server-di"; -import { customerKey } from "@/feature/customer/customer-key"; -import Customer from "@/feature/customer/domain/entity/customer"; -import CustomerRepo, { customerRepoKey } from "@/feature/customer/domain/i-repo/customer-repo"; +import { customerKey } from "@/feature/core/customer/customer-key"; +import Customer from "@/feature/core/customer/domain/entity/customer"; +import CustomerRepo, { customerRepoKey } from "@/feature/core/customer/domain/i-repo/customer-repo"; export default function fetchCustomersUsecase(query: string): Promise<Customer[]> { const repo = serverDi(customerKey).resolve<CustomerRepo>(customerRepoKey) diff --git a/src/feature/invoice/data/module/invoice-di.ts b/src/feature/core/invoice/data/module/invoice-di.ts similarity index 62% rename from src/feature/invoice/data/module/invoice-di.ts rename to src/feature/core/invoice/data/module/invoice-di.ts index c7c133a..1434954 100644 --- a/src/feature/invoice/data/module/invoice-di.ts +++ b/src/feature/core/invoice/data/module/invoice-di.ts @@ -1,6 +1,6 @@ import di from "@/bootstrap/di/init-di"; -import invoiceDbRepo from "@/feature/invoice/data/repo/invoice-db-repo"; -import { invoiceRepoKey } from "@/feature/invoice/domain/i-repo/invoice-repo"; +import invoiceDbRepo from "@/feature/core/invoice/data/repo/invoice-db-repo"; +import { invoiceRepoKey } from "@/feature/core/invoice/domain/i-repo/invoice-repo"; import { DependencyContainer } from "tsyringe"; export default function getInvoiceDi(): DependencyContainer { diff --git a/src/feature/invoice/data/repo/invoice-db-repo.ts b/src/feature/core/invoice/data/repo/invoice-db-repo.ts similarity index 87% rename from src/feature/invoice/data/repo/invoice-db-repo.ts rename to src/feature/core/invoice/data/repo/invoice-db-repo.ts index bc7c2a8..c9bf5e9 100644 --- a/src/feature/invoice/data/repo/invoice-db-repo.ts +++ b/src/feature/core/invoice/data/repo/invoice-db-repo.ts @@ -1,7 +1,7 @@ import { formatCurrency } from "@/app/lib/utils"; import { sql } from "@/bootstrap/db/db"; -import InvoiceRepo from "@/feature/invoice/domain/i-repo/invoice-repo"; -import InvoiceStatusSummary from "@/feature/invoice/domain/value-object/invoice-status"; +import InvoiceRepo from "@/feature/core/invoice/domain/i-repo/invoice-repo"; +import InvoiceStatusSummary from "@/feature/core/invoice/domain/value-object/invoice-status"; import postgres from "postgres"; type InvoiceSummaryDbResponse = {paid: string, pending: string} diff --git a/src/feature/invoice/domain/i-repo/invoice-repo.ts b/src/feature/core/invoice/domain/i-repo/invoice-repo.ts similarity index 52% rename from src/feature/invoice/domain/i-repo/invoice-repo.ts rename to src/feature/core/invoice/domain/i-repo/invoice-repo.ts index 085421c..90bac8f 100644 --- a/src/feature/invoice/domain/i-repo/invoice-repo.ts +++ b/src/feature/core/invoice/domain/i-repo/invoice-repo.ts @@ -1,4 +1,4 @@ -import InvoiceStatusSummary from "@/feature/invoice/domain/value-object/invoice-status" +import InvoiceStatusSummary from "@/feature/core/invoice/domain/value-object/invoice-status" export default interface InvoiceRepo { fetchAllInvoicesAmount(): Promise<number> diff --git a/src/feature/invoice/domain/usecase/fetch-all-invoices-amount-usecase.ts b/src/feature/core/invoice/domain/usecase/fetch-all-invoices-amount-usecase.ts similarity index 59% rename from src/feature/invoice/domain/usecase/fetch-all-invoices-amount-usecase.ts rename to src/feature/core/invoice/domain/usecase/fetch-all-invoices-amount-usecase.ts index 1922f81..93e2deb 100644 --- a/src/feature/invoice/domain/usecase/fetch-all-invoices-amount-usecase.ts +++ b/src/feature/core/invoice/domain/usecase/fetch-all-invoices-amount-usecase.ts @@ -1,7 +1,7 @@ "use server" import serverDi from "@/feature/common/server-di"; -import InvoiceRepo, { invoiceRepoKey } from "@/feature/invoice/domain/i-repo/invoice-repo"; -import { invoiceModuleKey } from "@/feature/invoice/invoice-module-key"; +import InvoiceRepo, { invoiceRepoKey } from "@/feature/core/invoice/domain/i-repo/invoice-repo"; +import { invoiceModuleKey } from "@/feature/core/invoice/invoice-module-key"; export default function fetchAllInvoicesAmountUsecase(): Promise<number> { const repo = serverDi(invoiceModuleKey).resolve<InvoiceRepo>(invoiceRepoKey) diff --git a/src/feature/core/invoice/domain/usecase/fetch-invoices-status-summary.ts b/src/feature/core/invoice/domain/usecase/fetch-invoices-status-summary.ts new file mode 100644 index 0000000..07c76a8 --- /dev/null +++ b/src/feature/core/invoice/domain/usecase/fetch-invoices-status-summary.ts @@ -0,0 +1,9 @@ +import serverDi from "@/feature/common/server-di"; +import InvoiceRepo, { invoiceRepoKey } from "@/feature/core/invoice/domain/i-repo/invoice-repo"; +import InvoiceStatusSummary from "@/feature/core/invoice/domain/value-object/invoice-status"; +import { invoiceModuleKey } from "@/feature/core/invoice/invoice-module-key"; + +export default function fetchInvoicesStatusSummary(): Promise<InvoiceStatusSummary> { + const repo = serverDi(invoiceModuleKey).resolve<InvoiceRepo>(invoiceRepoKey) + return repo.fetchInvoicesStatusSummary() +} \ No newline at end of file diff --git a/src/feature/invoice/domain/value-object/invoice-status.ts b/src/feature/core/invoice/domain/value-object/invoice-status.ts similarity index 100% rename from src/feature/invoice/domain/value-object/invoice-status.ts rename to src/feature/core/invoice/domain/value-object/invoice-status.ts diff --git a/src/feature/invoice/invoice-module-key.ts b/src/feature/core/invoice/invoice-module-key.ts similarity index 100% rename from src/feature/invoice/invoice-module-key.ts rename to src/feature/core/invoice/invoice-module-key.ts diff --git a/src/feature/customer-invoice/domain/i-repo/customer-invoice-repo.ts b/src/feature/customer-invoice/domain/i-repo/customer-invoice-repo.ts deleted file mode 100644 index f3f5eba..0000000 --- a/src/feature/customer-invoice/domain/i-repo/customer-invoice-repo.ts +++ /dev/null @@ -1,7 +0,0 @@ -import CustomerInvoice from "@/feature/customer-invoice/domain/entity/customer-invoice" - -export default interface CustomerInvoiceRepo { - fetchList(): Promise<CustomerInvoice[]> -} - -export const customerInvoiceRepoKey = "customerInvoiceRepoKey" \ No newline at end of file diff --git a/src/feature/invoice/domain/usecase/fetch-invoices-status-summary.ts b/src/feature/invoice/domain/usecase/fetch-invoices-status-summary.ts deleted file mode 100644 index f35a4dc..0000000 --- a/src/feature/invoice/domain/usecase/fetch-invoices-status-summary.ts +++ /dev/null @@ -1,9 +0,0 @@ -import serverDi from "@/feature/common/server-di"; -import InvoiceRepo, { invoiceRepoKey } from "@/feature/invoice/domain/i-repo/invoice-repo"; -import InvoiceStatusSummary from "@/feature/invoice/domain/value-object/invoice-status"; -import { invoiceModuleKey } from "@/feature/invoice/invoice-module-key"; - -export default function fetchInvoicesStatusSummary(): Promise<InvoiceStatusSummary> { - const repo = serverDi(invoiceModuleKey).resolve<InvoiceRepo>(invoiceRepoKey) - return repo.fetchInvoicesStatusSummary() -} \ No newline at end of file diff --git a/src/test/common/fake-factory/customer/customer-fake-factory.ts b/src/test/common/fake-factory/customer/customer-fake-factory.ts index cf7a53c..319c223 100644 --- a/src/test/common/fake-factory/customer/customer-fake-factory.ts +++ b/src/test/common/fake-factory/customer/customer-fake-factory.ts @@ -1,4 +1,4 @@ -import Customer from "@/feature/customer/domain/entity/customer"; +import Customer from "@/feature/core/customer/domain/entity/customer"; import { faker } from "@faker-js/faker"; export default class CustomerFakeFactory { diff --git a/src/test/unit/feature/customer/domain/usecase/fetch-customers-usecase.test.ts b/src/test/unit/feature/customer/domain/usecase/fetch-customers-usecase.test.ts index 7178ac2..9ce5ccd 100644 --- a/src/test/unit/feature/customer/domain/usecase/fetch-customers-usecase.test.ts +++ b/src/test/unit/feature/customer/domain/usecase/fetch-customers-usecase.test.ts @@ -1,9 +1,9 @@ -import CustomerRepo, { customerRepoKey } from "@/feature/customer/domain/i-repo/customer-repo"; +import CustomerRepo, { customerRepoKey } from "@/feature/core/customer/domain/i-repo/customer-repo"; import { getMock } from "@/test/common/mock/mock-factory"; import { describe } from "vitest"; import { faker } from "@faker-js/faker"; import CustomerFakeFactory from "@/test/common/fake-factory/customer/customer-fake-factory"; -import fetchCustomersUsecase from "@/feature/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"; /* -------------------------------------------------------------------------- */ /* Faking */ -- 2.39.5 From e592fef4ad99078757ba669ac9489656b2891e22 Mon Sep 17 00:00:00 2001 From: behnam <behnamrahimpour74@gmail.com> Date: Fri, 1 Nov 2024 16:33:19 +0300 Subject: [PATCH 13/37] Add module for fetch summary info --- src/feature/common/server-di.ts | 3 ++ .../data/module/summary-info-di.ts | 20 +++++++++++ .../domain/summary-info-module-key.ts | 1 + .../usecase/fetch-summary-info-usecase.ts | 34 +++++++++++++++++++ .../domain/value-object/summary-info.ts | 17 ++++++++++ 5 files changed, 75 insertions(+) create mode 100644 src/feature/core/summary-info/data/module/summary-info-di.ts create mode 100644 src/feature/core/summary-info/domain/summary-info-module-key.ts create mode 100644 src/feature/core/summary-info/domain/usecase/fetch-summary-info-usecase.ts create mode 100644 src/feature/core/summary-info/domain/value-object/summary-info.ts diff --git a/src/feature/common/server-di.ts b/src/feature/common/server-di.ts index af68905..b1653f9 100644 --- a/src/feature/common/server-di.ts +++ b/src/feature/common/server-di.ts @@ -7,6 +7,8 @@ import getTestModule from "@/feature/infra/test/module/test-module"; import getInvoiceDi from "@/feature/core/invoice/data/module/invoice-di"; import { invoiceModuleKey } from "@/feature/core/invoice/invoice-module-key"; import { DependencyContainer } from "tsyringe"; +import { summaryInfoModuleKey } from "@/feature/core/summary-info/domain/summary-info-module-key"; +import getSummaryInfoDi from "@/feature/core/summary-info/data/module/summary-info-di"; export default function serverDi(module: string): DependencyContainer { const getDi = { @@ -14,6 +16,7 @@ export default function serverDi(module: string): DependencyContainer { [customerKey]: getCustomerDi, [customerInvoiceModuleKey]: getCustomerInvoiceDi, [invoiceModuleKey]: getInvoiceDi, + [summaryInfoModuleKey]: getSummaryInfoDi, }[module] if (!getDi) throw new Error("Server Di didn't found for module: " + module) diff --git a/src/feature/core/summary-info/data/module/summary-info-di.ts b/src/feature/core/summary-info/data/module/summary-info-di.ts new file mode 100644 index 0000000..cd181eb --- /dev/null +++ b/src/feature/core/summary-info/data/module/summary-info-di.ts @@ -0,0 +1,20 @@ +import di from "@/bootstrap/di/init-di" +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 fetchInvoicesStatusSummary from "@/feature/core/invoice/domain/usecase/fetch-invoices-status-summary" +import fetchSummaryInfoUsecase from "@/feature/core/summary-info/domain/usecase/fetch-summary-info-usecase" + +export default function getSummaryInfoDi() { + const summaryInfoDi = di.createChildContainer() + + summaryInfoDi.register(fetchAllInvoicesAmountUsecase.name, { + useValue: fetchAllInvoicesAmountUsecase + }) + summaryInfoDi.register(fetchCustomersAmountUsecase.name, { + useValue: fetchCustomersAmountUsecase + }) + summaryInfoDi.register(fetchInvoicesStatusSummary.name, { + useValue: fetchSummaryInfoUsecase + }) + return summaryInfoDi +} \ No newline at end of file diff --git a/src/feature/core/summary-info/domain/summary-info-module-key.ts b/src/feature/core/summary-info/domain/summary-info-module-key.ts new file mode 100644 index 0000000..a2e027b --- /dev/null +++ b/src/feature/core/summary-info/domain/summary-info-module-key.ts @@ -0,0 +1 @@ +export const summaryInfoModuleKey = "summaryInfoModuleKey" \ No newline at end of file diff --git a/src/feature/core/summary-info/domain/usecase/fetch-summary-info-usecase.ts b/src/feature/core/summary-info/domain/usecase/fetch-summary-info-usecase.ts new file mode 100644 index 0000000..e0a6305 --- /dev/null +++ b/src/feature/core/summary-info/domain/usecase/fetch-summary-info-usecase.ts @@ -0,0 +1,34 @@ +import serverDi from "@/feature/common/server-di"; +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 fetchInvoicesStatusSummary from "@/feature/core/invoice/domain/usecase/fetch-invoices-status-summary"; +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 { connection } from "next/server"; + +export default async function fetchSummaryInfoUsecase(): Promise<SummaryInfo> { + connection() + + try{ + const summaryInfoDi = serverDi(summaryInfoModuleKey) + const invoicesAmountPromise = summaryInfoDi.resolve<typeof fetchAllInvoicesAmountUsecase>(fetchAllInvoicesAmountUsecase.name)() + const customersAmountPromise = summaryInfoDi.resolve<typeof fetchCustomersAmountUsecase>(fetchCustomersAmountUsecase.name)() + const invoiceSummaryPomise = summaryInfoDi.resolve<typeof fetchInvoicesStatusSummary>(fetchInvoicesStatusSummary.name)() + + const [invoicesAmount, customersAmount, invoicesSummary] = await Promise.all([ + invoicesAmountPromise, + customersAmountPromise, + invoiceSummaryPomise, + ]); + + + return new SummaryInfo({ + invoicesNumber: invoicesAmount, + customersNumber: customersAmount, + invoicesSummary: invoicesSummary + }) + } catch (error) { + console.error('Database Error:', error); + throw new Error('Failed to fetch card data.'); + } +} \ No newline at end of file diff --git a/src/feature/core/summary-info/domain/value-object/summary-info.ts b/src/feature/core/summary-info/domain/value-object/summary-info.ts new file mode 100644 index 0000000..9c30901 --- /dev/null +++ b/src/feature/core/summary-info/domain/value-object/summary-info.ts @@ -0,0 +1,17 @@ +import InvoiceStatusSummary from "@/feature/core/invoice/domain/value-object/invoice-status"; + +export default class SummaryInfo { + customersNumber: number; + invoicesNumber: number; + invoicesSummary: InvoiceStatusSummary + + constructor({ + customersNumber, + invoicesNumber, + invoicesSummary + }: SummaryInfo) { + this.customersNumber = customersNumber + this.invoicesNumber = invoicesNumber + this.invoicesSummary = invoicesSummary + } +} \ No newline at end of file -- 2.39.5 From 8b79d9aa4b014341d5fe0755f024a8082eac870a Mon Sep 17 00:00:00 2001 From: behnam <behnamrahimpour74@gmail.com> Date: Fri, 1 Nov 2024 16:57:12 +0300 Subject: [PATCH 14/37] Add fetch revenues module --- src/app/lib/data.ts | 73 ------------------- src/app/lib/definitions.ts | 26 ------- src/app/lib/utils.ts | 49 +------------ src/feature/common/server-di.ts | 3 + .../core/revenue/data/module/revenue-di.ts | 10 +++ .../core/revenue/data/repo/revenue-db-repo.ts | 43 +++++++++++ .../core/revenue/domain/entity/revenue.ts | 14 ++++ .../revenue/domain/i-repo/revenue-repo.ts | 7 ++ .../core/revenue/domain/revenue-module-key.ts | 1 + .../domain/usecase/fetch-revenues-usecase.ts | 9 +++ 10 files changed, 88 insertions(+), 147 deletions(-) delete mode 100644 src/app/lib/data.ts delete mode 100644 src/app/lib/definitions.ts create mode 100644 src/feature/core/revenue/data/module/revenue-di.ts create mode 100644 src/feature/core/revenue/data/repo/revenue-db-repo.ts create mode 100644 src/feature/core/revenue/domain/entity/revenue.ts create mode 100644 src/feature/core/revenue/domain/i-repo/revenue-repo.ts create mode 100644 src/feature/core/revenue/domain/revenue-module-key.ts create mode 100644 src/feature/core/revenue/domain/usecase/fetch-revenues-usecase.ts diff --git a/src/app/lib/data.ts b/src/app/lib/data.ts deleted file mode 100644 index 6326383..0000000 --- a/src/app/lib/data.ts +++ /dev/null @@ -1,73 +0,0 @@ -import { sql } from '@/bootstrap/db/db'; -import { - Revenue, - Invoice, - Customer, -} from './definitions'; -import { formatCurrency } from './utils'; -import postgres from 'postgres'; -import { connection } from 'next/server'; - -export async function fetchRevenue() { - // This is equivalent to in fetch(..., {cache: 'no-store'}). - connection() - - try { - // Artificially delay a response for demo purposes. - // Don't do this in production :) - - console.log('Fetching revenue data...'); - await new Promise((resolve) => setTimeout(resolve, 3000)); - - const data = await sql`SELECT * FROM revenue`; - - console.log('Data fetch completed after 3 seconds.'); - - return data as postgres.RowList<Revenue[]>; - } catch (error) { - console.error('Database Error:', error); - throw new Error('Failed to fetch revenue data.'); - } -} - -export async function fetchCardData() { - // This is equivalent to in fetch(..., {cache: 'no-store'}). - connection() - - try { - // You can probably combine these into a single SQL query - // However, we are intentionally splitting them to demonstrate - // how to initialize multiple queries in parallel with JS. - const invoiceCountPromise = sql`SELECT COUNT(*) FROM invoices`; - const customerCountPromise = sql`SELECT COUNT(*) FROM customers`; - const invoiceStatusPromise = sql`SELECT - id, - SUM(CASE WHEN status = 'paid' THEN amount ELSE 0 END) AS "paid", - SUM(CASE WHEN status = 'pending' THEN amount ELSE 0 END) AS "pending" - FROM invoices`; - - const data = await Promise.all([ - invoiceCountPromise, - customerCountPromise, - invoiceStatusPromise, - ]); - - const invoices = data[0] as postgres.RowList<Invoice[]> - const customres = data[1] as postgres.RowList<Customer[]> - const invoiceStatus = data[2] as postgres.RowList<({id: string; paid: string, pending: string})[]> - const numberOfInvoices = Number(invoices.count ?? '0'); - const numberOfCustomers = Number(customres.count ?? '0'); - const totalPaidInvoices = formatCurrency(Number(invoiceStatus.at(0)?.paid ?? '0')); - const totalPendingInvoices = formatCurrency(Number(invoiceStatus.at(0)?.pending ?? '0')); - - return { - numberOfCustomers, - numberOfInvoices, - totalPaidInvoices, - totalPendingInvoices, - }; - } catch (error) { - console.error('Database Error:', error); - throw new Error('Failed to fetch card data.'); - } -} diff --git a/src/app/lib/definitions.ts b/src/app/lib/definitions.ts deleted file mode 100644 index b26dd32..0000000 --- a/src/app/lib/definitions.ts +++ /dev/null @@ -1,26 +0,0 @@ -export type Customer = { - id: string; - name: string; - email: string; - image_url: string; -}; - -export type Invoice = { - id: string; // Will be created on the database - customer_id: string; - amount: number; // Stored in cents - status: 'pending' | 'paid'; - date: string; -}; - -export type Revenue = { - month: string; - revenue: number; -}; - -export type InvoiceForm = { - id: string; - customer_id: string; - amount: number; - status: 'pending' | 'paid'; -}; diff --git a/src/app/lib/utils.ts b/src/app/lib/utils.ts index b7f7cff..c3184af 100644 --- a/src/app/lib/utils.ts +++ b/src/app/lib/utils.ts @@ -1,4 +1,4 @@ -import { Revenue } from './definitions'; +import Revenue from "@/feature/core/revenue/domain/entity/revenue"; export const formatCurrency = (amount: number) => { return (amount / 100).toLocaleString('en-US', { @@ -7,20 +7,6 @@ export const formatCurrency = (amount: number) => { }); }; -export const formatDateToLocal = ( - dateStr: string, - locale: string = 'en-US', -) => { - const date = new Date(dateStr); - const options: Intl.DateTimeFormatOptions = { - day: 'numeric', - month: 'short', - year: 'numeric', - }; - const formatter = new Intl.DateTimeFormat(locale, options); - return formatter.format(date); -}; - export const generateYAxis = (revenue: Revenue[]) => { // Calculate what labels we need to display on the y-axis // based on highest record and in 1000s @@ -34,36 +20,3 @@ export const generateYAxis = (revenue: Revenue[]) => { return { yAxisLabels, topLabel }; }; - -export const generatePagination = (currentPage: number, totalPages: number) => { - // If the total number of pages is 7 or less, - // display all pages without any ellipsis. - if (totalPages <= 7) { - return Array.from({ length: totalPages }, (_, i) => i + 1); - } - - // If the current page is among the first 3 pages, - // show the first 3, an ellipsis, and the last 2 pages. - if (currentPage <= 3) { - return [1, 2, 3, '...', totalPages - 1, totalPages]; - } - - // If the current page is among the last 3 pages, - // show the first 2, an ellipsis, and the last 3 pages. - if (currentPage >= totalPages - 2) { - return [1, 2, '...', totalPages - 2, totalPages - 1, totalPages]; - } - - // If the current page is somewhere in the middle, - // show the first page, an ellipsis, the current page and its neighbors, - // another ellipsis, and the last page. - return [ - 1, - '...', - currentPage - 1, - currentPage, - currentPage + 1, - '...', - totalPages, - ]; -}; diff --git a/src/feature/common/server-di.ts b/src/feature/common/server-di.ts index b1653f9..7ce0735 100644 --- a/src/feature/common/server-di.ts +++ b/src/feature/common/server-di.ts @@ -9,6 +9,8 @@ import { invoiceModuleKey } from "@/feature/core/invoice/invoice-module-key"; import { DependencyContainer } from "tsyringe"; 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 { revenueModuleKey } from "@/feature/core/revenue/domain/revenue-module-key"; +import getRevenueDi from "@/feature/core/revenue/data/module/revenue-di"; export default function serverDi(module: string): DependencyContainer { const getDi = { @@ -17,6 +19,7 @@ export default function serverDi(module: string): DependencyContainer { [customerInvoiceModuleKey]: getCustomerInvoiceDi, [invoiceModuleKey]: getInvoiceDi, [summaryInfoModuleKey]: getSummaryInfoDi, + [revenueModuleKey]: getRevenueDi, }[module] if (!getDi) throw new Error("Server Di didn't found for module: " + module) diff --git a/src/feature/core/revenue/data/module/revenue-di.ts b/src/feature/core/revenue/data/module/revenue-di.ts new file mode 100644 index 0000000..921a2ed --- /dev/null +++ b/src/feature/core/revenue/data/module/revenue-di.ts @@ -0,0 +1,10 @@ +import di from "@/bootstrap/di/init-di" +import RevenueDbRepo from "@/feature/core/revenue/data/repo/revenue-db-repo" +import { revenueRepoKey } from "@/feature/core/revenue/domain/i-repo/revenue-repo" + +export default function getRevenueDi() { + const revenueDi = di.createChildContainer() + + revenueDi.register(revenueRepoKey, RevenueDbRepo) + return revenueDi +} \ No newline at end of file diff --git a/src/feature/core/revenue/data/repo/revenue-db-repo.ts b/src/feature/core/revenue/data/repo/revenue-db-repo.ts new file mode 100644 index 0000000..b29c5d2 --- /dev/null +++ b/src/feature/core/revenue/data/repo/revenue-db-repo.ts @@ -0,0 +1,43 @@ +import { sql } from "@/bootstrap/db/db"; +import Revenue from "@/feature/core/revenue/domain/entity/revenue"; +import RevenueRepo from "@/feature/core/revenue/domain/i-repo/revenue-repo"; +import { connection } from "next/server"; +import postgres from "postgres"; + +export type RevenueDbResponse = { + month: string; + revenue: number; +}; +export default class RevenueDbRepo implements RevenueRepo { + async fetchRevenues(): Promise<Revenue[]> { + // This is equivalent to in fetch(..., {cache: 'no-store'}). + connection() + try { + // Artificially delay a response for demo purposes. + // Don't do this in production :) + await new Promise((resolve) => setTimeout(resolve, 3000)); + + const data = await sql`SELECT * FROM revenue` as postgres.RowList<RevenueDbResponse[]>; + + console.log('Data fetch completed after 3 seconds.'); + + return this.revenuesDto(data); + } catch (error) { + console.error('Database Error:', error); + throw new Error('Failed to fetch revenue data.'); + } + } + + + private revenuesDto(dbResponse: RevenueDbResponse[]): Revenue[] { + return dbResponse.map((dbRevenue) => this.revenueDto(dbRevenue)) + } + + private revenueDto(dbResponse: RevenueDbResponse): Revenue { + return new Revenue({ + month: dbResponse.month, + revenue: dbResponse.revenue + }) + } + +} \ No newline at end of file diff --git a/src/feature/core/revenue/domain/entity/revenue.ts b/src/feature/core/revenue/domain/entity/revenue.ts new file mode 100644 index 0000000..290ca32 --- /dev/null +++ b/src/feature/core/revenue/domain/entity/revenue.ts @@ -0,0 +1,14 @@ +export default class Revenue { + month: string; + revenue: number; + + constructor( + { + month, + revenue + }: Revenue + ) { + this.month = month + this.revenue = revenue + } +} \ No newline at end of file diff --git a/src/feature/core/revenue/domain/i-repo/revenue-repo.ts b/src/feature/core/revenue/domain/i-repo/revenue-repo.ts new file mode 100644 index 0000000..be6924b --- /dev/null +++ b/src/feature/core/revenue/domain/i-repo/revenue-repo.ts @@ -0,0 +1,7 @@ +import Revenue from "@/feature/core/revenue/domain/entity/revenue"; + +export default interface RevenueRepo { + fetchRevenues(): Promise<Revenue[]> +} + +export const revenueRepoKey = "revenueRepoKey" \ No newline at end of file diff --git a/src/feature/core/revenue/domain/revenue-module-key.ts b/src/feature/core/revenue/domain/revenue-module-key.ts new file mode 100644 index 0000000..27150fb --- /dev/null +++ b/src/feature/core/revenue/domain/revenue-module-key.ts @@ -0,0 +1 @@ +export const revenueModuleKey = "RevenueModuleKey" \ No newline at end of file diff --git a/src/feature/core/revenue/domain/usecase/fetch-revenues-usecase.ts b/src/feature/core/revenue/domain/usecase/fetch-revenues-usecase.ts new file mode 100644 index 0000000..c9e6068 --- /dev/null +++ b/src/feature/core/revenue/domain/usecase/fetch-revenues-usecase.ts @@ -0,0 +1,9 @@ +import serverDi from "@/feature/common/server-di"; +import Revenue from "@/feature/core/revenue/domain/entity/revenue"; +import RevenueRepo from "@/feature/core/revenue/domain/i-repo/revenue-repo"; +import { revenueModuleKey } from "@/feature/core/revenue/domain/revenue-module-key"; + +export default function fetchRevenuesUsecase(): Promise<Revenue[]> { + const repo = serverDi(revenueModuleKey).resolve<RevenueRepo>(revenueModuleKey) + return repo.fetchRevenues() +} \ No newline at end of file -- 2.39.5 From 43a622851da498af2c202f70449156a1101fc9f1 Mon Sep 17 00:00:00 2001 From: behnam <behnamrahimpour74@gmail.com> Date: Fri, 1 Nov 2024 17:50:43 +0300 Subject: [PATCH 15/37] Update RFCs to use feature layer architecture --- .gitignore | 2 +- src/app/dashboard/components/cards.tsx | 17 +++++------- .../dashboard/components/latest-invoices.tsx | 14 +++++----- .../dashboard/components/revenue-chart.tsx | 4 +-- .../dashboard/module/dashboard-app-module.ts | 27 +++++++++++++++++++ src/feature/common/server-di.ts | 9 +++++-- .../data/module/customer-invoice-di.ts | 9 ++----- .../data/repo/customer-invoice-db-repo.ts | 6 +---- .../fetch-customer-invoices-usecase.ts | 5 ++-- .../core/customer/data/module/customer-di.ts | 5 ---- .../usecase/fetch-customers-amount-usecase.ts | 2 +- .../domain/usecase/fetch-customers-usecase.ts | 2 +- .../fetch-all-invoices-amount-usecase.ts | 2 +- .../usecase/fetch-invoices-status-summary.ts | 2 +- .../core/revenue/data/repo/revenue-db-repo.ts | 1 - .../domain/usecase/fetch-revenues-usecase.ts | 6 ++--- .../data/module/summary-info-di.ts | 3 +-- 17 files changed, 64 insertions(+), 52 deletions(-) create mode 100644 src/app/dashboard/module/dashboard-app-module.ts diff --git a/.gitignore b/.gitignore index 26b002a..39c19d2 100644 --- a/.gitignore +++ b/.gitignore @@ -9,7 +9,7 @@ !.yarn/plugins !.yarn/releases !.yarn/versions - +.vscode # testing /coverage diff --git a/src/app/dashboard/components/cards.tsx b/src/app/dashboard/components/cards.tsx index 72bb37b..5060f9f 100644 --- a/src/app/dashboard/components/cards.tsx +++ b/src/app/dashboard/components/cards.tsx @@ -1,10 +1,10 @@ +import fetchSummaryInfoUsecase from '@/feature/core/summary-info/domain/usecase/fetch-summary-info-usecase'; import { BanknotesIcon, ClockIcon, UserGroupIcon, InboxIcon, } from '@heroicons/react/24/outline'; -import { fetchCardData } from '@/app/lib/data'; const iconMap = { collected: BanknotesIcon, @@ -14,21 +14,16 @@ const iconMap = { }; export default async function CardWrapper() { - const { - numberOfInvoices, - numberOfCustomers, - totalPaidInvoices, - totalPendingInvoices, - } = await fetchCardData(); + const {customersNumber, invoicesNumber, invoicesSummary } = await fetchSummaryInfoUsecase(); return ( <> - <Card title="Collected" value={totalPaidInvoices} type="collected" /> - <Card title="Pending" value={totalPendingInvoices} type="pending" /> - <Card title="Total Invoices" value={numberOfInvoices} type="invoices" /> + <Card title="Collected" value={invoicesSummary.paid} type="collected" /> + <Card title="Pending" value={invoicesSummary.pending} type="pending" /> + <Card title="Total Invoices" value={invoicesNumber} type="invoices" /> <Card title="Total Customers" - value={numberOfCustomers} + value={customersNumber} type="customers" /> </> diff --git a/src/app/dashboard/components/latest-invoices.tsx b/src/app/dashboard/components/latest-invoices.tsx index 5c7cd95..6f62655 100644 --- a/src/app/dashboard/components/latest-invoices.tsx +++ b/src/app/dashboard/components/latest-invoices.tsx @@ -1,9 +1,9 @@ +import fetchCustomerInvoicesUsecase from '@/feature/core/customer-invoice/domain/usecase/fetch-customer-invoices-usecase'; import { ArrowPathIcon } from '@heroicons/react/24/outline'; import clsx from 'clsx'; import Image from 'next/image'; -import { fetchLatestInvoices } from '@/app/lib/data'; export default async function LatestInvoices() { - const latestInvoices = await fetchLatestInvoices(); + const latestInvoices = await fetchCustomerInvoicesUsecase(); return ( <div className="flex w-full flex-col md:col-span-4"> @@ -26,25 +26,25 @@ export default async function LatestInvoices() { > <div className="flex items-center"> <Image - src={invoice.image_url} - alt={`${invoice.name}'s profile picture`} + src={invoice.customerImageUrl} + alt={`${invoice.customerName}'s profile picture`} className="mr-4 rounded-full" width={32} height={32} /> <div className="min-w-0"> <p className="truncate text-sm font-semibold md:text-base"> - {invoice.name} + {invoice.customerName} </p> <p className="hidden text-sm text-gray-500 sm:block"> - {invoice.email} + {invoice.customerEmail} </p> </div> </div> <p className="truncate text-sm font-medium md:text-base" > - {invoice.amount} + {invoice.invoicesAmount} </p> </div> ); diff --git a/src/app/dashboard/components/revenue-chart.tsx b/src/app/dashboard/components/revenue-chart.tsx index 49d888c..f6a6f91 100644 --- a/src/app/dashboard/components/revenue-chart.tsx +++ b/src/app/dashboard/components/revenue-chart.tsx @@ -1,9 +1,9 @@ import { generateYAxis } from '@/app/lib/utils'; +import fetchRevenuesUsecase from '@/feature/core/revenue/domain/usecase/fetch-revenues-usecase'; import { CalendarIcon } from '@heroicons/react/24/outline'; -import { fetchRevenue } from '@/app/lib/data'; export default async function RevenueChart() { - const revenue = await fetchRevenue(); + const revenue = await fetchRevenuesUsecase(); const chartHeight = 350; diff --git a/src/app/dashboard/module/dashboard-app-module.ts b/src/app/dashboard/module/dashboard-app-module.ts new file mode 100644 index 0000000..fd9f144 --- /dev/null +++ b/src/app/dashboard/module/dashboard-app-module.ts @@ -0,0 +1,27 @@ +import di from "@/bootstrap/di/init-di" +import fetchCustomerInvoicesUsecase from "@/feature/core/customer-invoice/domain/usecase/fetch-customer-invoices-usecase"; +import fetchCustomersUsecase from "@/feature/core/customer/domain/usecase/fetch-customers-usecase"; +import fetchAllInvoicesAmountUsecase from "@/feature/core/invoice/domain/usecase/fetch-all-invoices-amount-usecase"; +import fetchRevenuesUsecase from "@/feature/core/revenue/domain/usecase/fetch-revenues-usecase"; + +export default function dashboardAppModule() { + const dashboardDi = di.createChildContainer() + + dashboardDi.register(fetchCustomersUsecase.name, { + useValue: fetchCustomersUsecase + }) + + dashboardDi.register(fetchAllInvoicesAmountUsecase.name, { + useValue: fetchAllInvoicesAmountUsecase + }) + dashboardDi.register(fetchAllInvoicesAmountUsecase.name, { + useValue: fetchAllInvoicesAmountUsecase + }) + dashboardDi.register(fetchCustomerInvoicesUsecase.name, { + useValue: fetchCustomerInvoicesUsecase + }) + dashboardDi.register(fetchRevenuesUsecase.name, { + useValue: fetchRevenuesUsecase + }) + return dashboardDi +} diff --git a/src/feature/common/server-di.ts b/src/feature/common/server-di.ts index 7ce0735..401e706 100644 --- a/src/feature/common/server-di.ts +++ b/src/feature/common/server-di.ts @@ -12,7 +12,10 @@ import getSummaryInfoDi from "@/feature/core/summary-info/data/module/summary-in import { revenueModuleKey } from "@/feature/core/revenue/domain/revenue-module-key"; import getRevenueDi from "@/feature/core/revenue/data/module/revenue-di"; +const memoizedDis: Record<string, DependencyContainer> = {} + export default function serverDi(module: string): DependencyContainer { + if (memoizedDis[module]) return memoizedDis[module] const getDi = { [testModuleKey]: getTestModule, [customerKey]: getCustomerDi, @@ -23,6 +26,8 @@ export default function serverDi(module: string): DependencyContainer { }[module] if (!getDi) throw new Error("Server Di didn't found for module: " + module) - - return getDi() + + const di = getDi() + memoizedDis[module] = di + return di } \ No newline at end of file diff --git a/src/feature/core/customer-invoice/data/module/customer-invoice-di.ts b/src/feature/core/customer-invoice/data/module/customer-invoice-di.ts index 76a7453..5364a92 100644 --- a/src/feature/core/customer-invoice/data/module/customer-invoice-di.ts +++ b/src/feature/core/customer-invoice/data/module/customer-invoice-di.ts @@ -1,16 +1,11 @@ import di from "@/bootstrap/di/init-di"; +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 fetchCustomerInvoicesUsecase from "@/feature/core/customer-invoice/domain/usecase/fetch-customer-invoices-usecase"; -import CustomerDbRepo from "@/feature/core/customer/data/repo/customer-db-repo"; import { DependencyContainer } from "tsyringe"; export default function getCustomerInvoiceDi(): DependencyContainer { const customerInvoiceDi = di.createChildContainer() - customerInvoiceDi.register(fetchCustomerInvoicesUsecase.name, { - useValue: fetchCustomerInvoicesUsecase - }) - - customerInvoiceDi.register(customerInvoiceRepoKey, CustomerDbRepo) + customerInvoiceDi.register(customerInvoiceRepoKey, CustomerInvoiceDbRepo) return customerInvoiceDi } \ No newline at end of file diff --git a/src/feature/core/customer-invoice/data/repo/customer-invoice-db-repo.ts b/src/feature/core/customer-invoice/data/repo/customer-invoice-db-repo.ts index 45ec6ab..18f7db1 100644 --- a/src/feature/core/customer-invoice/data/repo/customer-invoice-db-repo.ts +++ b/src/feature/core/customer-invoice/data/repo/customer-invoice-db-repo.ts @@ -2,7 +2,6 @@ import { formatCurrency } from "@/app/lib/utils"; import { sql } from "@/bootstrap/db/db"; import CustomerInvoice from "@/feature/core/customer-invoice/domain/entity/customer-invoice"; import CustomerInvoiceRepo from "@/feature/core/customer-invoice/domain/i-repo/customer-invoice-repo"; -import { connection } from "next/server"; import postgres from "postgres"; type customerInvoiceDbResponse = { @@ -13,11 +12,8 @@ type customerInvoiceDbResponse = { amount: string; } -export default class CustomerDbRepo implements CustomerInvoiceRepo { +export default class CustomerInvoiceDbRepo implements CustomerInvoiceRepo { async fetchList(): Promise<CustomerInvoice[]> { - // This is equivalent to in fetch(..., {cache: 'no-store'}). - connection() - try { const data = await sql` SELECT invoices.amount, customers.name, customers.image_url, customers.email, invoices.id diff --git a/src/feature/core/customer-invoice/domain/usecase/fetch-customer-invoices-usecase.ts b/src/feature/core/customer-invoice/domain/usecase/fetch-customer-invoices-usecase.ts index fd97f46..5947553 100644 --- a/src/feature/core/customer-invoice/domain/usecase/fetch-customer-invoices-usecase.ts +++ b/src/feature/core/customer-invoice/domain/usecase/fetch-customer-invoices-usecase.ts @@ -3,9 +3,10 @@ import serverDi from "@/feature/common/server-di"; import CustomerInvoice from "@/feature/core/customer-invoice/domain/entity/customer-invoice"; import CustomerInvoiceRepo, { customerInvoiceRepoKey } from "@/feature/core/customer-invoice/domain/i-repo/customer-invoice-repo"; import { customerInvoiceModuleKey } from "@/feature/core/customer-invoice/invoice-module-key"; +import { connection } from "next/server"; -export default function fetchCustomerInvoicesUsecase(): Promise<CustomerInvoice[]> { +export default async function fetchCustomerInvoicesUsecase(): Promise<CustomerInvoice[]> { + connection() const repo = serverDi(customerInvoiceModuleKey).resolve<CustomerInvoiceRepo>(customerInvoiceRepoKey) - return repo.fetchList() } \ No newline at end of file diff --git a/src/feature/core/customer/data/module/customer-di.ts b/src/feature/core/customer/data/module/customer-di.ts index 1fa4398..c3806ee 100644 --- a/src/feature/core/customer/data/module/customer-di.ts +++ b/src/feature/core/customer/data/module/customer-di.ts @@ -1,16 +1,11 @@ import di from "@/bootstrap/di/init-di"; import CustomerDbRepo from "@/feature/core/customer/data/repo/customer-db-repo"; import { customerRepoKey } from "@/feature/core/customer/domain/i-repo/customer-repo"; -import fetchCustomersUsecase from "@/feature/core/customer/domain/usecase/fetch-customers-usecase"; import { DependencyContainer } from "tsyringe"; export default function getCustomerDi(): DependencyContainer { const customerDi = di.createChildContainer() - customerDi.register(fetchCustomersUsecase.name, { - useValue: fetchCustomersUsecase - }) - customerDi.register(customerRepoKey, CustomerDbRepo) return customerDi } \ No newline at end of file diff --git a/src/feature/core/customer/domain/usecase/fetch-customers-amount-usecase.ts b/src/feature/core/customer/domain/usecase/fetch-customers-amount-usecase.ts index f90d5c3..71cd13d 100644 --- a/src/feature/core/customer/domain/usecase/fetch-customers-amount-usecase.ts +++ b/src/feature/core/customer/domain/usecase/fetch-customers-amount-usecase.ts @@ -2,7 +2,7 @@ import serverDi from "@/feature/common/server-di"; import { customerKey } from "@/feature/core/customer/customer-key"; import CustomerRepo, { customerRepoKey } from "@/feature/core/customer/domain/i-repo/customer-repo"; -export default function fetchCustomersAmountUsecase(): Promise<number> { +export default async function fetchCustomersAmountUsecase(): Promise<number> { const repo = serverDi(customerKey).resolve<CustomerRepo>(customerRepoKey) return repo.fetchCustomersAmount() } \ No newline at end of file diff --git a/src/feature/core/customer/domain/usecase/fetch-customers-usecase.ts b/src/feature/core/customer/domain/usecase/fetch-customers-usecase.ts index 60bd0c5..d28584d 100644 --- a/src/feature/core/customer/domain/usecase/fetch-customers-usecase.ts +++ b/src/feature/core/customer/domain/usecase/fetch-customers-usecase.ts @@ -5,7 +5,7 @@ import { customerKey } from "@/feature/core/customer/customer-key"; import Customer from "@/feature/core/customer/domain/entity/customer"; import CustomerRepo, { customerRepoKey } from "@/feature/core/customer/domain/i-repo/customer-repo"; -export default function fetchCustomersUsecase(query: string): Promise<Customer[]> { +export default async function fetchCustomersUsecase(query: string): Promise<Customer[]> { const repo = serverDi(customerKey).resolve<CustomerRepo>(customerRepoKey) return repo.fetchList(query) diff --git a/src/feature/core/invoice/domain/usecase/fetch-all-invoices-amount-usecase.ts b/src/feature/core/invoice/domain/usecase/fetch-all-invoices-amount-usecase.ts index 93e2deb..48840f4 100644 --- a/src/feature/core/invoice/domain/usecase/fetch-all-invoices-amount-usecase.ts +++ b/src/feature/core/invoice/domain/usecase/fetch-all-invoices-amount-usecase.ts @@ -3,7 +3,7 @@ import serverDi from "@/feature/common/server-di"; import InvoiceRepo, { invoiceRepoKey } from "@/feature/core/invoice/domain/i-repo/invoice-repo"; import { invoiceModuleKey } from "@/feature/core/invoice/invoice-module-key"; -export default function fetchAllInvoicesAmountUsecase(): Promise<number> { +export default async function fetchAllInvoicesAmountUsecase(): Promise<number> { const repo = serverDi(invoiceModuleKey).resolve<InvoiceRepo>(invoiceRepoKey) return repo.fetchAllInvoicesAmount() diff --git a/src/feature/core/invoice/domain/usecase/fetch-invoices-status-summary.ts b/src/feature/core/invoice/domain/usecase/fetch-invoices-status-summary.ts index 07c76a8..3bb9a5e 100644 --- a/src/feature/core/invoice/domain/usecase/fetch-invoices-status-summary.ts +++ b/src/feature/core/invoice/domain/usecase/fetch-invoices-status-summary.ts @@ -3,7 +3,7 @@ import InvoiceRepo, { invoiceRepoKey } from "@/feature/core/invoice/domain/i-rep import InvoiceStatusSummary from "@/feature/core/invoice/domain/value-object/invoice-status"; import { invoiceModuleKey } from "@/feature/core/invoice/invoice-module-key"; -export default function fetchInvoicesStatusSummary(): Promise<InvoiceStatusSummary> { +export default async function fetchInvoicesStatusSummary(): Promise<InvoiceStatusSummary> { const repo = serverDi(invoiceModuleKey).resolve<InvoiceRepo>(invoiceRepoKey) return repo.fetchInvoicesStatusSummary() } \ No newline at end of file diff --git a/src/feature/core/revenue/data/repo/revenue-db-repo.ts b/src/feature/core/revenue/data/repo/revenue-db-repo.ts index b29c5d2..7adc439 100644 --- a/src/feature/core/revenue/data/repo/revenue-db-repo.ts +++ b/src/feature/core/revenue/data/repo/revenue-db-repo.ts @@ -11,7 +11,6 @@ export type RevenueDbResponse = { export default class RevenueDbRepo implements RevenueRepo { async fetchRevenues(): Promise<Revenue[]> { // This is equivalent to in fetch(..., {cache: 'no-store'}). - connection() try { // Artificially delay a response for demo purposes. // Don't do this in production :) diff --git a/src/feature/core/revenue/domain/usecase/fetch-revenues-usecase.ts b/src/feature/core/revenue/domain/usecase/fetch-revenues-usecase.ts index c9e6068..0f428c5 100644 --- a/src/feature/core/revenue/domain/usecase/fetch-revenues-usecase.ts +++ b/src/feature/core/revenue/domain/usecase/fetch-revenues-usecase.ts @@ -1,9 +1,9 @@ import serverDi from "@/feature/common/server-di"; import Revenue from "@/feature/core/revenue/domain/entity/revenue"; -import RevenueRepo from "@/feature/core/revenue/domain/i-repo/revenue-repo"; +import RevenueRepo, { revenueRepoKey } from "@/feature/core/revenue/domain/i-repo/revenue-repo"; import { revenueModuleKey } from "@/feature/core/revenue/domain/revenue-module-key"; -export default function fetchRevenuesUsecase(): Promise<Revenue[]> { - const repo = serverDi(revenueModuleKey).resolve<RevenueRepo>(revenueModuleKey) +export default async function fetchRevenuesUsecase(): Promise<Revenue[]> { + const repo = serverDi(revenueModuleKey).resolve<RevenueRepo>(revenueRepoKey) return repo.fetchRevenues() } \ No newline at end of file diff --git a/src/feature/core/summary-info/data/module/summary-info-di.ts b/src/feature/core/summary-info/data/module/summary-info-di.ts index cd181eb..9172b3d 100644 --- a/src/feature/core/summary-info/data/module/summary-info-di.ts +++ b/src/feature/core/summary-info/data/module/summary-info-di.ts @@ -2,7 +2,6 @@ import di from "@/bootstrap/di/init-di" 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 fetchInvoicesStatusSummary from "@/feature/core/invoice/domain/usecase/fetch-invoices-status-summary" -import fetchSummaryInfoUsecase from "@/feature/core/summary-info/domain/usecase/fetch-summary-info-usecase" export default function getSummaryInfoDi() { const summaryInfoDi = di.createChildContainer() @@ -14,7 +13,7 @@ export default function getSummaryInfoDi() { useValue: fetchCustomersAmountUsecase }) summaryInfoDi.register(fetchInvoicesStatusSummary.name, { - useValue: fetchSummaryInfoUsecase + useValue: fetchInvoicesStatusSummary }) return summaryInfoDi } \ No newline at end of file -- 2.39.5 From 0cb29f0b5f100c8b896d17095d2755bfe5da5576 Mon Sep 17 00:00:00 2001 From: behnam <behnamrahimpour74@gmail.com> Date: Fri, 1 Nov 2024 18:03:11 +0300 Subject: [PATCH 16/37] Move caching decision to the usecase layer --- src/feature/core/customer/data/repo/customer-db-repo.ts | 2 -- .../core/customer/domain/usecase/fetch-customers-usecase.ts | 2 ++ src/feature/core/revenue/data/repo/revenue-db-repo.ts | 1 - 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/feature/core/customer/data/repo/customer-db-repo.ts b/src/feature/core/customer/data/repo/customer-db-repo.ts index 82c0494..ad6705f 100644 --- a/src/feature/core/customer/data/repo/customer-db-repo.ts +++ b/src/feature/core/customer/data/repo/customer-db-repo.ts @@ -17,8 +17,6 @@ type customerDbResponse = { export default class CustomerDbRepo implements CustomerRepo { async fetchList(query: string): Promise<Customer[]> { - // This is equivalent to in fetch(..., {cache: 'no-store'}). - connection() try { const data = await sql` SELECT diff --git a/src/feature/core/customer/domain/usecase/fetch-customers-usecase.ts b/src/feature/core/customer/domain/usecase/fetch-customers-usecase.ts index d28584d..c83a252 100644 --- a/src/feature/core/customer/domain/usecase/fetch-customers-usecase.ts +++ b/src/feature/core/customer/domain/usecase/fetch-customers-usecase.ts @@ -4,8 +4,10 @@ import serverDi from "@/feature/common/server-di"; import { customerKey } from "@/feature/core/customer/customer-key"; import Customer from "@/feature/core/customer/domain/entity/customer"; import CustomerRepo, { customerRepoKey } from "@/feature/core/customer/domain/i-repo/customer-repo"; +import { connection } from "next/server"; export default async function fetchCustomersUsecase(query: string): Promise<Customer[]> { + connection() const repo = serverDi(customerKey).resolve<CustomerRepo>(customerRepoKey) return repo.fetchList(query) diff --git a/src/feature/core/revenue/data/repo/revenue-db-repo.ts b/src/feature/core/revenue/data/repo/revenue-db-repo.ts index 7adc439..92ac993 100644 --- a/src/feature/core/revenue/data/repo/revenue-db-repo.ts +++ b/src/feature/core/revenue/data/repo/revenue-db-repo.ts @@ -10,7 +10,6 @@ export type RevenueDbResponse = { }; export default class RevenueDbRepo implements RevenueRepo { async fetchRevenues(): Promise<Revenue[]> { - // This is equivalent to in fetch(..., {cache: 'no-store'}). try { // Artificially delay a response for demo purposes. // Don't do this in production :) -- 2.39.5 From d358d4cd035773cfa7227e80c4cf38a01c17750e Mon Sep 17 00:00:00 2001 From: behnam <behnamrahimpour74@gmail.com> Date: Fri, 1 Nov 2024 18:14:29 +0300 Subject: [PATCH 17/37] Update card wrapper to follow controller based architecture --- src/app/dashboard/(overview)/page.tsx | 2 +- .../components/card/card-controller.ts | 19 ++ src/app/dashboard/components/card/card.tsx | 29 +++ src/app/dashboard/components/cards.tsx | 57 ------ .../components/cards/cards-controller.ts | 5 + src/app/dashboard/components/cards/cards.tsx | 20 ++ src/app/lib/placeholder-data.js | 188 ------------------ src/app/lib/utils.ts | 6 - src/bootstrap/helpers/global-helpers.ts | 0 src/feature/common/feature-helpers.ts | 6 + .../data/repo/customer-invoice-db-repo.ts | 2 +- .../customer/data/repo/customer-db-repo.ts | 3 +- .../core/invoice/data/repo/invoice-db-repo.ts | 2 +- 13 files changed, 83 insertions(+), 256 deletions(-) create mode 100644 src/app/dashboard/components/card/card-controller.ts create mode 100644 src/app/dashboard/components/card/card.tsx delete mode 100644 src/app/dashboard/components/cards.tsx create mode 100644 src/app/dashboard/components/cards/cards-controller.ts create mode 100644 src/app/dashboard/components/cards/cards.tsx delete mode 100644 src/app/lib/placeholder-data.js create mode 100644 src/bootstrap/helpers/global-helpers.ts create mode 100644 src/feature/common/feature-helpers.ts diff --git a/src/app/dashboard/(overview)/page.tsx b/src/app/dashboard/(overview)/page.tsx index 6d632b5..463edbb 100644 --- a/src/app/dashboard/(overview)/page.tsx +++ b/src/app/dashboard/(overview)/page.tsx @@ -1,5 +1,5 @@ import { LatestInvoicesSkeleton, RevenueChartSkeleton } from "@/app/components/skeleton/skeletons"; -import CardWrapper from "@/app/dashboard/components/cards"; +import CardWrapper from "@/app/dashboard/components/cards/cards"; import LatestInvoices from "@/app/dashboard/components/latest-invoices"; import RevenueChart from "@/app/dashboard/components/revenue-chart"; import { Suspense } from "react"; diff --git a/src/app/dashboard/components/card/card-controller.ts b/src/app/dashboard/components/card/card-controller.ts new file mode 100644 index 0000000..43c40f7 --- /dev/null +++ b/src/app/dashboard/components/card/card-controller.ts @@ -0,0 +1,19 @@ +import { + BanknotesIcon, + ClockIcon, + UserGroupIcon, + InboxIcon, +} from '@heroicons/react/24/outline'; + +export default function cardController(props: { type: 'invoices' | 'customers' | 'pending' | 'collected'; }) { + const { type } = props + const iconMap = { + collected: BanknotesIcon, + customers: UserGroupIcon, + pending: ClockIcon, + invoices: InboxIcon, + }; + return { + Icon: iconMap[type] + } +} \ No newline at end of file diff --git a/src/app/dashboard/components/card/card.tsx b/src/app/dashboard/components/card/card.tsx new file mode 100644 index 0000000..5494f4f --- /dev/null +++ b/src/app/dashboard/components/card/card.tsx @@ -0,0 +1,29 @@ +import cardController from "@/app/dashboard/components/card/card-controller"; + + + +export function Card({ + title, + value, + type, +}: { + title: string; + value: number | string; + type: 'invoices' | 'customers' | 'pending' | 'collected'; +}) { + const { Icon } = cardController({type}) + + return ( + <div className="rounded-xl bg-gray-50 p-2 shadow-sm"> + <div className="flex p-4"> + {Icon ? <Icon className="h-5 w-5 text-gray-700" /> : null} + <h3 className="ml-2 text-sm font-medium">{title}</h3> + </div> + <p + className="rounded-xl bg-white px-4 py-8 text-center text-2xl" + > + {value} + </p> + </div> + ); +} \ No newline at end of file diff --git a/src/app/dashboard/components/cards.tsx b/src/app/dashboard/components/cards.tsx deleted file mode 100644 index 5060f9f..0000000 --- a/src/app/dashboard/components/cards.tsx +++ /dev/null @@ -1,57 +0,0 @@ -import fetchSummaryInfoUsecase from '@/feature/core/summary-info/domain/usecase/fetch-summary-info-usecase'; -import { - BanknotesIcon, - ClockIcon, - UserGroupIcon, - InboxIcon, -} from '@heroicons/react/24/outline'; - -const iconMap = { - collected: BanknotesIcon, - customers: UserGroupIcon, - pending: ClockIcon, - invoices: InboxIcon, -}; - -export default async function CardWrapper() { - const {customersNumber, invoicesNumber, invoicesSummary } = await fetchSummaryInfoUsecase(); - - return ( - <> - <Card title="Collected" value={invoicesSummary.paid} type="collected" /> - <Card title="Pending" value={invoicesSummary.pending} type="pending" /> - <Card title="Total Invoices" value={invoicesNumber} type="invoices" /> - <Card - title="Total Customers" - value={customersNumber} - type="customers" - /> - </> - ); -} - -export function Card({ - title, - value, - type, -}: { - title: string; - value: number | string; - type: 'invoices' | 'customers' | 'pending' | 'collected'; -}) { - const Icon = iconMap[type]; - - return ( - <div className="rounded-xl bg-gray-50 p-2 shadow-sm"> - <div className="flex p-4"> - {Icon ? <Icon className="h-5 w-5 text-gray-700" /> : null} - <h3 className="ml-2 text-sm font-medium">{title}</h3> - </div> - <p - className="rounded-xl bg-white px-4 py-8 text-center text-2xl" - > - {value} - </p> - </div> - ); -} diff --git a/src/app/dashboard/components/cards/cards-controller.ts b/src/app/dashboard/components/cards/cards-controller.ts new file mode 100644 index 0000000..b8aaf19 --- /dev/null +++ b/src/app/dashboard/components/cards/cards-controller.ts @@ -0,0 +1,5 @@ +import fetchSummaryInfoUsecase from "@/feature/core/summary-info/domain/usecase/fetch-summary-info-usecase"; + +export default function cardsController() { + return fetchSummaryInfoUsecase(); +} \ No newline at end of file diff --git a/src/app/dashboard/components/cards/cards.tsx b/src/app/dashboard/components/cards/cards.tsx new file mode 100644 index 0000000..c39a4fe --- /dev/null +++ b/src/app/dashboard/components/cards/cards.tsx @@ -0,0 +1,20 @@ +import { Card } from '@/app/dashboard/components/card/card'; +import cardsController from '@/app/dashboard/components/cards/cards-controller'; + + +export default async function CardWrapper() { + const {customersNumber, invoicesNumber, invoicesSummary } = await cardsController(); + + return ( + <> + <Card title="Collected" value={invoicesSummary.paid} type="collected" /> + <Card title="Pending" value={invoicesSummary.pending} type="pending" /> + <Card title="Total Invoices" value={invoicesNumber} type="invoices" /> + <Card + title="Total Customers" + value={customersNumber} + type="customers" + /> + </> + ); +} \ No newline at end of file diff --git a/src/app/lib/placeholder-data.js b/src/app/lib/placeholder-data.js deleted file mode 100644 index 15a4156..0000000 --- a/src/app/lib/placeholder-data.js +++ /dev/null @@ -1,188 +0,0 @@ -// This file contains placeholder data that you'll be replacing with real data in the Data Fetching chapter: -// https://nextjs.org/learn/dashboard-app/fetching-data -const users = [ - { - id: '410544b2-4001-4271-9855-fec4b6a6442a', - name: 'User', - email: 'user@nextmail.com', - password: '123456', - }, -]; - -const customers = [ - { - id: '3958dc9e-712f-4377-85e9-fec4b6a6442a', - name: 'Delba de Oliveira', - email: 'delba@oliveira.com', - image_url: '/customers/delba-de-oliveira.png', - }, - { - id: '3958dc9e-742f-4377-85e9-fec4b6a6442a', - name: 'Lee Robinson', - email: 'lee@robinson.com', - image_url: '/customers/lee-robinson.png', - }, - { - id: '3958dc9e-737f-4377-85e9-fec4b6a6442a', - name: 'Hector Simpson', - email: 'hector@simpson.com', - image_url: '/customers/hector-simpson.png', - }, - { - id: '50ca3e18-62cd-11ee-8c99-0242ac120002', - name: 'Steven Tey', - email: 'steven@tey.com', - image_url: '/customers/steven-tey.png', - }, - { - id: '3958dc9e-787f-4377-85e9-fec4b6a6442a', - name: 'Steph Dietz', - email: 'steph@dietz.com', - image_url: '/customers/steph-dietz.png', - }, - { - id: '76d65c26-f784-44a2-ac19-586678f7c2f2', - name: 'Michael Novotny', - email: 'michael@novotny.com', - image_url: '/customers/michael-novotny.png', - }, - { - id: 'd6e15727-9fe1-4961-8c5b-ea44a9bd81aa', - name: 'Evil Rabbit', - email: 'evil@rabbit.com', - image_url: '/customers/evil-rabbit.png', - }, - { - id: '126eed9c-c90c-4ef6-a4a8-fcf7408d3c66', - name: 'Emil Kowalski', - email: 'emil@kowalski.com', - image_url: '/customers/emil-kowalski.png', - }, - { - id: 'CC27C14A-0ACF-4F4A-A6C9-D45682C144B9', - name: 'Amy Burns', - email: 'amy@burns.com', - image_url: '/customers/amy-burns.png', - }, - { - id: '13D07535-C59E-4157-A011-F8D2EF4E0CBB', - name: 'Balazs Orban', - email: 'balazs@orban.com', - image_url: '/customers/balazs-orban.png', - }, -]; - -const invoices = [ - { - customer_id: customers[0].id, - amount: 15795, - status: 'pending', - date: '2022-12-06', - }, - { - customer_id: customers[1].id, - amount: 20348, - status: 'pending', - date: '2022-11-14', - }, - { - customer_id: customers[4].id, - amount: 3040, - status: 'paid', - date: '2022-10-29', - }, - { - customer_id: customers[3].id, - amount: 44800, - status: 'paid', - date: '2023-09-10', - }, - { - customer_id: customers[5].id, - amount: 34577, - status: 'pending', - date: '2023-08-05', - }, - { - customer_id: customers[7].id, - amount: 54246, - status: 'pending', - date: '2023-07-16', - }, - { - customer_id: customers[6].id, - amount: 666, - status: 'pending', - date: '2023-06-27', - }, - { - customer_id: customers[3].id, - amount: 32545, - status: 'paid', - date: '2023-06-09', - }, - { - customer_id: customers[4].id, - amount: 1250, - status: 'paid', - date: '2023-06-17', - }, - { - customer_id: customers[5].id, - amount: 8546, - status: 'paid', - date: '2023-06-07', - }, - { - customer_id: customers[1].id, - amount: 500, - status: 'paid', - date: '2023-08-19', - }, - { - customer_id: customers[5].id, - amount: 8945, - status: 'paid', - date: '2023-06-03', - }, - { - customer_id: customers[2].id, - amount: 8945, - status: 'paid', - date: '2023-06-18', - }, - { - customer_id: customers[0].id, - amount: 8945, - status: 'paid', - date: '2023-10-04', - }, - { - customer_id: customers[2].id, - amount: 1000, - status: 'paid', - date: '2022-06-05', - }, -]; - -const revenue = [ - { month: 'Jan', revenue: 2000 }, - { month: 'Feb', revenue: 1800 }, - { month: 'Mar', revenue: 2200 }, - { month: 'Apr', revenue: 2500 }, - { month: 'May', revenue: 2300 }, - { month: 'Jun', revenue: 3200 }, - { month: 'Jul', revenue: 3500 }, - { month: 'Aug', revenue: 3700 }, - { month: 'Sep', revenue: 2500 }, - { month: 'Oct', revenue: 2800 }, - { month: 'Nov', revenue: 3000 }, - { month: 'Dec', revenue: 4800 }, -]; - -module.exports = { - users, - customers, - invoices, - revenue, -}; diff --git a/src/app/lib/utils.ts b/src/app/lib/utils.ts index c3184af..b7b6e70 100644 --- a/src/app/lib/utils.ts +++ b/src/app/lib/utils.ts @@ -1,11 +1,5 @@ import Revenue from "@/feature/core/revenue/domain/entity/revenue"; -export const formatCurrency = (amount: number) => { - return (amount / 100).toLocaleString('en-US', { - style: 'currency', - currency: 'USD', - }); -}; export const generateYAxis = (revenue: Revenue[]) => { // Calculate what labels we need to display on the y-axis diff --git a/src/bootstrap/helpers/global-helpers.ts b/src/bootstrap/helpers/global-helpers.ts new file mode 100644 index 0000000..e69de29 diff --git a/src/feature/common/feature-helpers.ts b/src/feature/common/feature-helpers.ts new file mode 100644 index 0000000..4269137 --- /dev/null +++ b/src/feature/common/feature-helpers.ts @@ -0,0 +1,6 @@ +export const formatCurrency = (amount: number) => { + return (amount / 100).toLocaleString('en-US', { + style: 'currency', + currency: 'USD', + }); +}; \ No newline at end of file diff --git a/src/feature/core/customer-invoice/data/repo/customer-invoice-db-repo.ts b/src/feature/core/customer-invoice/data/repo/customer-invoice-db-repo.ts index 18f7db1..ba6eff5 100644 --- a/src/feature/core/customer-invoice/data/repo/customer-invoice-db-repo.ts +++ b/src/feature/core/customer-invoice/data/repo/customer-invoice-db-repo.ts @@ -1,5 +1,5 @@ -import { formatCurrency } from "@/app/lib/utils"; import { sql } from "@/bootstrap/db/db"; +import { formatCurrency } from "@/feature/common/feature-helpers"; import CustomerInvoice from "@/feature/core/customer-invoice/domain/entity/customer-invoice"; import CustomerInvoiceRepo from "@/feature/core/customer-invoice/domain/i-repo/customer-invoice-repo"; import postgres from "postgres"; diff --git a/src/feature/core/customer/data/repo/customer-db-repo.ts b/src/feature/core/customer/data/repo/customer-db-repo.ts index ad6705f..f1239a4 100644 --- a/src/feature/core/customer/data/repo/customer-db-repo.ts +++ b/src/feature/core/customer/data/repo/customer-db-repo.ts @@ -1,8 +1,7 @@ -import { formatCurrency } from "@/app/lib/utils"; import { sql } from "@/bootstrap/db/db"; +import { formatCurrency } from "@/feature/common/feature-helpers"; import Customer from "@/feature/core/customer/domain/entity/customer"; import CustomerRepo from "@/feature/core/customer/domain/i-repo/customer-repo"; -import { connection } from "next/server"; import postgres from "postgres"; type customerDbResponse = { diff --git a/src/feature/core/invoice/data/repo/invoice-db-repo.ts b/src/feature/core/invoice/data/repo/invoice-db-repo.ts index c9bf5e9..66c0998 100644 --- a/src/feature/core/invoice/data/repo/invoice-db-repo.ts +++ b/src/feature/core/invoice/data/repo/invoice-db-repo.ts @@ -1,5 +1,5 @@ -import { formatCurrency } from "@/app/lib/utils"; import { sql } from "@/bootstrap/db/db"; +import { formatCurrency } from "@/feature/common/feature-helpers"; import InvoiceRepo from "@/feature/core/invoice/domain/i-repo/invoice-repo"; import InvoiceStatusSummary from "@/feature/core/invoice/domain/value-object/invoice-status"; import postgres from "postgres"; -- 2.39.5 From c85dd44029f31cdc41ccf2663abe9f8a5a1ed36a Mon Sep 17 00:00:00 2001 From: behnam <behnamrahimpour74@gmail.com> Date: Fri, 1 Nov 2024 18:16:12 +0300 Subject: [PATCH 18/37] Update location of skeleton for dashboard --- src/app/dashboard/(overview)/loading.tsx | 2 +- src/app/dashboard/(overview)/page.tsx | 2 +- .../skeleton => dashboard/components/skeletons}/skeletons.tsx | 0 3 files changed, 2 insertions(+), 2 deletions(-) rename src/app/{components/skeleton => dashboard/components/skeletons}/skeletons.tsx (100%) diff --git a/src/app/dashboard/(overview)/loading.tsx b/src/app/dashboard/(overview)/loading.tsx index fcf5df1..40c27b6 100644 --- a/src/app/dashboard/(overview)/loading.tsx +++ b/src/app/dashboard/(overview)/loading.tsx @@ -1,4 +1,4 @@ -import DashboardSkeleton from "@/app/components/skeleton/skeletons"; +import DashboardSkeleton from "@/app/dashboard/components/skeletons/skeletons"; export default function Loading() { return <DashboardSkeleton />; diff --git a/src/app/dashboard/(overview)/page.tsx b/src/app/dashboard/(overview)/page.tsx index 463edbb..c6b1b07 100644 --- a/src/app/dashboard/(overview)/page.tsx +++ b/src/app/dashboard/(overview)/page.tsx @@ -1,4 +1,4 @@ -import { LatestInvoicesSkeleton, RevenueChartSkeleton } from "@/app/components/skeleton/skeletons"; +import { LatestInvoicesSkeleton, RevenueChartSkeleton } from "@/app/dashboard/components/skeletons/skeletons"; import CardWrapper from "@/app/dashboard/components/cards/cards"; import LatestInvoices from "@/app/dashboard/components/latest-invoices"; import RevenueChart from "@/app/dashboard/components/revenue-chart"; diff --git a/src/app/components/skeleton/skeletons.tsx b/src/app/dashboard/components/skeletons/skeletons.tsx similarity index 100% rename from src/app/components/skeleton/skeletons.tsx rename to src/app/dashboard/components/skeletons/skeletons.tsx -- 2.39.5 From 22e97cf74f001e566c5c4ad69b6da6738bea9cfb Mon Sep 17 00:00:00 2001 From: behnam <behnamrahimpour74@gmail.com> Date: Fri, 1 Nov 2024 18:20:23 +0300 Subject: [PATCH 19/37] Update revenue chart architecture to follow controller architecture --- src/app/dashboard/(overview)/page.tsx | 2 +- .../revenue-chart/revenue-chart-controller.ts} | 16 +++++++++++++++- .../{ => revenue-chart}/revenue-chart.tsx | 9 ++------- 3 files changed, 18 insertions(+), 9 deletions(-) rename src/app/{lib/utils.ts => dashboard/components/revenue-chart/revenue-chart-controller.ts} (52%) rename src/app/dashboard/components/{ => revenue-chart}/revenue-chart.tsx (84%) diff --git a/src/app/dashboard/(overview)/page.tsx b/src/app/dashboard/(overview)/page.tsx index c6b1b07..e6017fc 100644 --- a/src/app/dashboard/(overview)/page.tsx +++ b/src/app/dashboard/(overview)/page.tsx @@ -1,7 +1,7 @@ import { LatestInvoicesSkeleton, RevenueChartSkeleton } from "@/app/dashboard/components/skeletons/skeletons"; import CardWrapper from "@/app/dashboard/components/cards/cards"; import LatestInvoices from "@/app/dashboard/components/latest-invoices"; -import RevenueChart from "@/app/dashboard/components/revenue-chart"; +import RevenueChart from "@/app/dashboard/components/revenue-chart/revenue-chart"; import { Suspense } from "react"; export default async function Dashboard() { diff --git a/src/app/lib/utils.ts b/src/app/dashboard/components/revenue-chart/revenue-chart-controller.ts similarity index 52% rename from src/app/lib/utils.ts rename to src/app/dashboard/components/revenue-chart/revenue-chart-controller.ts index b7b6e70..becc678 100644 --- a/src/app/lib/utils.ts +++ b/src/app/dashboard/components/revenue-chart/revenue-chart-controller.ts @@ -1,7 +1,21 @@ import Revenue from "@/feature/core/revenue/domain/entity/revenue"; +import fetchRevenuesUsecase from "@/feature/core/revenue/domain/usecase/fetch-revenues-usecase"; +export default async function revenueChartController() { + const revenue = await fetchRevenuesUsecase(); + const chartHeight = 350; -export const generateYAxis = (revenue: Revenue[]) => { + const { yAxisLabels, topLabel } = generateYAxis(revenue); + + return { + revenue, + chartHeight, + yAxisLabels, + topLabel + } +} + +function generateYAxis(revenue: Revenue[]) { // Calculate what labels we need to display on the y-axis // based on highest record and in 1000s const yAxisLabels = []; diff --git a/src/app/dashboard/components/revenue-chart.tsx b/src/app/dashboard/components/revenue-chart/revenue-chart.tsx similarity index 84% rename from src/app/dashboard/components/revenue-chart.tsx rename to src/app/dashboard/components/revenue-chart/revenue-chart.tsx index f6a6f91..608163c 100644 --- a/src/app/dashboard/components/revenue-chart.tsx +++ b/src/app/dashboard/components/revenue-chart/revenue-chart.tsx @@ -1,13 +1,8 @@ -import { generateYAxis } from '@/app/lib/utils'; -import fetchRevenuesUsecase from '@/feature/core/revenue/domain/usecase/fetch-revenues-usecase'; +import revenueChartController from '@/app/dashboard/components/revenue-chart/revenue-chart-controller'; import { CalendarIcon } from '@heroicons/react/24/outline'; export default async function RevenueChart() { - const revenue = await fetchRevenuesUsecase(); - - const chartHeight = 350; - - const { yAxisLabels, topLabel } = generateYAxis(revenue); + const { chartHeight, revenue, topLabel, yAxisLabels } = await revenueChartController() if (!revenue || revenue.length === 0) { return <p className="mt-4 text-gray-400">No data available.</p>; -- 2.39.5 From 38f6a47f6500bed31d05ddc7a7125e937c64b34f Mon Sep 17 00:00:00 2001 From: behnam <behnamrahimpour74@gmail.com> Date: Fri, 1 Nov 2024 18:23:00 +0300 Subject: [PATCH 20/37] Update latest invoices architecture to follow controller architecture --- src/app/dashboard/(overview)/page.tsx | 2 +- .../latest-invoices-controller.ts | 5 ++++ .../{ => latest-invoices}/latest-invoices.tsx | 26 ++++++++++--------- 3 files changed, 20 insertions(+), 13 deletions(-) create mode 100644 src/app/dashboard/components/latest-invoices/latest-invoices-controller.ts rename src/app/dashboard/components/{ => latest-invoices}/latest-invoices.tsx (88%) diff --git a/src/app/dashboard/(overview)/page.tsx b/src/app/dashboard/(overview)/page.tsx index e6017fc..519d478 100644 --- a/src/app/dashboard/(overview)/page.tsx +++ b/src/app/dashboard/(overview)/page.tsx @@ -1,6 +1,6 @@ import { LatestInvoicesSkeleton, RevenueChartSkeleton } from "@/app/dashboard/components/skeletons/skeletons"; import CardWrapper from "@/app/dashboard/components/cards/cards"; -import LatestInvoices from "@/app/dashboard/components/latest-invoices"; +import LatestInvoices from "@/app/dashboard/components/latest-invoices/latest-invoices"; import RevenueChart from "@/app/dashboard/components/revenue-chart/revenue-chart"; import { Suspense } from "react"; diff --git a/src/app/dashboard/components/latest-invoices/latest-invoices-controller.ts b/src/app/dashboard/components/latest-invoices/latest-invoices-controller.ts new file mode 100644 index 0000000..45bde22 --- /dev/null +++ b/src/app/dashboard/components/latest-invoices/latest-invoices-controller.ts @@ -0,0 +1,5 @@ +import fetchCustomerInvoicesUsecase from "@/feature/core/customer-invoice/domain/usecase/fetch-customer-invoices-usecase"; + +export default function latestInvoicesController() { + return fetchCustomerInvoicesUsecase() +} \ No newline at end of file diff --git a/src/app/dashboard/components/latest-invoices.tsx b/src/app/dashboard/components/latest-invoices/latest-invoices.tsx similarity index 88% rename from src/app/dashboard/components/latest-invoices.tsx rename to src/app/dashboard/components/latest-invoices/latest-invoices.tsx index 6f62655..0db6556 100644 --- a/src/app/dashboard/components/latest-invoices.tsx +++ b/src/app/dashboard/components/latest-invoices/latest-invoices.tsx @@ -1,19 +1,12 @@ -import fetchCustomerInvoicesUsecase from '@/feature/core/customer-invoice/domain/usecase/fetch-customer-invoices-usecase'; +import latestInvoicesController from '@/app/dashboard/components/latest-invoices/latest-invoices-controller'; import { ArrowPathIcon } from '@heroicons/react/24/outline'; import clsx from 'clsx'; import Image from 'next/image'; + export default async function LatestInvoices() { - const latestInvoices = await fetchCustomerInvoicesUsecase(); + const latestInvoices = await latestInvoicesController(); - return ( - <div className="flex w-full flex-col md:col-span-4"> - <h2 className="mb-4 text-xl md:text-2xl"> - Latest Invoices - </h2> - <div className="flex grow flex-col justify-between rounded-xl bg-gray-50 p-4"> - - <div className="bg-white px-6"> - {latestInvoices.map((invoice, i) => { + const invoices = latestInvoices.map((invoice, i) => { return ( <div key={invoice.id} @@ -48,7 +41,16 @@ export default async function LatestInvoices() { </p> </div> ); - })} + }) + return ( + <div className="flex w-full flex-col md:col-span-4"> + <h2 className="mb-4 text-xl md:text-2xl"> + Latest Invoices + </h2> + <div className="flex grow flex-col justify-between rounded-xl bg-gray-50 p-4"> + + <div className="bg-white px-6"> + {invoices} </div> <div className="flex items-center pb-2 pt-6"> <ArrowPathIcon className="h-5 w-5 text-gray-500" /> -- 2.39.5 From f522877b1948b02404d10965c704c7110944a5ce Mon Sep 17 00:00:00 2001 From: behnam <behnamrahimpour74@gmail.com> Date: Fri, 1 Nov 2024 18:31:59 +0300 Subject: [PATCH 21/37] Update dashboard main page to follow architecture of app layer --- src/app/dashboard/(overview)/loading.tsx | 5 ---- .../client/nav-links/nav-link-controller.ts | 29 +++++++++++++++++++ .../{ => client/nav-links}/nav-links.tsx | 21 ++------------ .../{ => server}/card/card-controller.ts | 0 .../components/{ => server}/card/card.tsx | 2 +- .../{ => server}/cards/cards-controller.ts | 0 .../components/{ => server}/cards/cards.tsx | 4 +-- .../latest-invoices-controller.ts | 0 .../latest-invoices/latest-invoices.tsx | 2 +- .../revenue-chart/revenue-chart-controller.ts | 0 .../revenue-chart/revenue-chart.tsx | 2 +- .../components/{ => server}/sidenav.tsx | 2 +- .../{ => server}/skeletons/skeletons.tsx | 0 src/app/dashboard/layout.tsx | 2 +- src/app/dashboard/loading.tsx | 5 ++++ src/app/dashboard/{(overview) => }/page.tsx | 8 ++--- 16 files changed, 48 insertions(+), 34 deletions(-) delete mode 100644 src/app/dashboard/(overview)/loading.tsx create mode 100644 src/app/dashboard/components/client/nav-links/nav-link-controller.ts rename src/app/dashboard/components/{ => client/nav-links}/nav-links.tsx (51%) rename src/app/dashboard/components/{ => server}/card/card-controller.ts (100%) rename src/app/dashboard/components/{ => server}/card/card.tsx (87%) rename src/app/dashboard/components/{ => server}/cards/cards-controller.ts (100%) rename src/app/dashboard/components/{ => server}/cards/cards.tsx (76%) rename src/app/dashboard/components/{ => server}/latest-invoices/latest-invoices-controller.ts (100%) rename src/app/dashboard/components/{ => server}/latest-invoices/latest-invoices.tsx (97%) rename src/app/dashboard/components/{ => server}/revenue-chart/revenue-chart-controller.ts (100%) rename src/app/dashboard/components/{ => server}/revenue-chart/revenue-chart.tsx (93%) rename src/app/dashboard/components/{ => server}/sidenav.tsx (88%) rename src/app/dashboard/components/{ => server}/skeletons/skeletons.tsx (100%) create mode 100644 src/app/dashboard/loading.tsx rename src/app/dashboard/{(overview) => }/page.tsx (68%) diff --git a/src/app/dashboard/(overview)/loading.tsx b/src/app/dashboard/(overview)/loading.tsx deleted file mode 100644 index 40c27b6..0000000 --- a/src/app/dashboard/(overview)/loading.tsx +++ /dev/null @@ -1,5 +0,0 @@ -import DashboardSkeleton from "@/app/dashboard/components/skeletons/skeletons"; - -export default function Loading() { - return <DashboardSkeleton />; -} \ No newline at end of file diff --git a/src/app/dashboard/components/client/nav-links/nav-link-controller.ts b/src/app/dashboard/components/client/nav-links/nav-link-controller.ts new file mode 100644 index 0000000..b6a3aa9 --- /dev/null +++ b/src/app/dashboard/components/client/nav-links/nav-link-controller.ts @@ -0,0 +1,29 @@ + +import { DocumentIcon } from '@/app/components/icons/document'; +import HomeIcon from '@/app/components/icons/home'; +import { UserIcon } from '@/app/components/icons/user'; +import { usePathname } from 'next/navigation'; + +type LinkItem = { + name: string; + href: string; + icon: (props: {className?: string}) => JSX.Element +} +export default function navLinkPersonalVM() { + const pathname = usePathname() + // Map of links to display in the side navigation. + // Depending on the size of the application, this would be stored in a database. + const links: LinkItem[] = [ + { name: 'Home', href: '/dashboard', icon: HomeIcon }, + { + name: 'Invoices', + href: '/dashboard/invoices', + icon: DocumentIcon, + }, + { name: 'Customers', href: '/dashboard/customers', icon: UserIcon }, + ]; + return { + links, + isLinkActive: (link: LinkItem) => pathname === link.href + } +} \ No newline at end of file diff --git a/src/app/dashboard/components/nav-links.tsx b/src/app/dashboard/components/client/nav-links/nav-links.tsx similarity index 51% rename from src/app/dashboard/components/nav-links.tsx rename to src/app/dashboard/components/client/nav-links/nav-links.tsx index ecfca9e..1aa6072 100644 --- a/src/app/dashboard/components/nav-links.tsx +++ b/src/app/dashboard/components/client/nav-links/nav-links.tsx @@ -1,25 +1,10 @@ 'use client' -import { DocumentIcon } from '@/app/components/icons/document'; -import HomeIcon from '@/app/components/icons/home'; -import { UserIcon } from '@/app/components/icons/user'; +import navLinkPersonalVM from '@/app/dashboard/components/client/nav-links/nav-link-controller'; import clsx from 'clsx'; import Link from 'next/link' -import { usePathname } from 'next/navigation'; - -// Map of links to display in the side navigation. -// Depending on the size of the application, this would be stored in a database. -const links = [ - { name: 'Home', href: '/dashboard', icon: HomeIcon }, - { - name: 'Invoices', - href: '/dashboard/invoices', - icon: DocumentIcon, - }, - { name: 'Customers', href: '/dashboard/customers', icon: UserIcon }, -]; export default function NavLinks() { - const pathname = usePathname() + const { links, isLinkActive } = navLinkPersonalVM() return ( <> {links.map((link) => { @@ -31,7 +16,7 @@ export default function NavLinks() { className={clsx( 'flex h-[48px] grow items-center justify-center gap-2 rounded-md bg-gray-50 p-3 text-sm font-medium hover:bg-sky-100 hover:text-blue-600 md:flex-none md:justify-start md:p-2 md:px-3', { - 'bg-sky-100 text-blue-600': pathname === link.href, + 'bg-sky-100 text-blue-600': isLinkActive(link), }, )} > diff --git a/src/app/dashboard/components/card/card-controller.ts b/src/app/dashboard/components/server/card/card-controller.ts similarity index 100% rename from src/app/dashboard/components/card/card-controller.ts rename to src/app/dashboard/components/server/card/card-controller.ts diff --git a/src/app/dashboard/components/card/card.tsx b/src/app/dashboard/components/server/card/card.tsx similarity index 87% rename from src/app/dashboard/components/card/card.tsx rename to src/app/dashboard/components/server/card/card.tsx index 5494f4f..1b22154 100644 --- a/src/app/dashboard/components/card/card.tsx +++ b/src/app/dashboard/components/server/card/card.tsx @@ -1,4 +1,4 @@ -import cardController from "@/app/dashboard/components/card/card-controller"; +import cardController from "@/app/dashboard/components/server/card/card-controller"; diff --git a/src/app/dashboard/components/cards/cards-controller.ts b/src/app/dashboard/components/server/cards/cards-controller.ts similarity index 100% rename from src/app/dashboard/components/cards/cards-controller.ts rename to src/app/dashboard/components/server/cards/cards-controller.ts diff --git a/src/app/dashboard/components/cards/cards.tsx b/src/app/dashboard/components/server/cards/cards.tsx similarity index 76% rename from src/app/dashboard/components/cards/cards.tsx rename to src/app/dashboard/components/server/cards/cards.tsx index c39a4fe..e8f74a9 100644 --- a/src/app/dashboard/components/cards/cards.tsx +++ b/src/app/dashboard/components/server/cards/cards.tsx @@ -1,5 +1,5 @@ -import { Card } from '@/app/dashboard/components/card/card'; -import cardsController from '@/app/dashboard/components/cards/cards-controller'; +import { Card } from '@/app/dashboard/components/server/card/card'; +import cardsController from '@/app/dashboard/components/server/cards/cards-controller'; export default async function CardWrapper() { diff --git a/src/app/dashboard/components/latest-invoices/latest-invoices-controller.ts b/src/app/dashboard/components/server/latest-invoices/latest-invoices-controller.ts similarity index 100% rename from src/app/dashboard/components/latest-invoices/latest-invoices-controller.ts rename to src/app/dashboard/components/server/latest-invoices/latest-invoices-controller.ts diff --git a/src/app/dashboard/components/latest-invoices/latest-invoices.tsx b/src/app/dashboard/components/server/latest-invoices/latest-invoices.tsx similarity index 97% rename from src/app/dashboard/components/latest-invoices/latest-invoices.tsx rename to src/app/dashboard/components/server/latest-invoices/latest-invoices.tsx index 0db6556..dc3c7be 100644 --- a/src/app/dashboard/components/latest-invoices/latest-invoices.tsx +++ b/src/app/dashboard/components/server/latest-invoices/latest-invoices.tsx @@ -1,4 +1,4 @@ -import latestInvoicesController from '@/app/dashboard/components/latest-invoices/latest-invoices-controller'; +import latestInvoicesController from '@/app/dashboard/components/server/latest-invoices/latest-invoices-controller'; import { ArrowPathIcon } from '@heroicons/react/24/outline'; import clsx from 'clsx'; import Image from 'next/image'; diff --git a/src/app/dashboard/components/revenue-chart/revenue-chart-controller.ts b/src/app/dashboard/components/server/revenue-chart/revenue-chart-controller.ts similarity index 100% rename from src/app/dashboard/components/revenue-chart/revenue-chart-controller.ts rename to src/app/dashboard/components/server/revenue-chart/revenue-chart-controller.ts diff --git a/src/app/dashboard/components/revenue-chart/revenue-chart.tsx b/src/app/dashboard/components/server/revenue-chart/revenue-chart.tsx similarity index 93% rename from src/app/dashboard/components/revenue-chart/revenue-chart.tsx rename to src/app/dashboard/components/server/revenue-chart/revenue-chart.tsx index 608163c..b29a7ae 100644 --- a/src/app/dashboard/components/revenue-chart/revenue-chart.tsx +++ b/src/app/dashboard/components/server/revenue-chart/revenue-chart.tsx @@ -1,4 +1,4 @@ -import revenueChartController from '@/app/dashboard/components/revenue-chart/revenue-chart-controller'; +import revenueChartController from '@/app/dashboard/components/server/revenue-chart/revenue-chart-controller'; import { CalendarIcon } from '@heroicons/react/24/outline'; export default async function RevenueChart() { diff --git a/src/app/dashboard/components/sidenav.tsx b/src/app/dashboard/components/server/sidenav.tsx similarity index 88% rename from src/app/dashboard/components/sidenav.tsx rename to src/app/dashboard/components/server/sidenav.tsx index 7cf3d44..0af5a13 100644 --- a/src/app/dashboard/components/sidenav.tsx +++ b/src/app/dashboard/components/server/sidenav.tsx @@ -1,4 +1,4 @@ -import NavLinks from '@/app/dashboard/components/nav-links'; +import NavLinks from '@/app/dashboard/components/client/nav-links/nav-links'; import Link from 'next/link'; export default function SideNav() { diff --git a/src/app/dashboard/components/skeletons/skeletons.tsx b/src/app/dashboard/components/server/skeletons/skeletons.tsx similarity index 100% rename from src/app/dashboard/components/skeletons/skeletons.tsx rename to src/app/dashboard/components/server/skeletons/skeletons.tsx diff --git a/src/app/dashboard/layout.tsx b/src/app/dashboard/layout.tsx index d28eae9..75b7ecb 100644 --- a/src/app/dashboard/layout.tsx +++ b/src/app/dashboard/layout.tsx @@ -1,4 +1,4 @@ -import SideNav from "@/app/dashboard/components/sidenav"; +import SideNav from "@/app/dashboard/components/server/sidenav"; export default function Layout({ children }: { children: React.ReactNode }) { diff --git a/src/app/dashboard/loading.tsx b/src/app/dashboard/loading.tsx new file mode 100644 index 0000000..c50ad40 --- /dev/null +++ b/src/app/dashboard/loading.tsx @@ -0,0 +1,5 @@ +import DashboardSkeleton from "@/app/dashboard/components/server/skeletons/skeletons"; + +export default function Loading() { + return <DashboardSkeleton />; +} \ No newline at end of file diff --git a/src/app/dashboard/(overview)/page.tsx b/src/app/dashboard/page.tsx similarity index 68% rename from src/app/dashboard/(overview)/page.tsx rename to src/app/dashboard/page.tsx index 519d478..24fb89a 100644 --- a/src/app/dashboard/(overview)/page.tsx +++ b/src/app/dashboard/page.tsx @@ -1,7 +1,7 @@ -import { LatestInvoicesSkeleton, RevenueChartSkeleton } from "@/app/dashboard/components/skeletons/skeletons"; -import CardWrapper from "@/app/dashboard/components/cards/cards"; -import LatestInvoices from "@/app/dashboard/components/latest-invoices/latest-invoices"; -import RevenueChart from "@/app/dashboard/components/revenue-chart/revenue-chart"; +import { LatestInvoicesSkeleton, RevenueChartSkeleton } from "@/app/dashboard/components/server/skeletons/skeletons"; +import CardWrapper from "@/app/dashboard/components/server/cards/cards"; +import LatestInvoices from "@/app/dashboard/components/server/latest-invoices/latest-invoices"; +import RevenueChart from "@/app/dashboard/components/server/revenue-chart/revenue-chart"; import { Suspense } from "react"; export default async function Dashboard() { -- 2.39.5 From f375de27ec7437bf976c6bec4770e68ec7472781 Mon Sep 17 00:00:00 2001 From: behnam <behnamrahimpour74@gmail.com> Date: Fri, 1 Nov 2024 18:47:24 +0300 Subject: [PATCH 22/37] Add button and update shadcn configs --- components.json | 10 ++-- package.json | 1 + src/app/components/button/button.tsx | 59 ++++++++++++++++++- src/{app => bootstrap/helpers}/lib/actions.ts | 0 .../helpers/lib/ui-utils.ts} | 0 src/bootstrap/helpers/view/base-view.tsx | 8 ++- yarn.lock | 12 ++++ 7 files changed, 82 insertions(+), 8 deletions(-) rename src/{app => bootstrap/helpers}/lib/actions.ts (100%) rename src/{lib/utils.ts => bootstrap/helpers/lib/ui-utils.ts} (100%) diff --git a/components.json b/components.json index 7a63543..a0c8a84 100644 --- a/components.json +++ b/components.json @@ -11,10 +11,10 @@ "prefix": "" }, "aliases": { - "components": "@/components", - "utils": "@/lib/utils", - "ui": "@/components/ui", - "lib": "@/lib", - "hooks": "@/hooks" + "components": "@/app/components", + "utils": "@/bootstrap/helpers/lib/ui-utils", + "ui": "@/app/components", + "lib": "@/bootstrap/helpers/lib", + "hooks": "@/bootstrap/helpers/vm/hooks" } } \ No newline at end of file diff --git a/package.json b/package.json index 2a11c38..62211ce 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ "dependencies": { "@heroicons/react": "^2.1.5", "@radix-ui/react-icons": "^1.3.1", + "@radix-ui/react-slot": "^1.1.0", "class-variance-authority": "^0.7.0", "clsx": "^2.1.1", "lucide-react": "^0.454.0", diff --git a/src/app/components/button/button.tsx b/src/app/components/button/button.tsx index e1b8a4d..6d0c377 100644 --- a/src/app/components/button/button.tsx +++ b/src/app/components/button/button.tsx @@ -2,11 +2,68 @@ import BaseView, { BuildProps } from "@/bootstrap/helpers/view/base-view"; import ButtonVm from "@/app/components/button/button-vm"; import { ReactNode } from "react"; +import * as React from "react" +import { Slot } from "@radix-ui/react-slot" +import { cva, type VariantProps } from "class-variance-authority" +import { cn } from "@/bootstrap/helpers/lib/ui-utils"; export default class Button extends BaseView<ButtonVm> { protected Build(props: BuildProps<ButtonVm>): ReactNode { const {vm} = props - return <button onClick={vm.onClick} >{vm.props.title}</button> + return <ButtonUi onClick={vm.onClick} >{vm.props.title}</ButtonUi> } } + + +const buttonVariants = cva( + "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0", + { + variants: { + variant: { + default: + "bg-primary text-primary-foreground shadow hover:bg-primary/90", + destructive: + "bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90", + outline: + "border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground", + secondary: + "bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80", + ghost: "hover:bg-accent hover:text-accent-foreground", + link: "text-primary underline-offset-4 hover:underline", + }, + size: { + default: "h-9 px-4 py-2", + sm: "h-8 rounded-md px-3 text-xs", + lg: "h-10 rounded-md px-8", + icon: "h-9 w-9", + }, + }, + defaultVariants: { + variant: "default", + size: "default", + }, + } +) + +export interface ButtonProps + extends React.ButtonHTMLAttributes<HTMLButtonElement>, + VariantProps<typeof buttonVariants> { + asChild?: boolean +} + +const ButtonUi = React.forwardRef<HTMLButtonElement, ButtonProps>( + ({ className, variant, size, asChild = false, ...props }, ref) => { + const Comp = asChild ? Slot : "button" + return ( + <Comp + className={cn(buttonVariants({ variant, size, className }))} + ref={ref} + {...props} + /> + ) + } +) +ButtonUi.displayName = "Button" + +export { Button, buttonVariants } \ No newline at end of file diff --git a/src/app/lib/actions.ts b/src/bootstrap/helpers/lib/actions.ts similarity index 100% rename from src/app/lib/actions.ts rename to src/bootstrap/helpers/lib/actions.ts diff --git a/src/lib/utils.ts b/src/bootstrap/helpers/lib/ui-utils.ts similarity index 100% rename from src/lib/utils.ts rename to src/bootstrap/helpers/lib/ui-utils.ts diff --git a/src/bootstrap/helpers/view/base-view.tsx b/src/bootstrap/helpers/view/base-view.tsx index a1eecc7..990cd19 100644 --- a/src/bootstrap/helpers/view/base-view.tsx +++ b/src/bootstrap/helpers/view/base-view.tsx @@ -69,13 +69,17 @@ export default abstract class BaseView< IVM extends IVMParent, PROPS extends IPropParent = undefined, > extends Component<BaseProps<IVM, PROPS>> { - /* -------------------------------- Abstracts ------------------------------- */ protected abstract Build(props: BuildProps<IVM, PROPS>): ReactNode; - /* -------------------------------- Renderer -------------------------------- */ + protected get componentName() { + return this.constructor.name + } + render(): ReactNode { const { vm, restProps, memoizedByVM, children, ...rest } = this.props; + VvmConnector.displayName = this.componentName + return ( <VvmConnector View={this.Build} diff --git a/yarn.lock b/yarn.lock index 1a06bc5..6d7dde4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -613,11 +613,23 @@ resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33" integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg== +"@radix-ui/react-compose-refs@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.0.tgz#656432461fc8283d7b591dcf0d79152fae9ecc74" + integrity sha512-b4inOtiaOnYf9KWyO3jAeeCG6FeyfY6ldiEPanbUjWd+xIk5wZeHa8yVwmrJ2vderhu/BQvzCrJI0lHd+wIiqw== + "@radix-ui/react-icons@^1.3.1": version "1.3.1" resolved "https://registry.yarnpkg.com/@radix-ui/react-icons/-/react-icons-1.3.1.tgz#462c85fd726a77854cd5956e29eb19a575aa7ce5" integrity sha512-QvYompk0X+8Yjlo/Fv4McrzxohDdM5GgLHyQcPpcsPvlOSXCGFjdbuyGL5dzRbg0GpknAjQJJZzdiRK7iWVuFQ== +"@radix-ui/react-slot@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-slot/-/react-slot-1.1.0.tgz#7c5e48c36ef5496d97b08f1357bb26ed7c714b84" + integrity sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw== + dependencies: + "@radix-ui/react-compose-refs" "1.1.0" + "@rollup/rollup-android-arm-eabi@4.24.3": version "4.24.3" resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.24.3.tgz#49a2a9808074f2683667992aa94b288e0b54fc82" -- 2.39.5 From 96e7811fff23adbc5cc64a720ef11e0208b908d0 Mon Sep 17 00:00:00 2001 From: behnam <behnamrahimpour74@gmail.com> Date: Fri, 1 Nov 2024 18:59:23 +0300 Subject: [PATCH 23/37] Add base vm for create invoice button --- src/app/components/button/button.tsx | 2 +- .../create-random-invoice.tsx | 13 +++++++++++ .../latest-invoices/latest-invoices.tsx | 4 +++- src/app/dashboard/layout.tsx | 17 +++++++++----- .../dashboard/module/dashboard-app-module.ts | 22 ++----------------- .../vm/create-random-invoice-button-vm.ts | 15 +++++++++++++ 6 files changed, 46 insertions(+), 27 deletions(-) create mode 100644 src/app/dashboard/components/client/create-random-invoice/create-random-invoice.tsx create mode 100644 src/app/dashboard/vm/create-random-invoice-button-vm.ts diff --git a/src/app/components/button/button.tsx b/src/app/components/button/button.tsx index 6d0c377..5245285 100644 --- a/src/app/components/button/button.tsx +++ b/src/app/components/button/button.tsx @@ -66,4 +66,4 @@ const ButtonUi = React.forwardRef<HTMLButtonElement, ButtonProps>( ) ButtonUi.displayName = "Button" -export { Button, buttonVariants } \ No newline at end of file +export { buttonVariants } \ No newline at end of file diff --git a/src/app/dashboard/components/client/create-random-invoice/create-random-invoice.tsx b/src/app/dashboard/components/client/create-random-invoice/create-random-invoice.tsx new file mode 100644 index 0000000..8a80645 --- /dev/null +++ b/src/app/dashboard/components/client/create-random-invoice/create-random-invoice.tsx @@ -0,0 +1,13 @@ +"use client" + +import Button from "@/app/components/button/button" +import CreateRandomInvoiceButtonVM from "@/app/dashboard/vm/create-random-invoice-button-vm" +import { useDI } from "@/bootstrap/di/di-context" +import { useRef } from "react" + +export default function CreateRandomInvoiceContainer() { + const di = useDI() + const vm = useRef(di.resolve(CreateRandomInvoiceButtonVM)) + + return <Button vm={vm.current}/> +} \ No newline at end of file diff --git a/src/app/dashboard/components/server/latest-invoices/latest-invoices.tsx b/src/app/dashboard/components/server/latest-invoices/latest-invoices.tsx index dc3c7be..09b140b 100644 --- a/src/app/dashboard/components/server/latest-invoices/latest-invoices.tsx +++ b/src/app/dashboard/components/server/latest-invoices/latest-invoices.tsx @@ -1,3 +1,4 @@ +import CreateRandomInvoiceContainer from '@/app/dashboard/components/client/create-random-invoice/create-random-invoice'; import latestInvoicesController from '@/app/dashboard/components/server/latest-invoices/latest-invoices-controller'; import { ArrowPathIcon } from '@heroicons/react/24/outline'; import clsx from 'clsx'; @@ -52,10 +53,11 @@ export default async function LatestInvoices() { <div className="bg-white px-6"> {invoices} </div> - <div className="flex items-center pb-2 pt-6"> + <div className="flex items-end mt-auto pb-2 pt-6"> <ArrowPathIcon className="h-5 w-5 text-gray-500" /> <h3 className="ml-2 text-sm text-gray-500 ">Updated just now</h3> </div> + <CreateRandomInvoiceContainer /> </div> </div> ); diff --git a/src/app/dashboard/layout.tsx b/src/app/dashboard/layout.tsx index 75b7ecb..55125e7 100644 --- a/src/app/dashboard/layout.tsx +++ b/src/app/dashboard/layout.tsx @@ -1,13 +1,20 @@ +"use client" import SideNav from "@/app/dashboard/components/server/sidenav"; +import dashboardAppModule from "@/app/dashboard/module/dashboard-app-module"; +import { DiContext } from "@/bootstrap/di/di-context"; +import { useRef } from "react"; export default function Layout({ children }: { children: React.ReactNode }) { + const di = useRef(dashboardAppModule()) return ( - <div className="flex h-screen flex-col md:flex-row md:overflow-hidden"> - <div className="w-full flex-none md:w-64"> - <SideNav /> + <DiContext.Provider value={di.current}> + <div className="flex h-screen flex-col md:flex-row md:overflow-hidden"> + <div className="w-full flex-none md:w-64"> + <SideNav /> + </div> + <div className="flex-grow p-6 md:overflow-y-auto md:p-12">{children}</div> </div> - <div className="flex-grow p-6 md:overflow-y-auto md:p-12">{children}</div> - </div> + </DiContext.Provider> ); } \ No newline at end of file diff --git a/src/app/dashboard/module/dashboard-app-module.ts b/src/app/dashboard/module/dashboard-app-module.ts index fd9f144..a3611c1 100644 --- a/src/app/dashboard/module/dashboard-app-module.ts +++ b/src/app/dashboard/module/dashboard-app-module.ts @@ -1,27 +1,9 @@ +import CreateRandomInvoiceButtonVM from "@/app/dashboard/vm/create-random-invoice-button-vm"; import di from "@/bootstrap/di/init-di" -import fetchCustomerInvoicesUsecase from "@/feature/core/customer-invoice/domain/usecase/fetch-customer-invoices-usecase"; -import fetchCustomersUsecase from "@/feature/core/customer/domain/usecase/fetch-customers-usecase"; -import fetchAllInvoicesAmountUsecase from "@/feature/core/invoice/domain/usecase/fetch-all-invoices-amount-usecase"; -import fetchRevenuesUsecase from "@/feature/core/revenue/domain/usecase/fetch-revenues-usecase"; export default function dashboardAppModule() { const dashboardDi = di.createChildContainer() - dashboardDi.register(fetchCustomersUsecase.name, { - useValue: fetchCustomersUsecase - }) - - dashboardDi.register(fetchAllInvoicesAmountUsecase.name, { - useValue: fetchAllInvoicesAmountUsecase - }) - dashboardDi.register(fetchAllInvoicesAmountUsecase.name, { - useValue: fetchAllInvoicesAmountUsecase - }) - dashboardDi.register(fetchCustomerInvoicesUsecase.name, { - useValue: fetchCustomerInvoicesUsecase - }) - dashboardDi.register(fetchRevenuesUsecase.name, { - useValue: fetchRevenuesUsecase - }) + dashboardDi.register(CreateRandomInvoiceButtonVM, CreateRandomInvoiceButtonVM) return dashboardDi } diff --git a/src/app/dashboard/vm/create-random-invoice-button-vm.ts b/src/app/dashboard/vm/create-random-invoice-button-vm.ts new file mode 100644 index 0000000..3bbf802 --- /dev/null +++ b/src/app/dashboard/vm/create-random-invoice-button-vm.ts @@ -0,0 +1,15 @@ +import ButtonVm from "@/app/components/button/button-vm"; +import BaseVM from "@/bootstrap/helpers/vm/base-vm"; + +export default class CreateRandomInvoiceButtonVM extends BaseVM<ButtonVm> { + useVM(): ButtonVm { + return { + props: { + title: "Button Title" + }, + onClick: () => { + console.log('clicked'); + } + } + } +} \ No newline at end of file -- 2.39.5 From 021511e60e8f0aefce9e95a22448bc8c5037b999 Mon Sep 17 00:00:00 2001 From: behnam <behnamrahimpour74@gmail.com> Date: Fri, 1 Nov 2024 20:00:16 +0300 Subject: [PATCH 24/37] Add create random invoice module --- components.json | 2 +- .../latest-invoices/latest-invoices.tsx | 4 +-- .../dashboard/module/dashboard-app-module.ts | 4 +++ .../vm/create-random-invoice-button-vm.ts | 29 ++++++++++++++++--- src/bootstrap/helpers/hooks/use-throttle.ts | 18 ++++++++++++ .../data/repo/customer-invoice-db-repo.ts | 2 +- .../core/invoice/data/repo/invoice-db-repo.ts | 23 +++++++++++++++ .../invoice/domain/i-repo/invoice-repo.ts | 2 ++ .../invoice/domain/param/invoice-param.ts | 10 +++++++ .../domain/usecase/create-invoice-usecase.ts | 22 ++++++++++++++ 10 files changed, 108 insertions(+), 8 deletions(-) create mode 100644 src/bootstrap/helpers/hooks/use-throttle.ts create mode 100644 src/feature/core/invoice/domain/param/invoice-param.ts create mode 100644 src/feature/core/invoice/domain/usecase/create-invoice-usecase.ts diff --git a/components.json b/components.json index a0c8a84..88a82c6 100644 --- a/components.json +++ b/components.json @@ -15,6 +15,6 @@ "utils": "@/bootstrap/helpers/lib/ui-utils", "ui": "@/app/components", "lib": "@/bootstrap/helpers/lib", - "hooks": "@/bootstrap/helpers/vm/hooks" + "hooks": "@/bootstrap/helpers/hooks" } } \ No newline at end of file diff --git a/src/app/dashboard/components/server/latest-invoices/latest-invoices.tsx b/src/app/dashboard/components/server/latest-invoices/latest-invoices.tsx index 09b140b..09396cd 100644 --- a/src/app/dashboard/components/server/latest-invoices/latest-invoices.tsx +++ b/src/app/dashboard/components/server/latest-invoices/latest-invoices.tsx @@ -48,9 +48,9 @@ export default async function LatestInvoices() { <h2 className="mb-4 text-xl md:text-2xl"> Latest Invoices </h2> - <div className="flex grow flex-col justify-between rounded-xl bg-gray-50 p-4"> + <div className="flex grow flex-col max-h-[66.5vh] justify-between rounded-xl bg-gray-50 p-4"> - <div className="bg-white px-6"> + <div className="bg-white px-6 h-full overflow-y-auto"> {invoices} </div> <div className="flex items-end mt-auto pb-2 pt-6"> diff --git a/src/app/dashboard/module/dashboard-app-module.ts b/src/app/dashboard/module/dashboard-app-module.ts index a3611c1..60721eb 100644 --- a/src/app/dashboard/module/dashboard-app-module.ts +++ b/src/app/dashboard/module/dashboard-app-module.ts @@ -1,9 +1,13 @@ import CreateRandomInvoiceButtonVM from "@/app/dashboard/vm/create-random-invoice-button-vm"; import di from "@/bootstrap/di/init-di" +import createInvoiceUsecase from "@/feature/core/invoice/domain/usecase/create-invoice-usecase"; export default function dashboardAppModule() { const dashboardDi = di.createChildContainer() + dashboardDi.register(createInvoiceUsecase.name, { + useValue: createInvoiceUsecase + }) dashboardDi.register(CreateRandomInvoiceButtonVM, CreateRandomInvoiceButtonVM) return dashboardDi } diff --git a/src/app/dashboard/vm/create-random-invoice-button-vm.ts b/src/app/dashboard/vm/create-random-invoice-button-vm.ts index 3bbf802..11a258e 100644 --- a/src/app/dashboard/vm/create-random-invoice-button-vm.ts +++ b/src/app/dashboard/vm/create-random-invoice-button-vm.ts @@ -1,15 +1,36 @@ import ButtonVm from "@/app/components/button/button-vm"; +import useThrottle from "@/bootstrap/helpers/hooks/use-throttle"; import BaseVM from "@/bootstrap/helpers/vm/base-vm"; +import { InvoiceParam } from "@/feature/core/invoice/domain/param/invoice-param"; +import createInvoiceUsecase from "@/feature/core/invoice/domain/usecase/create-invoice-usecase"; +import { faker } from "@faker-js/faker"; export default class CreateRandomInvoiceButtonVM extends BaseVM<ButtonVm> { + private createInvoice: typeof createInvoiceUsecase + + constructor() { + super() + this.createInvoice = this.di.resolve(createInvoiceUsecase.name) + } + useVM(): ButtonVm { + const throttledOnClick = useThrottle(this.onClickHandler.bind(this), 5000) return { props: { - title: "Button Title" + title: "Create Random Invoice" }, - onClick: () => { - console.log('clicked'); - } + onClick: throttledOnClick } } + + onClickHandler() { + const fakedParams: InvoiceParam = { + amount: faker.number.int({ + min: 1, + max: 10 + }), + status: "paid" + } + this.createInvoice(fakedParams) + } } \ No newline at end of file diff --git a/src/bootstrap/helpers/hooks/use-throttle.ts b/src/bootstrap/helpers/hooks/use-throttle.ts new file mode 100644 index 0000000..ff2344f --- /dev/null +++ b/src/bootstrap/helpers/hooks/use-throttle.ts @@ -0,0 +1,18 @@ +"use client" + +import { useEffect, useRef } from "react" + +/** + * + * @param callback + * @param time In miliseconds + */ +export default function useThrottle<T extends Function>(callback: T, time: number = 2000) { + const lastRun = useRef(Date.now()) + + return function() { + if (Date.now() - lastRun.current <= time) return; + lastRun.current = Date.now() + return callback() + } +} \ No newline at end of file diff --git a/src/feature/core/customer-invoice/data/repo/customer-invoice-db-repo.ts b/src/feature/core/customer-invoice/data/repo/customer-invoice-db-repo.ts index ba6eff5..9c19809 100644 --- a/src/feature/core/customer-invoice/data/repo/customer-invoice-db-repo.ts +++ b/src/feature/core/customer-invoice/data/repo/customer-invoice-db-repo.ts @@ -20,7 +20,7 @@ export default class CustomerInvoiceDbRepo implements CustomerInvoiceRepo { FROM invoices JOIN customers ON invoices.customer_id = customers.id ORDER BY invoices.date DESC - LIMIT 5` as postgres.RowList<customerInvoiceDbResponse[]>; + LIMIT 20 ` as postgres.RowList<customerInvoiceDbResponse[]>; return this.customerInvoicesDto(data) } catch (error) { diff --git a/src/feature/core/invoice/data/repo/invoice-db-repo.ts b/src/feature/core/invoice/data/repo/invoice-db-repo.ts index 66c0998..fd2219c 100644 --- a/src/feature/core/invoice/data/repo/invoice-db-repo.ts +++ b/src/feature/core/invoice/data/repo/invoice-db-repo.ts @@ -1,6 +1,7 @@ import { sql } from "@/bootstrap/db/db"; import { formatCurrency } from "@/feature/common/feature-helpers"; import InvoiceRepo from "@/feature/core/invoice/domain/i-repo/invoice-repo"; +import { InvoiceParam } from "@/feature/core/invoice/domain/param/invoice-param"; import InvoiceStatusSummary from "@/feature/core/invoice/domain/value-object/invoice-status"; import postgres from "postgres"; @@ -12,6 +13,28 @@ export default class InvoiceDbRepo implements InvoiceRepo { return data.count ?? 0 } + async createInvoice(params: InvoiceParam): Promise<string> { + const firstCustomerIdDb = await sql`SELECT + id FROM customers + ORDER BY id ASC + LIMIT 1 + ` + const customerId = firstCustomerIdDb.at(0)?.id + if (!customerId) throw new Error("There is no customer") + + const { amount, status } = params; + const amountInCents = amount * 100; + const date = new Date().toISOString().split('T')[0]; + + // Insert data into the database + const result = await sql` + INSERT INTO invoices (customer_id, amount, status, date) + VALUES (${customerId}, ${amountInCents}, ${status}, ${date}) + RETURNING id + `; + return result.at(0)?.id ?? "" + } + async fetchInvoicesStatusSummary(): Promise<InvoiceStatusSummary> { const invoiceStatusPromise = await sql`SELECT SUM(CASE WHEN status = 'paid' THEN amount ELSE 0 END) AS "paid", diff --git a/src/feature/core/invoice/domain/i-repo/invoice-repo.ts b/src/feature/core/invoice/domain/i-repo/invoice-repo.ts index 90bac8f..983ac3f 100644 --- a/src/feature/core/invoice/domain/i-repo/invoice-repo.ts +++ b/src/feature/core/invoice/domain/i-repo/invoice-repo.ts @@ -1,8 +1,10 @@ +import { InvoiceParam } from "@/feature/core/invoice/domain/param/invoice-param" import InvoiceStatusSummary from "@/feature/core/invoice/domain/value-object/invoice-status" export default interface InvoiceRepo { fetchAllInvoicesAmount(): Promise<number> fetchInvoicesStatusSummary(): Promise<InvoiceStatusSummary> + createInvoice(params: InvoiceParam): Promise<string> } export const invoiceRepoKey = "invoiceRepoKey" \ No newline at end of file diff --git a/src/feature/core/invoice/domain/param/invoice-param.ts b/src/feature/core/invoice/domain/param/invoice-param.ts new file mode 100644 index 0000000..1dce62a --- /dev/null +++ b/src/feature/core/invoice/domain/param/invoice-param.ts @@ -0,0 +1,10 @@ +import { z } from "zod"; + +export const invoiceSchema = z.object({ + amount: z.coerce.number().gt(0, { message: 'Please enter an amount greater than $0.' }), + status: z.enum(['pending', 'paid'], { + invalid_type_error: 'Please select an invoice status.', + }), +}); + +export type InvoiceParam = z.infer<typeof invoiceSchema> \ No newline at end of file diff --git a/src/feature/core/invoice/domain/usecase/create-invoice-usecase.ts b/src/feature/core/invoice/domain/usecase/create-invoice-usecase.ts new file mode 100644 index 0000000..1b3ea6a --- /dev/null +++ b/src/feature/core/invoice/domain/usecase/create-invoice-usecase.ts @@ -0,0 +1,22 @@ +"use server" +import serverDi from "@/feature/common/server-di"; +import InvoiceRepo, { invoiceRepoKey } from "@/feature/core/invoice/domain/i-repo/invoice-repo"; +import { InvoiceParam, invoiceSchema } from "@/feature/core/invoice/domain/param/invoice-param"; +import { invoiceModuleKey } from "@/feature/core/invoice/invoice-module-key"; +import { revalidatePath } from "next/cache"; +import { redirect } from "next/navigation"; + +export default async function createInvoiceUsecase(params: InvoiceParam): Promise<string | {errorMessage: string}> { + const isParamsValid = invoiceSchema.safeParse(params) + + if (!isParamsValid) { + return { + errorMessage: "Please pass correct params" + } + } + const repo = serverDi(invoiceModuleKey).resolve<InvoiceRepo>(invoiceRepoKey) + + revalidatePath("/dashboard") + return repo.createInvoice(params) + +} \ No newline at end of file -- 2.39.5 From 324e7314e31f3203d2c73bfa5930b78493a9c326 Mon Sep 17 00:00:00 2001 From: behnam <behnamrahimpour74@gmail.com> Date: Sat, 2 Nov 2024 12:23:14 +0300 Subject: [PATCH 25/37] Add logic for loading handling with server action --- src/app/components/button/button-vm.ts | 3 +- src/app/components/button/button.tsx | 2 +- .../vm/create-random-invoice-button-vm.ts | 18 ++++++--- .../helpers/hooks/use-server-action.ts | 40 +++++++++++++++++++ .../core/invoice/data/repo/invoice-db-repo.ts | 2 +- .../domain/usecase/create-invoice-usecase.ts | 3 -- 6 files changed, 56 insertions(+), 12 deletions(-) create mode 100644 src/bootstrap/helpers/hooks/use-server-action.ts diff --git a/src/app/components/button/button-vm.ts b/src/app/components/button/button-vm.ts index f9e8754..ef0d7af 100644 --- a/src/app/components/button/button-vm.ts +++ b/src/app/components/button/button-vm.ts @@ -1,6 +1,7 @@ export default interface ButtonVm { props: { - title: string + title: string; + isDisable: boolean; } onClick(): void } \ No newline at end of file diff --git a/src/app/components/button/button.tsx b/src/app/components/button/button.tsx index 5245285..df0de5b 100644 --- a/src/app/components/button/button.tsx +++ b/src/app/components/button/button.tsx @@ -11,7 +11,7 @@ export default class Button extends BaseView<ButtonVm> { protected Build(props: BuildProps<ButtonVm>): ReactNode { const {vm} = props - return <ButtonUi onClick={vm.onClick} >{vm.props.title}</ButtonUi> + return <ButtonUi disabled={vm.props.isDisable} onClick={vm.onClick} >{vm.props.title}</ButtonUi> } } diff --git a/src/app/dashboard/vm/create-random-invoice-button-vm.ts b/src/app/dashboard/vm/create-random-invoice-button-vm.ts index 11a258e..c5ceb13 100644 --- a/src/app/dashboard/vm/create-random-invoice-button-vm.ts +++ b/src/app/dashboard/vm/create-random-invoice-button-vm.ts @@ -1,10 +1,11 @@ import ButtonVm from "@/app/components/button/button-vm"; +import { useServerAction } from "@/bootstrap/helpers/hooks/use-server-action"; import useThrottle from "@/bootstrap/helpers/hooks/use-throttle"; import BaseVM from "@/bootstrap/helpers/vm/base-vm"; import { InvoiceParam } from "@/feature/core/invoice/domain/param/invoice-param"; import createInvoiceUsecase from "@/feature/core/invoice/domain/usecase/create-invoice-usecase"; import { faker } from "@faker-js/faker"; - +import { useRouter } from "next/navigation"; export default class CreateRandomInvoiceButtonVM extends BaseVM<ButtonVm> { private createInvoice: typeof createInvoiceUsecase @@ -14,16 +15,20 @@ export default class CreateRandomInvoiceButtonVM extends BaseVM<ButtonVm> { } useVM(): ButtonVm { - const throttledOnClick = useThrottle(this.onClickHandler.bind(this), 5000) + const router = useRouter() + const [action, isPending] = useServerAction(() => this.onClickHandler(router.refresh)) + const throttledOnClick = useThrottle(action, 5000) + return { props: { - title: "Create Random Invoice" + title: isPending ? "Loading" : "Create Random Invoice", + isDisable: isPending ? true : false }, - onClick: throttledOnClick + onClick: throttledOnClick.bind(this) } } - onClickHandler() { + async onClickHandler(refreshPage: () => void) { const fakedParams: InvoiceParam = { amount: faker.number.int({ min: 1, @@ -31,6 +36,7 @@ export default class CreateRandomInvoiceButtonVM extends BaseVM<ButtonVm> { }), status: "paid" } - this.createInvoice(fakedParams) + await this.createInvoice(fakedParams) + refreshPage() } } \ No newline at end of file diff --git a/src/bootstrap/helpers/hooks/use-server-action.ts b/src/bootstrap/helpers/hooks/use-server-action.ts new file mode 100644 index 0000000..abb7516 --- /dev/null +++ b/src/bootstrap/helpers/hooks/use-server-action.ts @@ -0,0 +1,40 @@ +import { useState, useEffect, useTransition, useRef } from 'react'; + +/** + * + * @param action Main server action to run + * @param onFinished Callback to run after action + * @returns transitioned action to run and is pending variable +*/ +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export const useServerAction = <P extends any[], R>( + action: (...args: P) => Promise<R>, + onFinished?: (_: R | undefined) => void, +): [(...args: P) => Promise<R | undefined>, boolean] => { + const [isPending, startTransition] = useTransition(); + const [result, setResult] = useState<R>(); + const [finished, setFinished] = useState(false); + const resolver = useRef<(value?: R | PromiseLike<R>) => void>(); + + useEffect(() => { + if (!finished) return; + + if (onFinished) onFinished(result); + resolver.current?.(result); + }, [result, finished, onFinished]); + + const runAction = async (...args: P): Promise<R | undefined> => { + startTransition(() => { + action(...args).then((data) => { + setResult(data); + setFinished(true); + }); + }); + + return new Promise((resolve) => { + resolver.current = resolve; + }); + }; + + return [runAction, isPending]; +}; \ No newline at end of file diff --git a/src/feature/core/invoice/data/repo/invoice-db-repo.ts b/src/feature/core/invoice/data/repo/invoice-db-repo.ts index fd2219c..ea60b0f 100644 --- a/src/feature/core/invoice/data/repo/invoice-db-repo.ts +++ b/src/feature/core/invoice/data/repo/invoice-db-repo.ts @@ -16,7 +16,7 @@ export default class InvoiceDbRepo implements InvoiceRepo { async createInvoice(params: InvoiceParam): Promise<string> { const firstCustomerIdDb = await sql`SELECT id FROM customers - ORDER BY id ASC + ORDER BY id DESC LIMIT 1 ` const customerId = firstCustomerIdDb.at(0)?.id diff --git a/src/feature/core/invoice/domain/usecase/create-invoice-usecase.ts b/src/feature/core/invoice/domain/usecase/create-invoice-usecase.ts index 1b3ea6a..73a0106 100644 --- a/src/feature/core/invoice/domain/usecase/create-invoice-usecase.ts +++ b/src/feature/core/invoice/domain/usecase/create-invoice-usecase.ts @@ -3,8 +3,6 @@ import serverDi from "@/feature/common/server-di"; import InvoiceRepo, { invoiceRepoKey } from "@/feature/core/invoice/domain/i-repo/invoice-repo"; import { InvoiceParam, invoiceSchema } from "@/feature/core/invoice/domain/param/invoice-param"; import { invoiceModuleKey } from "@/feature/core/invoice/invoice-module-key"; -import { revalidatePath } from "next/cache"; -import { redirect } from "next/navigation"; export default async function createInvoiceUsecase(params: InvoiceParam): Promise<string | {errorMessage: string}> { const isParamsValid = invoiceSchema.safeParse(params) @@ -16,7 +14,6 @@ export default async function createInvoiceUsecase(params: InvoiceParam): Promis } const repo = serverDi(invoiceModuleKey).resolve<InvoiceRepo>(invoiceRepoKey) - revalidatePath("/dashboard") return repo.createInvoice(params) } \ No newline at end of file -- 2.39.5 From 0c70c66cf26be96f7ee8c45f280c267553d216ec Mon Sep 17 00:00:00 2001 From: behnam <behnamrahimpour74@gmail.com> Date: Sat, 2 Nov 2024 12:44:40 +0300 Subject: [PATCH 26/37] Remove unused domain --- src/app/test/client/view/parent-view.tsx | 13 ------- src/app/test/client/vm/test-button-vm.ts | 34 ------------------- src/app/test/layout.tsx | 10 ------ src/app/test/modules/test-app-module.ts | 13 ------- src/app/test/page.tsx | 5 --- src/feature/common/server-di.ts | 3 -- .../service/test-get-button-title-service.ts | 9 ----- .../domain/test/service/test-service-repo.ts | 5 --- src/feature/domain/test/test-module-key.ts | 1 - src/feature/infra/test/module/test-module.ts | 12 ------- src/feature/infra/test/repo/test-repo-iml.ts | 14 -------- 11 files changed, 119 deletions(-) delete mode 100644 src/app/test/client/view/parent-view.tsx delete mode 100644 src/app/test/client/vm/test-button-vm.ts delete mode 100644 src/app/test/layout.tsx delete mode 100644 src/app/test/modules/test-app-module.ts delete mode 100644 src/app/test/page.tsx delete mode 100644 src/feature/domain/test/service/test-get-button-title-service.ts delete mode 100644 src/feature/domain/test/service/test-service-repo.ts delete mode 100644 src/feature/domain/test/test-module-key.ts delete mode 100644 src/feature/infra/test/module/test-module.ts delete mode 100644 src/feature/infra/test/repo/test-repo-iml.ts diff --git a/src/app/test/client/view/parent-view.tsx b/src/app/test/client/view/parent-view.tsx deleted file mode 100644 index 81de26a..0000000 --- a/src/app/test/client/view/parent-view.tsx +++ /dev/null @@ -1,13 +0,0 @@ -"use client" -import Button from "@/app/components/button/button" -import { TestButtonVM } from "@/app/test/client/vm/test-button-vm" -import { useDI } from "@/bootstrap/di/di-context" -import { useRef } from "react" - -export default function ParentView() { - const di = useDI() - - const vmRef = useRef(di.resolve(TestButtonVM)) - - return <Button vm={vmRef.current} /> -} \ No newline at end of file diff --git a/src/app/test/client/vm/test-button-vm.ts b/src/app/test/client/vm/test-button-vm.ts deleted file mode 100644 index 1a74c04..0000000 --- a/src/app/test/client/vm/test-button-vm.ts +++ /dev/null @@ -1,34 +0,0 @@ -"use client" -import BaseVM from "@/bootstrap/helpers/vm/base-vm"; -import ButtonVm from "@/app/components/button/button-vm"; -import { useEffect, useState } from "react"; -import getButtonTitle from "@/feature/domain/test/service/test-get-button-title-service"; - -export class TestButtonVM extends BaseVM<ButtonVm> { - private getButtonTitle: () => Promise<string> - - constructor() { - super() - this.getButtonTitle = this.di.resolve(getButtonTitle.name) - } - - useVM(): ButtonVm { - const [ buttonTitle, setTitle ] = useState("Default title") - useEffect(() => { - (async () => { - const title = await this.getButtonTitle() - setTitle(title) - })() - }, []) - return { - props: { - title: buttonTitle - }, - onClick: () => { - console.log("clicked on the button"); - } - } - } -} - -export const testKey = "testKey" \ No newline at end of file diff --git a/src/app/test/layout.tsx b/src/app/test/layout.tsx deleted file mode 100644 index 173e5ca..0000000 --- a/src/app/test/layout.tsx +++ /dev/null @@ -1,10 +0,0 @@ -"use client" -import testAppModule from "@/app/test/modules/test-app-module"; -import { DiContext } from "@/bootstrap/di/di-context"; -import { PropsWithChildren, useRef } from "react"; - -export default function WithDILayout(props: PropsWithChildren) { - const testDi = useRef(testAppModule()) - return <DiContext.Provider value={testDi.current}>{props.children}</DiContext.Provider> -} - diff --git a/src/app/test/modules/test-app-module.ts b/src/app/test/modules/test-app-module.ts deleted file mode 100644 index 7f4d702..0000000 --- a/src/app/test/modules/test-app-module.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { TestButtonVM, testKey } from "@/app/test/client/vm/test-button-vm"; -import di from "@/bootstrap/di/init-di" -import getButtonTitle from "@/feature/domain/test/service/test-get-button-title-service"; - -export default function testAppModule() { - const testDi = di.createChildContainer() - - testDi.registerInstance(testKey, TestButtonVM); - testDi.register(getButtonTitle.name, { - useValue: getButtonTitle - }) - return testDi -} diff --git a/src/app/test/page.tsx b/src/app/test/page.tsx deleted file mode 100644 index fb067fd..0000000 --- a/src/app/test/page.tsx +++ /dev/null @@ -1,5 +0,0 @@ -import ParentView from "@/app/test/client/view/parent-view"; - -export default function Page() { - return <ParentView /> -} \ No newline at end of file diff --git a/src/feature/common/server-di.ts b/src/feature/common/server-di.ts index 401e706..cec83f7 100644 --- a/src/feature/common/server-di.ts +++ b/src/feature/common/server-di.ts @@ -2,8 +2,6 @@ import getCustomerInvoiceDi from "@/feature/core/customer-invoice/data/module/cu import { customerInvoiceModuleKey } from "@/feature/core/customer-invoice/invoice-module-key"; import { customerKey } from "@/feature/core/customer/customer-key"; import getCustomerDi from "@/feature/core/customer/data/module/customer-di"; -import { testModuleKey } from "@/feature/domain/test/test-module-key"; -import getTestModule from "@/feature/infra/test/module/test-module"; import getInvoiceDi from "@/feature/core/invoice/data/module/invoice-di"; import { invoiceModuleKey } from "@/feature/core/invoice/invoice-module-key"; import { DependencyContainer } from "tsyringe"; @@ -17,7 +15,6 @@ const memoizedDis: Record<string, DependencyContainer> = {} export default function serverDi(module: string): DependencyContainer { if (memoizedDis[module]) return memoizedDis[module] const getDi = { - [testModuleKey]: getTestModule, [customerKey]: getCustomerDi, [customerInvoiceModuleKey]: getCustomerInvoiceDi, [invoiceModuleKey]: getInvoiceDi, diff --git a/src/feature/domain/test/service/test-get-button-title-service.ts b/src/feature/domain/test/service/test-get-button-title-service.ts deleted file mode 100644 index c9a4910..0000000 --- a/src/feature/domain/test/service/test-get-button-title-service.ts +++ /dev/null @@ -1,9 +0,0 @@ -"use server" -import serverDi from "@/feature/common/server-di"; -import TestRepo, { testRepoKey } from "@/feature/domain/test/service/test-service-repo" -import { testModuleKey } from "@/feature/domain/test/test-module-key"; - -export default async function getButtonTitle() { - const repo = serverDi(testModuleKey).resolve<TestRepo>(testRepoKey) - return repo.getButtonTitle() -} diff --git a/src/feature/domain/test/service/test-service-repo.ts b/src/feature/domain/test/service/test-service-repo.ts deleted file mode 100644 index 91e00f8..0000000 --- a/src/feature/domain/test/service/test-service-repo.ts +++ /dev/null @@ -1,5 +0,0 @@ -export default interface TestRepo { - getButtonTitle(): Promise<string> -} - -export const testRepoKey = "restRepoKey" \ No newline at end of file diff --git a/src/feature/domain/test/test-module-key.ts b/src/feature/domain/test/test-module-key.ts deleted file mode 100644 index abb15e6..0000000 --- a/src/feature/domain/test/test-module-key.ts +++ /dev/null @@ -1 +0,0 @@ -export const testModuleKey = "testModuleKey" \ No newline at end of file diff --git a/src/feature/infra/test/module/test-module.ts b/src/feature/infra/test/module/test-module.ts deleted file mode 100644 index d8963b8..0000000 --- a/src/feature/infra/test/module/test-module.ts +++ /dev/null @@ -1,12 +0,0 @@ -import di from "@/bootstrap/di/init-di" -import { testRepoKey } from "@/feature/domain/test/service/test-service-repo" -import TestRepoImpl from "@/feature/infra/test/repo/test-repo-iml" - -export default function getTestModule() { - const testDi = di.createChildContainer() - - di.register(testRepoKey, { - useClass: TestRepoImpl - }) - return testDi -} \ No newline at end of file diff --git a/src/feature/infra/test/repo/test-repo-iml.ts b/src/feature/infra/test/repo/test-repo-iml.ts deleted file mode 100644 index f519bee..0000000 --- a/src/feature/infra/test/repo/test-repo-iml.ts +++ /dev/null @@ -1,14 +0,0 @@ -import TestRepo from "@/feature/domain/test/service/test-service-repo"; - -export default class TestRepoImpl implements TestRepo { - async getButtonTitle(): Promise<string> { - await new Promise((res) => { - setTimeout(() => { - res(true) - }, 3000) - }) - console.log('hereee'); - return Promise.resolve("Button title") - } - -} \ No newline at end of file -- 2.39.5 From 26833e18185944235825ba678aa5288558caf13d Mon Sep 17 00:00:00 2001 From: behnam <behnamrahimpour74@gmail.com> Date: Sat, 2 Nov 2024 12:50:33 +0300 Subject: [PATCH 27/37] Fix location of db to boundaries --- package.json | 2 +- src/bootstrap/{ => boundaries}/db/db.ts | 2 +- src/bootstrap/{ => boundaries}/db/placeholder-data.js | 0 src/bootstrap/{ => boundaries}/db/seed.js | 0 src/bootstrap/helpers/lib/actions.ts | 2 +- .../core/customer-invoice/data/repo/customer-invoice-db-repo.ts | 2 +- src/feature/core/customer/data/repo/customer-db-repo.ts | 2 +- src/feature/core/invoice/data/repo/invoice-db-repo.ts | 2 +- src/feature/core/revenue/data/repo/revenue-db-repo.ts | 2 +- tsconfig.json | 2 +- 10 files changed, 8 insertions(+), 8 deletions(-) rename src/bootstrap/{ => boundaries}/db/db.ts (86%) rename src/bootstrap/{ => boundaries}/db/placeholder-data.js (100%) rename src/bootstrap/{ => boundaries}/db/seed.js (100%) diff --git a/package.json b/package.json index 62211ce..8691324 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,7 @@ "start": "next start --port 4000", "lint": "next lint", "test": "vitest", - "seed": "node -r dotenv/config ./src/bootstrap/db/seed.js" + "seed": "node -r dotenv/config ./src/bootstrap/boundaries/db/seed.js" }, "dependencies": { "@heroicons/react": "^2.1.5", diff --git a/src/bootstrap/db/db.ts b/src/bootstrap/boundaries/db/db.ts similarity index 86% rename from src/bootstrap/db/db.ts rename to src/bootstrap/boundaries/db/db.ts index dbcd877..d6962af 100644 --- a/src/bootstrap/db/db.ts +++ b/src/bootstrap/boundaries/db/db.ts @@ -10,4 +10,4 @@ const dbConfigs = { database: envs.POSTGRES_DB, } -export const sql = postgres(dbConfigs); \ No newline at end of file +export const sql = postgres(dbConfigs); diff --git a/src/bootstrap/db/placeholder-data.js b/src/bootstrap/boundaries/db/placeholder-data.js similarity index 100% rename from src/bootstrap/db/placeholder-data.js rename to src/bootstrap/boundaries/db/placeholder-data.js diff --git a/src/bootstrap/db/seed.js b/src/bootstrap/boundaries/db/seed.js similarity index 100% rename from src/bootstrap/db/seed.js rename to src/bootstrap/boundaries/db/seed.js diff --git a/src/bootstrap/helpers/lib/actions.ts b/src/bootstrap/helpers/lib/actions.ts index 617b4d7..a408241 100644 --- a/src/bootstrap/helpers/lib/actions.ts +++ b/src/bootstrap/helpers/lib/actions.ts @@ -3,7 +3,7 @@ import { z } from 'zod'; import { revalidatePath } from 'next/cache'; import { redirect } from 'next/navigation'; -import { sql } from '@/bootstrap/db/db'; +import { sql } from '@/bootstrap/boundaries/db/db'; const FormSchema = z.object({ id: z.string(), diff --git a/src/feature/core/customer-invoice/data/repo/customer-invoice-db-repo.ts b/src/feature/core/customer-invoice/data/repo/customer-invoice-db-repo.ts index 9c19809..a12de93 100644 --- a/src/feature/core/customer-invoice/data/repo/customer-invoice-db-repo.ts +++ b/src/feature/core/customer-invoice/data/repo/customer-invoice-db-repo.ts @@ -1,4 +1,4 @@ -import { sql } from "@/bootstrap/db/db"; +import { sql } from "@/bootstrap/boundaries/db/db"; import { formatCurrency } from "@/feature/common/feature-helpers"; import CustomerInvoice from "@/feature/core/customer-invoice/domain/entity/customer-invoice"; import CustomerInvoiceRepo from "@/feature/core/customer-invoice/domain/i-repo/customer-invoice-repo"; diff --git a/src/feature/core/customer/data/repo/customer-db-repo.ts b/src/feature/core/customer/data/repo/customer-db-repo.ts index f1239a4..8c6fba4 100644 --- a/src/feature/core/customer/data/repo/customer-db-repo.ts +++ b/src/feature/core/customer/data/repo/customer-db-repo.ts @@ -1,4 +1,4 @@ -import { sql } from "@/bootstrap/db/db"; +import { sql } from "@/bootstrap/boundaries/db/db"; import { formatCurrency } from "@/feature/common/feature-helpers"; import Customer from "@/feature/core/customer/domain/entity/customer"; import CustomerRepo from "@/feature/core/customer/domain/i-repo/customer-repo"; diff --git a/src/feature/core/invoice/data/repo/invoice-db-repo.ts b/src/feature/core/invoice/data/repo/invoice-db-repo.ts index ea60b0f..c8e2bb9 100644 --- a/src/feature/core/invoice/data/repo/invoice-db-repo.ts +++ b/src/feature/core/invoice/data/repo/invoice-db-repo.ts @@ -1,4 +1,4 @@ -import { sql } from "@/bootstrap/db/db"; +import { sql } from "@/bootstrap/boundaries/db/db"; import { formatCurrency } from "@/feature/common/feature-helpers"; import InvoiceRepo from "@/feature/core/invoice/domain/i-repo/invoice-repo"; import { InvoiceParam } from "@/feature/core/invoice/domain/param/invoice-param"; diff --git a/src/feature/core/revenue/data/repo/revenue-db-repo.ts b/src/feature/core/revenue/data/repo/revenue-db-repo.ts index 92ac993..d8d771d 100644 --- a/src/feature/core/revenue/data/repo/revenue-db-repo.ts +++ b/src/feature/core/revenue/data/repo/revenue-db-repo.ts @@ -1,4 +1,4 @@ -import { sql } from "@/bootstrap/db/db"; +import { sql } from "@/bootstrap/boundaries/db/db"; import Revenue from "@/feature/core/revenue/domain/entity/revenue"; import RevenueRepo from "@/feature/core/revenue/domain/i-repo/revenue-repo"; import { connection } from "next/server"; diff --git a/tsconfig.json b/tsconfig.json index ef29509..0d0b9fb 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -25,6 +25,6 @@ "@/*": ["./src/*"] } }, - "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts", "src/bootstrap/db/seed.js", "src/bootstrap/db/placeholder-data.js"], + "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts", "src/bootstrap/boundaries/db/seed.js", "src/bootstrap/boundaries/db/placeholder-data.js"], "exclude": ["node_modules"] } -- 2.39.5 From 4c4b00c51fb4d4a180aa4ea02bd89362760275c1 Mon Sep 17 00:00:00 2001 From: behnam <behnamrahimpour74@gmail.com> Date: Sat, 2 Nov 2024 13:10:17 +0300 Subject: [PATCH 28/37] Add tools for failure handling --- package.json | 1 + src/feature/common/data/api-task.ts | 8 ++ src/feature/common/failures/base-failure.ts | 22 +++++ .../common/failures/dev/arguments-failure.ts | 12 +++ .../common/failures/dev/base-dev-failure.ts | 3 + .../common/failures/dev/dependency-failure.ts | 10 ++ .../common/failures/failure-helpers.ts | 95 +++++++++++++++++++ .../common/failures/network-failure.ts | 12 +++ yarn.lock | 5 + 9 files changed, 168 insertions(+) create mode 100644 src/feature/common/data/api-task.ts create mode 100644 src/feature/common/failures/base-failure.ts create mode 100644 src/feature/common/failures/dev/arguments-failure.ts create mode 100644 src/feature/common/failures/dev/base-dev-failure.ts create mode 100644 src/feature/common/failures/dev/dependency-failure.ts create mode 100644 src/feature/common/failures/failure-helpers.ts create mode 100644 src/feature/common/failures/network-failure.ts diff --git a/package.json b/package.json index 8691324..6fd58e3 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,7 @@ "@radix-ui/react-slot": "^1.1.0", "class-variance-authority": "^0.7.0", "clsx": "^2.1.1", + "fp-ts": "^2.16.9", "lucide-react": "^0.454.0", "next": "15.0.2", "postgres": "^3.4.5", diff --git a/src/feature/common/data/api-task.ts b/src/feature/common/data/api-task.ts new file mode 100644 index 0000000..f234898 --- /dev/null +++ b/src/feature/common/data/api-task.ts @@ -0,0 +1,8 @@ +import { Either } from "fp-ts/lib/Either"; +import { TaskEither } from "fp-ts/lib/TaskEither"; +import BaseFailure from "@/feature/common/failures/base-failure"; + +type ApiTask<ResponseType> = TaskEither<BaseFailure, ResponseType>; +export type ApiEither<ResponseType> = Either<BaseFailure, ResponseType>; + +export default ApiTask; diff --git a/src/feature/common/failures/base-failure.ts b/src/feature/common/failures/base-failure.ts new file mode 100644 index 0000000..bc09402 --- /dev/null +++ b/src/feature/common/failures/base-failure.ts @@ -0,0 +1,22 @@ +import { makeFailureMessage } from "@/feature/common/failures/failure-helpers"; + +/** + * This is a class called BaseFailure that extends the Error class. It is + * used as a base class for creating custom failure classes. + */ +export default abstract class BaseFailure { + /* ------------------------------- Attributes ------------------------------- */ + private readonly BASE_FAILURE_MESSAGE = "failure"; + + /* -------------------------------------------------------------------------- */ + /** + * Use this message as key lang for failure messages + */ + message = this.BASE_FAILURE_MESSAGE; + + /* -------------------------------------------------------------------------- */ + constructor(key: string) { + this.message = makeFailureMessage(this.message, key); + } + /* -------------------------------------------------------------------------- */ +} diff --git a/src/feature/common/failures/dev/arguments-failure.ts b/src/feature/common/failures/dev/arguments-failure.ts new file mode 100644 index 0000000..ed4e2c9 --- /dev/null +++ b/src/feature/common/failures/dev/arguments-failure.ts @@ -0,0 +1,12 @@ +import BaseDevFailure from "@/feature/common/failures/dev/base-dev-failure"; + +/** + * Failure for needed arguments in a method but sent wrong one + */ +export default class ArgumentsFailure extends BaseDevFailure { + /* ------------------------------- Constructor ------------------------------ */ + constructor() { + super("arguments"); + } + /* -------------------------------------------------------------------------- */ +} diff --git a/src/feature/common/failures/dev/base-dev-failure.ts b/src/feature/common/failures/dev/base-dev-failure.ts new file mode 100644 index 0000000..aaf8142 --- /dev/null +++ b/src/feature/common/failures/dev/base-dev-failure.ts @@ -0,0 +1,3 @@ +import BaseFailure from "@/feature/common/failures/base-failure"; + +export default abstract class BaseDevFailure extends BaseFailure {} diff --git a/src/feature/common/failures/dev/dependency-failure.ts b/src/feature/common/failures/dev/dependency-failure.ts new file mode 100644 index 0000000..86b49cf --- /dev/null +++ b/src/feature/common/failures/dev/dependency-failure.ts @@ -0,0 +1,10 @@ +import BaseDevFailure from "@/feature/common/failures/dev/base-dev-failure"; + +/** + * This is a failure of not having specific dependency + */ +export default class DependencyFailure extends BaseDevFailure { + constructor() { + super("DependencyFailure"); + } +} diff --git a/src/feature/common/failures/failure-helpers.ts b/src/feature/common/failures/failure-helpers.ts new file mode 100644 index 0000000..a6c8f46 --- /dev/null +++ b/src/feature/common/failures/failure-helpers.ts @@ -0,0 +1,95 @@ +import BaseFailure from "@/feature/common/failures/base-failure"; + +/** + * This method is supposed to save previous failure of TaskEither + * to prevent it from loosing and overriding by the new one. + * + * Usage example: + * ```ts + * tryCatch( + * async () => { + * ... + * throw ValidationFailure(); + * ... + * }, + * (reason) => failureOr(reason, new UserCreationFailure()), + * ) + * ``` + * In this example `failureOr` will return already throwed + * instance of `BaseFailure` which is `ValidationFailure`. + * + * + * @param reason is throwed object. + * Basically it can be default `Error` or instance of `BaseFailure`. + * @param failure instance of `BaseFailure` that will be returned + * if reason is not instance of `BaseFailure`. + * @returns `BaseFailure` + */ +export function failureOr(reason: unknown, failure: BaseFailure): BaseFailure { + if (reason instanceof BaseFailure) { + return reason; + } + return failure; +} + +/** + * Returns a function that maps a BaseFailure instance to a new BaseFailure instance of type IfType using the provided mapping function. + * @param f A function that maps an instance of IfType to a new instance of BaseFailure. + * @param ctor A constructor function for IfType. + * @returns A function that maps a BaseFailure instance to a new BaseFailure instance of type IfType. + */ +export function mapToFailureFrom<IfType extends BaseFailure>( + f: (t: IfType) => BaseFailure, + ctor: new (...args: never[]) => IfType, +): (t: BaseFailure) => BaseFailure { + return mapIfInstance<IfType, BaseFailure>(f, ctor); +} + +/** + * Maps an instance of a class to a response using a provided function. + * + * @template IfType - The type of the instance to map. + * @template Response - The type of the response to map to. + * @param {function} f - The function to use to map the instance to a response. + * @param {new (...args: never[]) => IfType} ctor - The constructor function of the instance to map. + * @returns {(t: IfType | Response) => IfType | Response} - A function that maps the instance to a response using the provided function. + */ +export function mapIfInstance<IfType, Response>( + f: (t: IfType) => Response, + ctor: new (...args: never[]) => IfType, +) { + return (t: IfType | Response) => { + if (t instanceof ctor) { + return f(t); + } + return t; + }; +} + +/** + * Maps a function to a value if it is not an instance of a given class. + * @template IfType The type of the value to be mapped. + * @template Response The type of the mapped value. + * @param {function} f The function to map the value with. + * @param {new (...args: never[]) => IfType} ctor The class to check the value against. + * @returns {function} A function that maps the value if it is not an instance of the given class. + */ +export function mapIfNotInstance<IfType, Response>( + f: (t: IfType) => Response, + ctor: new (...args: never[]) => IfType, +) { + return (t: IfType | Response) => { + if (t! instanceof ctor) { + return f(t); + } + return t; + }; +} + +/** + * Gets Message key and it'll add it to the failure message key hierarchy + */ +export function makeFailureMessage(message: string, key: string) { + if (!key) return message; + return `${message}.${key}`; +} diff --git a/src/feature/common/failures/network-failure.ts b/src/feature/common/failures/network-failure.ts new file mode 100644 index 0000000..3268fc3 --- /dev/null +++ b/src/feature/common/failures/network-failure.ts @@ -0,0 +1,12 @@ +import BaseFailure from "./base-failure"; + +/** + * Failure for HTTP response when response dosn't have base structure + */ +export default class NetworkFailure extends BaseFailure { + /* ------------------------------- Constructor ------------------------------ */ + constructor() { + super("network"); + } + /* -------------------------------------------------------------------------- */ +} diff --git a/yarn.lock b/yarn.lock index 6d7dde4..194f43b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2125,6 +2125,11 @@ form-data@^4.0.0: combined-stream "^1.0.8" mime-types "^2.1.12" +fp-ts@^2.16.9: + version "2.16.9" + resolved "https://registry.yarnpkg.com/fp-ts/-/fp-ts-2.16.9.tgz#99628fc5e0bb3b432c4a16d8f4455247380bae8a" + integrity sha512-+I2+FnVB+tVaxcYyQkHUq7ZdKScaBlX53A41mxQtpIccsfyv8PzdzP7fzp2AY832T4aoK6UZ5WRX/ebGd8uZuQ== + fs-minipass@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb" -- 2.39.5 From 7046c5adc99ecf90a0ae89e1e4cdeae35a8a74fb Mon Sep 17 00:00:00 2001 From: behnam <behnamrahimpour74@gmail.com> Date: Sat, 2 Nov 2024 14:57:23 +0300 Subject: [PATCH 29/37] Add demo logics for using fp-ts in feature layer --- .../latest-invoices-controller.ts | 4 +- .../latest-invoices/latest-invoices.tsx | 5 ++- src/feature/common/failures/params-failure.ts | 12 ++++++ .../data/repo/customer-invoice-db-repo.ts | 37 +++++++++++-------- .../domain/i-repo/customer-invoice-repo.ts | 3 +- .../fetch-customer-invoices-usecase.ts | 6 +-- .../customer/domain/i-repo/customer-repo.ts | 3 +- .../invoice/domain/i-repo/invoice-repo.ts | 3 +- .../domain/usecase/create-invoice-usecase.ts | 25 ++++++++----- 9 files changed, 64 insertions(+), 34 deletions(-) create mode 100644 src/feature/common/failures/params-failure.ts diff --git a/src/app/dashboard/components/server/latest-invoices/latest-invoices-controller.ts b/src/app/dashboard/components/server/latest-invoices/latest-invoices-controller.ts index 45bde22..8fbbde9 100644 --- a/src/app/dashboard/components/server/latest-invoices/latest-invoices-controller.ts +++ b/src/app/dashboard/components/server/latest-invoices/latest-invoices-controller.ts @@ -1,5 +1,5 @@ import fetchCustomerInvoicesUsecase from "@/feature/core/customer-invoice/domain/usecase/fetch-customer-invoices-usecase"; -export default function latestInvoicesController() { - return fetchCustomerInvoicesUsecase() +export default async function latestInvoicesController() { + return await fetchCustomerInvoicesUsecase() } \ No newline at end of file diff --git a/src/app/dashboard/components/server/latest-invoices/latest-invoices.tsx b/src/app/dashboard/components/server/latest-invoices/latest-invoices.tsx index 09396cd..696af73 100644 --- a/src/app/dashboard/components/server/latest-invoices/latest-invoices.tsx +++ b/src/app/dashboard/components/server/latest-invoices/latest-invoices.tsx @@ -2,12 +2,15 @@ import CreateRandomInvoiceContainer from '@/app/dashboard/components/client/crea import latestInvoicesController from '@/app/dashboard/components/server/latest-invoices/latest-invoices-controller'; import { ArrowPathIcon } from '@heroicons/react/24/outline'; import clsx from 'clsx'; +import { isLeft } from 'fp-ts/lib/Either'; import Image from 'next/image'; export default async function LatestInvoices() { const latestInvoices = await latestInvoicesController(); - const invoices = latestInvoices.map((invoice, i) => { + if (isLeft(latestInvoices)) return <div>Error</div> + + const invoices = latestInvoices.right.map((invoice, i) => { return ( <div key={invoice.id} diff --git a/src/feature/common/failures/params-failure.ts b/src/feature/common/failures/params-failure.ts new file mode 100644 index 0000000..4849027 --- /dev/null +++ b/src/feature/common/failures/params-failure.ts @@ -0,0 +1,12 @@ +import BaseFailure from "./base-failure"; + +/** + * Failure for params failure + */ +export default class ParamsFailure extends BaseFailure { + /* ------------------------------- Constructor ------------------------------ */ + constructor() { + super("params"); + } + /* -------------------------------------------------------------------------- */ +} diff --git a/src/feature/core/customer-invoice/data/repo/customer-invoice-db-repo.ts b/src/feature/core/customer-invoice/data/repo/customer-invoice-db-repo.ts index a12de93..db036b8 100644 --- a/src/feature/core/customer-invoice/data/repo/customer-invoice-db-repo.ts +++ b/src/feature/core/customer-invoice/data/repo/customer-invoice-db-repo.ts @@ -1,7 +1,12 @@ import { sql } from "@/bootstrap/boundaries/db/db"; +import ApiTask from "@/feature/common/data/api-task"; +import { failureOr } from "@/feature/common/failures/failure-helpers"; +import NetworkFailure from "@/feature/common/failures/network-failure"; import { formatCurrency } from "@/feature/common/feature-helpers"; import CustomerInvoice from "@/feature/core/customer-invoice/domain/entity/customer-invoice"; import CustomerInvoiceRepo from "@/feature/core/customer-invoice/domain/i-repo/customer-invoice-repo"; +import { pipe } from "fp-ts/lib/function"; +import { tryCatch } from "fp-ts/lib/TaskEither"; import postgres from "postgres"; type customerInvoiceDbResponse = { @@ -13,23 +18,25 @@ type customerInvoiceDbResponse = { } export default class CustomerInvoiceDbRepo implements CustomerInvoiceRepo { - async fetchList(): Promise<CustomerInvoice[]> { - try { - const data = await sql` - SELECT invoices.amount, customers.name, customers.image_url, customers.email, invoices.id - FROM invoices - JOIN customers ON invoices.customer_id = customers.id - ORDER BY invoices.date DESC - LIMIT 20 ` as postgres.RowList<customerInvoiceDbResponse[]>; - - return this.customerInvoicesDto(data) - } catch (error) { - console.error('Database Error:', error); - throw new Error('Failed to fetch the latest invoices.'); - } + fetchList(): ApiTask<CustomerInvoice[]> { + + return pipe( + tryCatch( + async () => { + const response = await sql` + SELECT invoices.amount, customers.name, customers.image_url, customers.email, invoices.id + FROM invoices + JOIN customers ON invoices.customer_id = customers.id + ORDER BY invoices.date DESC + LIMIT 20 ` as postgres.RowList<customerInvoiceDbResponse[]>; + + return this.customerInvoicesDto(response) + }, + (l) => failureOr(l, new NetworkFailure()) + ) + ) } - private customerInvoicesDto(dbCustomers: customerInvoiceDbResponse[]): CustomerInvoice[] { return dbCustomers.map((customer) => this.customerInvoiceDto(customer)); } diff --git a/src/feature/core/customer-invoice/domain/i-repo/customer-invoice-repo.ts b/src/feature/core/customer-invoice/domain/i-repo/customer-invoice-repo.ts index 0a8c993..ab4b486 100644 --- a/src/feature/core/customer-invoice/domain/i-repo/customer-invoice-repo.ts +++ b/src/feature/core/customer-invoice/domain/i-repo/customer-invoice-repo.ts @@ -1,7 +1,8 @@ +import ApiTask from "@/feature/common/data/api-task" import CustomerInvoice from "@/feature/core/customer-invoice/domain/entity/customer-invoice" export default interface CustomerInvoiceRepo { - fetchList(): Promise<CustomerInvoice[]> + fetchList(): ApiTask<CustomerInvoice[]> } export const customerInvoiceRepoKey = "customerInvoiceRepoKey" \ No newline at end of file diff --git a/src/feature/core/customer-invoice/domain/usecase/fetch-customer-invoices-usecase.ts b/src/feature/core/customer-invoice/domain/usecase/fetch-customer-invoices-usecase.ts index 5947553..5d2df55 100644 --- a/src/feature/core/customer-invoice/domain/usecase/fetch-customer-invoices-usecase.ts +++ b/src/feature/core/customer-invoice/domain/usecase/fetch-customer-invoices-usecase.ts @@ -1,12 +1,12 @@ -"use server" +import { ApiEither } from "@/feature/common/data/api-task"; import serverDi from "@/feature/common/server-di"; import CustomerInvoice from "@/feature/core/customer-invoice/domain/entity/customer-invoice"; import CustomerInvoiceRepo, { customerInvoiceRepoKey } from "@/feature/core/customer-invoice/domain/i-repo/customer-invoice-repo"; import { customerInvoiceModuleKey } from "@/feature/core/customer-invoice/invoice-module-key"; import { connection } from "next/server"; -export default async function fetchCustomerInvoicesUsecase(): Promise<CustomerInvoice[]> { +export default async function fetchCustomerInvoicesUsecase(): Promise<ApiEither<CustomerInvoice[]>> { connection() const repo = serverDi(customerInvoiceModuleKey).resolve<CustomerInvoiceRepo>(customerInvoiceRepoKey) - return repo.fetchList() + return repo.fetchList()() } \ No newline at end of file diff --git a/src/feature/core/customer/domain/i-repo/customer-repo.ts b/src/feature/core/customer/domain/i-repo/customer-repo.ts index d48fdde..86b890e 100644 --- a/src/feature/core/customer/domain/i-repo/customer-repo.ts +++ b/src/feature/core/customer/domain/i-repo/customer-repo.ts @@ -1,7 +1,8 @@ +import ApiTask from "@/feature/common/data/api-task" import Customer from "@/feature/core/customer/domain/entity/customer" export default interface CustomerRepo { - fetchList(query: string): Promise<Customer[]> + fetchList(query: string): ApiTask<Customer[]> fetchCustomersAmount(): Promise<number> } diff --git a/src/feature/core/invoice/domain/i-repo/invoice-repo.ts b/src/feature/core/invoice/domain/i-repo/invoice-repo.ts index 983ac3f..ca5096d 100644 --- a/src/feature/core/invoice/domain/i-repo/invoice-repo.ts +++ b/src/feature/core/invoice/domain/i-repo/invoice-repo.ts @@ -1,10 +1,11 @@ +import ApiTask from "@/feature/common/data/api-task" import { InvoiceParam } from "@/feature/core/invoice/domain/param/invoice-param" import InvoiceStatusSummary from "@/feature/core/invoice/domain/value-object/invoice-status" export default interface InvoiceRepo { fetchAllInvoicesAmount(): Promise<number> fetchInvoicesStatusSummary(): Promise<InvoiceStatusSummary> - createInvoice(params: InvoiceParam): Promise<string> + createInvoice(params: InvoiceParam): ApiTask<string> } export const invoiceRepoKey = "invoiceRepoKey" \ No newline at end of file diff --git a/src/feature/core/invoice/domain/usecase/create-invoice-usecase.ts b/src/feature/core/invoice/domain/usecase/create-invoice-usecase.ts index 73a0106..9cfc63d 100644 --- a/src/feature/core/invoice/domain/usecase/create-invoice-usecase.ts +++ b/src/feature/core/invoice/domain/usecase/create-invoice-usecase.ts @@ -1,19 +1,24 @@ "use server" +import { ApiEither } from "@/feature/common/data/api-task"; +import ParamsFailure from "@/feature/common/failures/params-failure"; import serverDi from "@/feature/common/server-di"; import InvoiceRepo, { invoiceRepoKey } from "@/feature/core/invoice/domain/i-repo/invoice-repo"; import { InvoiceParam, invoiceSchema } from "@/feature/core/invoice/domain/param/invoice-param"; import { invoiceModuleKey } from "@/feature/core/invoice/invoice-module-key"; +import { pipe } from "fp-ts/lib/function"; +import { chain, fromNullable, left, map, right } from "fp-ts/lib/TaskEither"; -export default async function createInvoiceUsecase(params: InvoiceParam): Promise<string | {errorMessage: string}> { - const isParamsValid = invoiceSchema.safeParse(params) - - if (!isParamsValid) { - return { - errorMessage: "Please pass correct params" - } - } +export default async function createInvoiceUsecase(params: InvoiceParam): Promise<ApiEither<string>> { const repo = serverDi(invoiceModuleKey).resolve<InvoiceRepo>(invoiceRepoKey) - return repo.createInvoice(params) - + return pipe( + fromNullable(new ParamsFailure())(params), + map((params) => invoiceSchema.safeParse(params)), + chain((params) => { + const isParamsValid = invoiceSchema.safeParse(params) + if (!isParamsValid.success) left(new ParamsFailure()) + return right(params.data as InvoiceParam) + }), + chain((params) => repo.createInvoice(params)) + )() } \ No newline at end of file -- 2.39.5 From 6f54fa0c67c4a124c383ff590b10d70e74350409 Mon Sep 17 00:00:00 2001 From: behnam <behnamrahimpour74@gmail.com> Date: Sat, 2 Nov 2024 14:57:23 +0300 Subject: [PATCH 30/37] Add demo logics for using fp-ts in feature layer --- .../latest-invoices-controller.ts | 4 +- .../latest-invoices/latest-invoices.tsx | 5 +- src/feature/common/failures/base-failure.ts | 8 ++- .../common/failures/dev/arguments-failure.ts | 6 +-- .../common/failures/dev/base-dev-failure.ts | 2 +- .../common/failures/dev/dependency-failure.ts | 6 +-- .../common/failures/network-failure.ts | 6 +-- src/feature/common/failures/params-failure.ts | 12 +++++ .../data/repo/customer-invoice-db-repo.ts | 36 +++++++------ .../domain/i-repo/customer-invoice-repo.ts | 3 +- .../fetch-customer-invoices-usecase.ts | 6 +-- .../core/invoice/data/repo/invoice-db-repo.ts | 52 ++++++++++++------- .../invoice/domain/i-repo/invoice-repo.ts | 3 +- .../domain/usecase/create-invoice-usecase.ts | 25 +++++---- 14 files changed, 109 insertions(+), 65 deletions(-) create mode 100644 src/feature/common/failures/params-failure.ts diff --git a/src/app/dashboard/components/server/latest-invoices/latest-invoices-controller.ts b/src/app/dashboard/components/server/latest-invoices/latest-invoices-controller.ts index 45bde22..8fbbde9 100644 --- a/src/app/dashboard/components/server/latest-invoices/latest-invoices-controller.ts +++ b/src/app/dashboard/components/server/latest-invoices/latest-invoices-controller.ts @@ -1,5 +1,5 @@ import fetchCustomerInvoicesUsecase from "@/feature/core/customer-invoice/domain/usecase/fetch-customer-invoices-usecase"; -export default function latestInvoicesController() { - return fetchCustomerInvoicesUsecase() +export default async function latestInvoicesController() { + return await fetchCustomerInvoicesUsecase() } \ No newline at end of file diff --git a/src/app/dashboard/components/server/latest-invoices/latest-invoices.tsx b/src/app/dashboard/components/server/latest-invoices/latest-invoices.tsx index 09396cd..696af73 100644 --- a/src/app/dashboard/components/server/latest-invoices/latest-invoices.tsx +++ b/src/app/dashboard/components/server/latest-invoices/latest-invoices.tsx @@ -2,12 +2,15 @@ import CreateRandomInvoiceContainer from '@/app/dashboard/components/client/crea import latestInvoicesController from '@/app/dashboard/components/server/latest-invoices/latest-invoices-controller'; import { ArrowPathIcon } from '@heroicons/react/24/outline'; import clsx from 'clsx'; +import { isLeft } from 'fp-ts/lib/Either'; import Image from 'next/image'; export default async function LatestInvoices() { const latestInvoices = await latestInvoicesController(); - const invoices = latestInvoices.map((invoice, i) => { + if (isLeft(latestInvoices)) return <div>Error</div> + + const invoices = latestInvoices.right.map((invoice, i) => { return ( <div key={invoice.id} diff --git a/src/feature/common/failures/base-failure.ts b/src/feature/common/failures/base-failure.ts index bc09402..43e6117 100644 --- a/src/feature/common/failures/base-failure.ts +++ b/src/feature/common/failures/base-failure.ts @@ -4,7 +4,7 @@ import { makeFailureMessage } from "@/feature/common/failures/failure-helpers"; * This is a class called BaseFailure that extends the Error class. It is * used as a base class for creating custom failure classes. */ -export default abstract class BaseFailure { +export default abstract class BaseFailure<META_DATA> { /* ------------------------------- Attributes ------------------------------- */ private readonly BASE_FAILURE_MESSAGE = "failure"; @@ -15,8 +15,12 @@ export default abstract class BaseFailure { message = this.BASE_FAILURE_MESSAGE; /* -------------------------------------------------------------------------- */ - constructor(key: string) { + metadata: META_DATA | undefined; + + /* -------------------------------------------------------------------------- */ + constructor(key: string, metadata?: META_DATA) { this.message = makeFailureMessage(this.message, key); + this.metadata = metadata ?? undefined } /* -------------------------------------------------------------------------- */ } diff --git a/src/feature/common/failures/dev/arguments-failure.ts b/src/feature/common/failures/dev/arguments-failure.ts index ed4e2c9..11d01c2 100644 --- a/src/feature/common/failures/dev/arguments-failure.ts +++ b/src/feature/common/failures/dev/arguments-failure.ts @@ -3,10 +3,10 @@ import BaseDevFailure from "@/feature/common/failures/dev/base-dev-failure"; /** * Failure for needed arguments in a method but sent wrong one */ -export default class ArgumentsFailure extends BaseDevFailure { +export default class ArgumentsFailure<META_DATA> extends BaseDevFailure<META_DATA> { /* ------------------------------- Constructor ------------------------------ */ - constructor() { - super("arguments"); + constructor(metadata?: META_DATA) { + super("arguments", metadata); } /* -------------------------------------------------------------------------- */ } diff --git a/src/feature/common/failures/dev/base-dev-failure.ts b/src/feature/common/failures/dev/base-dev-failure.ts index aaf8142..ad404d1 100644 --- a/src/feature/common/failures/dev/base-dev-failure.ts +++ b/src/feature/common/failures/dev/base-dev-failure.ts @@ -1,3 +1,3 @@ import BaseFailure from "@/feature/common/failures/base-failure"; -export default abstract class BaseDevFailure extends BaseFailure {} +export default abstract class BaseDevFailure<META_DATA> extends BaseFailure<META_DATA> {} diff --git a/src/feature/common/failures/dev/dependency-failure.ts b/src/feature/common/failures/dev/dependency-failure.ts index 86b49cf..6f16f8f 100644 --- a/src/feature/common/failures/dev/dependency-failure.ts +++ b/src/feature/common/failures/dev/dependency-failure.ts @@ -3,8 +3,8 @@ import BaseDevFailure from "@/feature/common/failures/dev/base-dev-failure"; /** * This is a failure of not having specific dependency */ -export default class DependencyFailure extends BaseDevFailure { - constructor() { - super("DependencyFailure"); +export default class DependencyFailure<META_DATA> extends BaseDevFailure<META_DATA> { + constructor(metadata: META_DATA) { + super("DependencyFailure", metadata); } } diff --git a/src/feature/common/failures/network-failure.ts b/src/feature/common/failures/network-failure.ts index 3268fc3..192bdf5 100644 --- a/src/feature/common/failures/network-failure.ts +++ b/src/feature/common/failures/network-failure.ts @@ -3,10 +3,10 @@ import BaseFailure from "./base-failure"; /** * Failure for HTTP response when response dosn't have base structure */ -export default class NetworkFailure extends BaseFailure { +export default class NetworkFailure<META_DATA> extends BaseFailure<META_DATA> { /* ------------------------------- Constructor ------------------------------ */ - constructor() { - super("network"); + constructor(metaData?: META_DATA) { + super("network", metaData); } /* -------------------------------------------------------------------------- */ } diff --git a/src/feature/common/failures/params-failure.ts b/src/feature/common/failures/params-failure.ts new file mode 100644 index 0000000..df50d8c --- /dev/null +++ b/src/feature/common/failures/params-failure.ts @@ -0,0 +1,12 @@ +import BaseFailure from "./base-failure"; + +/** + * Failure for params failure + */ +export default class ParamsFailure<META_DATA> extends BaseFailure<META_DATA> { + /* ------------------------------- Constructor ------------------------------ */ + constructor(metadata?: META_DATA) { + super("params", metadata); + } + /* -------------------------------------------------------------------------- */ +} diff --git a/src/feature/core/customer-invoice/data/repo/customer-invoice-db-repo.ts b/src/feature/core/customer-invoice/data/repo/customer-invoice-db-repo.ts index a12de93..bc35087 100644 --- a/src/feature/core/customer-invoice/data/repo/customer-invoice-db-repo.ts +++ b/src/feature/core/customer-invoice/data/repo/customer-invoice-db-repo.ts @@ -1,7 +1,12 @@ import { sql } from "@/bootstrap/boundaries/db/db"; +import ApiTask from "@/feature/common/data/api-task"; +import { failureOr } from "@/feature/common/failures/failure-helpers"; +import NetworkFailure from "@/feature/common/failures/network-failure"; import { formatCurrency } from "@/feature/common/feature-helpers"; import CustomerInvoice from "@/feature/core/customer-invoice/domain/entity/customer-invoice"; import CustomerInvoiceRepo from "@/feature/core/customer-invoice/domain/i-repo/customer-invoice-repo"; +import { pipe } from "fp-ts/lib/function"; +import { tryCatch } from "fp-ts/lib/TaskEither"; import postgres from "postgres"; type customerInvoiceDbResponse = { @@ -13,23 +18,24 @@ type customerInvoiceDbResponse = { } export default class CustomerInvoiceDbRepo implements CustomerInvoiceRepo { - async fetchList(): Promise<CustomerInvoice[]> { - try { - const data = await sql` - SELECT invoices.amount, customers.name, customers.image_url, customers.email, invoices.id - FROM invoices - JOIN customers ON invoices.customer_id = customers.id - ORDER BY invoices.date DESC - LIMIT 20 ` as postgres.RowList<customerInvoiceDbResponse[]>; - - return this.customerInvoicesDto(data) - } catch (error) { - console.error('Database Error:', error); - throw new Error('Failed to fetch the latest invoices.'); - } + fetchList(): ApiTask<CustomerInvoice[]> { + return pipe( + tryCatch( + async () => { + const response = await sql` + SELECT invoices.amount, customers.name, customers.image_url, customers.email, invoices.id + FROM invoices + JOIN customers ON invoices.customer_id = customers.id + ORDER BY invoices.date DESC + LIMIT 20 ` as postgres.RowList<customerInvoiceDbResponse[]>; + + return this.customerInvoicesDto(response) + }, + (l) => failureOr(l, new NetworkFailure()) + ) + ) } - private customerInvoicesDto(dbCustomers: customerInvoiceDbResponse[]): CustomerInvoice[] { return dbCustomers.map((customer) => this.customerInvoiceDto(customer)); } diff --git a/src/feature/core/customer-invoice/domain/i-repo/customer-invoice-repo.ts b/src/feature/core/customer-invoice/domain/i-repo/customer-invoice-repo.ts index 0a8c993..ab4b486 100644 --- a/src/feature/core/customer-invoice/domain/i-repo/customer-invoice-repo.ts +++ b/src/feature/core/customer-invoice/domain/i-repo/customer-invoice-repo.ts @@ -1,7 +1,8 @@ +import ApiTask from "@/feature/common/data/api-task" import CustomerInvoice from "@/feature/core/customer-invoice/domain/entity/customer-invoice" export default interface CustomerInvoiceRepo { - fetchList(): Promise<CustomerInvoice[]> + fetchList(): ApiTask<CustomerInvoice[]> } export const customerInvoiceRepoKey = "customerInvoiceRepoKey" \ No newline at end of file diff --git a/src/feature/core/customer-invoice/domain/usecase/fetch-customer-invoices-usecase.ts b/src/feature/core/customer-invoice/domain/usecase/fetch-customer-invoices-usecase.ts index 5947553..5d2df55 100644 --- a/src/feature/core/customer-invoice/domain/usecase/fetch-customer-invoices-usecase.ts +++ b/src/feature/core/customer-invoice/domain/usecase/fetch-customer-invoices-usecase.ts @@ -1,12 +1,12 @@ -"use server" +import { ApiEither } from "@/feature/common/data/api-task"; import serverDi from "@/feature/common/server-di"; import CustomerInvoice from "@/feature/core/customer-invoice/domain/entity/customer-invoice"; import CustomerInvoiceRepo, { customerInvoiceRepoKey } from "@/feature/core/customer-invoice/domain/i-repo/customer-invoice-repo"; import { customerInvoiceModuleKey } from "@/feature/core/customer-invoice/invoice-module-key"; import { connection } from "next/server"; -export default async function fetchCustomerInvoicesUsecase(): Promise<CustomerInvoice[]> { +export default async function fetchCustomerInvoicesUsecase(): Promise<ApiEither<CustomerInvoice[]>> { connection() const repo = serverDi(customerInvoiceModuleKey).resolve<CustomerInvoiceRepo>(customerInvoiceRepoKey) - return repo.fetchList() + return repo.fetchList()() } \ No newline at end of file diff --git a/src/feature/core/invoice/data/repo/invoice-db-repo.ts b/src/feature/core/invoice/data/repo/invoice-db-repo.ts index c8e2bb9..416c060 100644 --- a/src/feature/core/invoice/data/repo/invoice-db-repo.ts +++ b/src/feature/core/invoice/data/repo/invoice-db-repo.ts @@ -1,8 +1,13 @@ import { sql } from "@/bootstrap/boundaries/db/db"; +import ApiTask from "@/feature/common/data/api-task"; +import { failureOr } from "@/feature/common/failures/failure-helpers"; +import NetworkFailure from "@/feature/common/failures/network-failure"; import { formatCurrency } from "@/feature/common/feature-helpers"; import InvoiceRepo from "@/feature/core/invoice/domain/i-repo/invoice-repo"; import { InvoiceParam } from "@/feature/core/invoice/domain/param/invoice-param"; import InvoiceStatusSummary from "@/feature/core/invoice/domain/value-object/invoice-status"; +import { pipe } from "fp-ts/lib/function"; +import { tryCatch } from "fp-ts/lib/TaskEither"; import postgres from "postgres"; type InvoiceSummaryDbResponse = {paid: string, pending: string} @@ -13,26 +18,33 @@ export default class InvoiceDbRepo implements InvoiceRepo { return data.count ?? 0 } - async createInvoice(params: InvoiceParam): Promise<string> { - const firstCustomerIdDb = await sql`SELECT - id FROM customers - ORDER BY id DESC - LIMIT 1 - ` - const customerId = firstCustomerIdDb.at(0)?.id - if (!customerId) throw new Error("There is no customer") - - const { amount, status } = params; - const amountInCents = amount * 100; - const date = new Date().toISOString().split('T')[0]; - - // Insert data into the database - const result = await sql` - INSERT INTO invoices (customer_id, amount, status, date) - VALUES (${customerId}, ${amountInCents}, ${status}, ${date}) - RETURNING id - `; - return result.at(0)?.id ?? "" + createInvoice(params: InvoiceParam): ApiTask<string> { + return pipe( + tryCatch( + async () => { + const firstCustomerIdDb = await sql`SELECT + id FROM customers + ORDER BY id DESC + LIMIT 1 + ` + const customerId = firstCustomerIdDb.at(0)?.id + if (!customerId) throw new Error("There is no customer") + + const { amount, status } = params; + const amountInCents = amount * 100; + const date = new Date().toISOString().split('T')[0]; + + // Insert data into the database + const result = await sql` + INSERT INTO invoices (customer_id, amount, status, date) + VALUES (${customerId}, ${amountInCents}, ${status}, ${date}) + RETURNING id + `; + return result.at(0)?.id ?? "" + }, + (l) => failureOr(l, new NetworkFailure(l as Error)) + ), + ) } async fetchInvoicesStatusSummary(): Promise<InvoiceStatusSummary> { diff --git a/src/feature/core/invoice/domain/i-repo/invoice-repo.ts b/src/feature/core/invoice/domain/i-repo/invoice-repo.ts index 983ac3f..ca5096d 100644 --- a/src/feature/core/invoice/domain/i-repo/invoice-repo.ts +++ b/src/feature/core/invoice/domain/i-repo/invoice-repo.ts @@ -1,10 +1,11 @@ +import ApiTask from "@/feature/common/data/api-task" import { InvoiceParam } from "@/feature/core/invoice/domain/param/invoice-param" import InvoiceStatusSummary from "@/feature/core/invoice/domain/value-object/invoice-status" export default interface InvoiceRepo { fetchAllInvoicesAmount(): Promise<number> fetchInvoicesStatusSummary(): Promise<InvoiceStatusSummary> - createInvoice(params: InvoiceParam): Promise<string> + createInvoice(params: InvoiceParam): ApiTask<string> } export const invoiceRepoKey = "invoiceRepoKey" \ No newline at end of file diff --git a/src/feature/core/invoice/domain/usecase/create-invoice-usecase.ts b/src/feature/core/invoice/domain/usecase/create-invoice-usecase.ts index 73a0106..9cfc63d 100644 --- a/src/feature/core/invoice/domain/usecase/create-invoice-usecase.ts +++ b/src/feature/core/invoice/domain/usecase/create-invoice-usecase.ts @@ -1,19 +1,24 @@ "use server" +import { ApiEither } from "@/feature/common/data/api-task"; +import ParamsFailure from "@/feature/common/failures/params-failure"; import serverDi from "@/feature/common/server-di"; import InvoiceRepo, { invoiceRepoKey } from "@/feature/core/invoice/domain/i-repo/invoice-repo"; import { InvoiceParam, invoiceSchema } from "@/feature/core/invoice/domain/param/invoice-param"; import { invoiceModuleKey } from "@/feature/core/invoice/invoice-module-key"; +import { pipe } from "fp-ts/lib/function"; +import { chain, fromNullable, left, map, right } from "fp-ts/lib/TaskEither"; -export default async function createInvoiceUsecase(params: InvoiceParam): Promise<string | {errorMessage: string}> { - const isParamsValid = invoiceSchema.safeParse(params) - - if (!isParamsValid) { - return { - errorMessage: "Please pass correct params" - } - } +export default async function createInvoiceUsecase(params: InvoiceParam): Promise<ApiEither<string>> { const repo = serverDi(invoiceModuleKey).resolve<InvoiceRepo>(invoiceRepoKey) - return repo.createInvoice(params) - + return pipe( + fromNullable(new ParamsFailure())(params), + map((params) => invoiceSchema.safeParse(params)), + chain((params) => { + const isParamsValid = invoiceSchema.safeParse(params) + if (!isParamsValid.success) left(new ParamsFailure()) + return right(params.data as InvoiceParam) + }), + chain((params) => repo.createInvoice(params)) + )() } \ No newline at end of file -- 2.39.5 From e9029eff76d62fcb12e81f53fc524784c6348266 Mon Sep 17 00:00:00 2001 From: behnam <behnamrahimpour74@gmail.com> Date: Sat, 2 Nov 2024 16:53:22 +0300 Subject: [PATCH 31/37] Add base lang for server --- package.json | 3 ++ .../create-random-invoice.tsx | 2 +- .../client/nav-links/nav-link-controller.ts | 0 .../components/client/nav-links/nav-links.tsx | 2 +- .../components/server/card/card-controller.ts | 0 .../dashboard/components/server/card/card.tsx | 2 +- .../server/cards/cards-controller.ts | 0 .../components/server/cards/cards.tsx | 4 +-- .../latest-invoices-controller.ts | 0 .../latest-invoices/latest-invoices.tsx | 4 +-- .../revenue-chart/revenue-chart-controller.ts | 0 .../server/revenue-chart/revenue-chart.tsx | 2 +- .../dashboard/components/server/sidenav.tsx | 2 +- .../components/server/skeletons/skeletons.tsx | 0 src/app/{ => [lang]}/dashboard/layout.tsx | 4 +-- src/app/[lang]/dashboard/loading.tsx | 5 +++ .../dashboard/module/dashboard-app-module.ts | 2 +- src/app/{ => [lang]}/dashboard/page.tsx | 16 +++++---- .../vm/create-random-invoice-button-vm.ts | 0 src/app/{ => [lang]}/page.tsx | 0 src/app/dashboard/loading.tsx | 5 --- src/bootstrap/i18n/dictionaries/en.ts | 15 ++++++++ src/bootstrap/i18n/dictionaries/lang-key.ts | 13 +++++++ src/bootstrap/i18n/dictionaries/ru.ts | 15 ++++++++ src/bootstrap/i18n/i18n.ts | 21 +++++++++++ src/bootstrap/i18n/settings.ts | 15 ++++++++ src/middleware.ts | 23 ++++++++++++ tsconfig.json | 2 +- yarn.lock | 36 ++++++++++++++++++- 29 files changed, 167 insertions(+), 26 deletions(-) rename src/app/{ => [lang]}/dashboard/components/client/create-random-invoice/create-random-invoice.tsx (76%) rename src/app/{ => [lang]}/dashboard/components/client/nav-links/nav-link-controller.ts (100%) rename src/app/{ => [lang]}/dashboard/components/client/nav-links/nav-links.tsx (88%) rename src/app/{ => [lang]}/dashboard/components/server/card/card-controller.ts (100%) rename src/app/{ => [lang]}/dashboard/components/server/card/card.tsx (86%) rename src/app/{ => [lang]}/dashboard/components/server/cards/cards-controller.ts (100%) rename src/app/{ => [lang]}/dashboard/components/server/cards/cards.tsx (75%) rename src/app/{ => [lang]}/dashboard/components/server/latest-invoices/latest-invoices-controller.ts (100%) rename src/app/{ => [lang]}/dashboard/components/server/latest-invoices/latest-invoices.tsx (89%) rename src/app/{ => [lang]}/dashboard/components/server/revenue-chart/revenue-chart-controller.ts (100%) rename src/app/{ => [lang]}/dashboard/components/server/revenue-chart/revenue-chart.tsx (93%) rename src/app/{ => [lang]}/dashboard/components/server/sidenav.tsx (87%) rename src/app/{ => [lang]}/dashboard/components/server/skeletons/skeletons.tsx (100%) rename src/app/{ => [lang]}/dashboard/layout.tsx (78%) create mode 100644 src/app/[lang]/dashboard/loading.tsx rename src/app/{ => [lang]}/dashboard/module/dashboard-app-module.ts (81%) rename src/app/{ => [lang]}/dashboard/page.tsx (50%) rename src/app/{ => [lang]}/dashboard/vm/create-random-invoice-button-vm.ts (100%) rename src/app/{ => [lang]}/page.tsx (100%) delete mode 100644 src/app/dashboard/loading.tsx create mode 100644 src/bootstrap/i18n/dictionaries/en.ts create mode 100644 src/bootstrap/i18n/dictionaries/lang-key.ts create mode 100644 src/bootstrap/i18n/dictionaries/ru.ts create mode 100644 src/bootstrap/i18n/i18n.ts create mode 100644 src/bootstrap/i18n/settings.ts create mode 100644 src/middleware.ts diff --git a/package.json b/package.json index 6fd58e3..8fee4df 100644 --- a/package.json +++ b/package.json @@ -17,11 +17,14 @@ "class-variance-authority": "^0.7.0", "clsx": "^2.1.1", "fp-ts": "^2.16.9", + "i18next": "^23.16.4", + "i18next-resources-to-backend": "^1.2.1", "lucide-react": "^0.454.0", "next": "15.0.2", "postgres": "^3.4.5", "react": "19.0.0-rc-69d4b800-20241021", "react-dom": "19.0.0-rc-69d4b800-20241021", + "react-i18next": "^15.1.0", "reflect-metadata": "^0.2.2", "tailwind-merge": "^2.5.4", "tailwindcss-animate": "^1.0.7", diff --git a/src/app/dashboard/components/client/create-random-invoice/create-random-invoice.tsx b/src/app/[lang]/dashboard/components/client/create-random-invoice/create-random-invoice.tsx similarity index 76% rename from src/app/dashboard/components/client/create-random-invoice/create-random-invoice.tsx rename to src/app/[lang]/dashboard/components/client/create-random-invoice/create-random-invoice.tsx index 8a80645..f3f95a4 100644 --- a/src/app/dashboard/components/client/create-random-invoice/create-random-invoice.tsx +++ b/src/app/[lang]/dashboard/components/client/create-random-invoice/create-random-invoice.tsx @@ -1,7 +1,7 @@ "use client" import Button from "@/app/components/button/button" -import CreateRandomInvoiceButtonVM from "@/app/dashboard/vm/create-random-invoice-button-vm" +import CreateRandomInvoiceButtonVM from "@/app/[lang]/dashboard/vm/create-random-invoice-button-vm" import { useDI } from "@/bootstrap/di/di-context" import { useRef } from "react" diff --git a/src/app/dashboard/components/client/nav-links/nav-link-controller.ts b/src/app/[lang]/dashboard/components/client/nav-links/nav-link-controller.ts similarity index 100% rename from src/app/dashboard/components/client/nav-links/nav-link-controller.ts rename to src/app/[lang]/dashboard/components/client/nav-links/nav-link-controller.ts diff --git a/src/app/dashboard/components/client/nav-links/nav-links.tsx b/src/app/[lang]/dashboard/components/client/nav-links/nav-links.tsx similarity index 88% rename from src/app/dashboard/components/client/nav-links/nav-links.tsx rename to src/app/[lang]/dashboard/components/client/nav-links/nav-links.tsx index 1aa6072..6aa2ce8 100644 --- a/src/app/dashboard/components/client/nav-links/nav-links.tsx +++ b/src/app/[lang]/dashboard/components/client/nav-links/nav-links.tsx @@ -1,5 +1,5 @@ 'use client' -import navLinkPersonalVM from '@/app/dashboard/components/client/nav-links/nav-link-controller'; +import navLinkPersonalVM from '@/app/[lang]/dashboard/components/client/nav-links/nav-link-controller'; import clsx from 'clsx'; import Link from 'next/link' diff --git a/src/app/dashboard/components/server/card/card-controller.ts b/src/app/[lang]/dashboard/components/server/card/card-controller.ts similarity index 100% rename from src/app/dashboard/components/server/card/card-controller.ts rename to src/app/[lang]/dashboard/components/server/card/card-controller.ts diff --git a/src/app/dashboard/components/server/card/card.tsx b/src/app/[lang]/dashboard/components/server/card/card.tsx similarity index 86% rename from src/app/dashboard/components/server/card/card.tsx rename to src/app/[lang]/dashboard/components/server/card/card.tsx index 1b22154..303eaec 100644 --- a/src/app/dashboard/components/server/card/card.tsx +++ b/src/app/[lang]/dashboard/components/server/card/card.tsx @@ -1,4 +1,4 @@ -import cardController from "@/app/dashboard/components/server/card/card-controller"; +import cardController from "@/app/[lang]/dashboard/components/server/card/card-controller"; diff --git a/src/app/dashboard/components/server/cards/cards-controller.ts b/src/app/[lang]/dashboard/components/server/cards/cards-controller.ts similarity index 100% rename from src/app/dashboard/components/server/cards/cards-controller.ts rename to src/app/[lang]/dashboard/components/server/cards/cards-controller.ts diff --git a/src/app/dashboard/components/server/cards/cards.tsx b/src/app/[lang]/dashboard/components/server/cards/cards.tsx similarity index 75% rename from src/app/dashboard/components/server/cards/cards.tsx rename to src/app/[lang]/dashboard/components/server/cards/cards.tsx index e8f74a9..a0aea58 100644 --- a/src/app/dashboard/components/server/cards/cards.tsx +++ b/src/app/[lang]/dashboard/components/server/cards/cards.tsx @@ -1,5 +1,5 @@ -import { Card } from '@/app/dashboard/components/server/card/card'; -import cardsController from '@/app/dashboard/components/server/cards/cards-controller'; +import { Card } from '@/app/[lang]/dashboard/components/server/card/card'; +import cardsController from '@/app/[lang]/dashboard/components/server/cards/cards-controller'; export default async function CardWrapper() { diff --git a/src/app/dashboard/components/server/latest-invoices/latest-invoices-controller.ts b/src/app/[lang]/dashboard/components/server/latest-invoices/latest-invoices-controller.ts similarity index 100% rename from src/app/dashboard/components/server/latest-invoices/latest-invoices-controller.ts rename to src/app/[lang]/dashboard/components/server/latest-invoices/latest-invoices-controller.ts diff --git a/src/app/dashboard/components/server/latest-invoices/latest-invoices.tsx b/src/app/[lang]/dashboard/components/server/latest-invoices/latest-invoices.tsx similarity index 89% rename from src/app/dashboard/components/server/latest-invoices/latest-invoices.tsx rename to src/app/[lang]/dashboard/components/server/latest-invoices/latest-invoices.tsx index 696af73..3c3e687 100644 --- a/src/app/dashboard/components/server/latest-invoices/latest-invoices.tsx +++ b/src/app/[lang]/dashboard/components/server/latest-invoices/latest-invoices.tsx @@ -1,5 +1,5 @@ -import CreateRandomInvoiceContainer from '@/app/dashboard/components/client/create-random-invoice/create-random-invoice'; -import latestInvoicesController from '@/app/dashboard/components/server/latest-invoices/latest-invoices-controller'; +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 { ArrowPathIcon } from '@heroicons/react/24/outline'; import clsx from 'clsx'; import { isLeft } from 'fp-ts/lib/Either'; diff --git a/src/app/dashboard/components/server/revenue-chart/revenue-chart-controller.ts b/src/app/[lang]/dashboard/components/server/revenue-chart/revenue-chart-controller.ts similarity index 100% rename from src/app/dashboard/components/server/revenue-chart/revenue-chart-controller.ts rename to src/app/[lang]/dashboard/components/server/revenue-chart/revenue-chart-controller.ts diff --git a/src/app/dashboard/components/server/revenue-chart/revenue-chart.tsx b/src/app/[lang]/dashboard/components/server/revenue-chart/revenue-chart.tsx similarity index 93% rename from src/app/dashboard/components/server/revenue-chart/revenue-chart.tsx rename to src/app/[lang]/dashboard/components/server/revenue-chart/revenue-chart.tsx index b29a7ae..fb778f2 100644 --- a/src/app/dashboard/components/server/revenue-chart/revenue-chart.tsx +++ b/src/app/[lang]/dashboard/components/server/revenue-chart/revenue-chart.tsx @@ -1,4 +1,4 @@ -import revenueChartController from '@/app/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'; export default async function RevenueChart() { diff --git a/src/app/dashboard/components/server/sidenav.tsx b/src/app/[lang]/dashboard/components/server/sidenav.tsx similarity index 87% rename from src/app/dashboard/components/server/sidenav.tsx rename to src/app/[lang]/dashboard/components/server/sidenav.tsx index 0af5a13..bc396c4 100644 --- a/src/app/dashboard/components/server/sidenav.tsx +++ b/src/app/[lang]/dashboard/components/server/sidenav.tsx @@ -1,4 +1,4 @@ -import NavLinks from '@/app/dashboard/components/client/nav-links/nav-links'; +import NavLinks from '@/app/[lang]/dashboard/components/client/nav-links/nav-links'; import Link from 'next/link'; export default function SideNav() { diff --git a/src/app/dashboard/components/server/skeletons/skeletons.tsx b/src/app/[lang]/dashboard/components/server/skeletons/skeletons.tsx similarity index 100% rename from src/app/dashboard/components/server/skeletons/skeletons.tsx rename to src/app/[lang]/dashboard/components/server/skeletons/skeletons.tsx diff --git a/src/app/dashboard/layout.tsx b/src/app/[lang]/dashboard/layout.tsx similarity index 78% rename from src/app/dashboard/layout.tsx rename to src/app/[lang]/dashboard/layout.tsx index 55125e7..4e678cf 100644 --- a/src/app/dashboard/layout.tsx +++ b/src/app/[lang]/dashboard/layout.tsx @@ -1,6 +1,6 @@ "use client" -import SideNav from "@/app/dashboard/components/server/sidenav"; -import dashboardAppModule from "@/app/dashboard/module/dashboard-app-module"; +import SideNav from "@/app/[lang]/dashboard/components/server/sidenav"; +import dashboardAppModule from "@/app/[lang]/dashboard/module/dashboard-app-module"; import { DiContext } from "@/bootstrap/di/di-context"; import { useRef } from "react"; diff --git a/src/app/[lang]/dashboard/loading.tsx b/src/app/[lang]/dashboard/loading.tsx new file mode 100644 index 0000000..9c38c20 --- /dev/null +++ b/src/app/[lang]/dashboard/loading.tsx @@ -0,0 +1,5 @@ +import DashboardSkeleton from "@/app/[lang]/dashboard/components/server/skeletons/skeletons"; + +export default function Loading() { + return <DashboardSkeleton />; +} \ No newline at end of file diff --git a/src/app/dashboard/module/dashboard-app-module.ts b/src/app/[lang]/dashboard/module/dashboard-app-module.ts similarity index 81% rename from src/app/dashboard/module/dashboard-app-module.ts rename to src/app/[lang]/dashboard/module/dashboard-app-module.ts index 60721eb..10992a6 100644 --- a/src/app/dashboard/module/dashboard-app-module.ts +++ b/src/app/[lang]/dashboard/module/dashboard-app-module.ts @@ -1,4 +1,4 @@ -import CreateRandomInvoiceButtonVM from "@/app/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 createInvoiceUsecase from "@/feature/core/invoice/domain/usecase/create-invoice-usecase"; diff --git a/src/app/dashboard/page.tsx b/src/app/[lang]/dashboard/page.tsx similarity index 50% rename from src/app/dashboard/page.tsx rename to src/app/[lang]/dashboard/page.tsx index 24fb89a..a77f734 100644 --- a/src/app/dashboard/page.tsx +++ b/src/app/[lang]/dashboard/page.tsx @@ -1,15 +1,17 @@ -import { LatestInvoicesSkeleton, RevenueChartSkeleton } from "@/app/dashboard/components/server/skeletons/skeletons"; -import CardWrapper from "@/app/dashboard/components/server/cards/cards"; -import LatestInvoices from "@/app/dashboard/components/server/latest-invoices/latest-invoices"; -import RevenueChart from "@/app/dashboard/components/server/revenue-chart/revenue-chart"; +import { LatestInvoicesSkeleton, RevenueChartSkeleton } from "@/app/[lang]/dashboard/components/server/skeletons/skeletons"; +import CardWrapper from "@/app/[lang]/dashboard/components/server/cards/cards"; +import LatestInvoices from "@/app/[lang]/dashboard/components/server/latest-invoices/latest-invoices"; +import RevenueChart from "@/app/[lang]/dashboard/components/server/revenue-chart/revenue-chart"; import { Suspense } from "react"; +import { getTranslation } from "@/bootstrap/i18n/i18n"; -export default async function Dashboard() { - +export default async function Dashboard(props: {params: Promise<{lang: string}>}) { + const {lang} = await props.params + const { t } = await getTranslation(lang) return ( <main> <h1 className={`mb-4 text-xl md:text-2xl`}> - Dashboard + {t("global.dashboard")} </h1> <div className="grid gap-6 sm:grid-cols-2 lg:grid-cols-4"> <CardWrapper /> diff --git a/src/app/dashboard/vm/create-random-invoice-button-vm.ts b/src/app/[lang]/dashboard/vm/create-random-invoice-button-vm.ts similarity index 100% rename from src/app/dashboard/vm/create-random-invoice-button-vm.ts rename to src/app/[lang]/dashboard/vm/create-random-invoice-button-vm.ts diff --git a/src/app/page.tsx b/src/app/[lang]/page.tsx similarity index 100% rename from src/app/page.tsx rename to src/app/[lang]/page.tsx diff --git a/src/app/dashboard/loading.tsx b/src/app/dashboard/loading.tsx deleted file mode 100644 index c50ad40..0000000 --- a/src/app/dashboard/loading.tsx +++ /dev/null @@ -1,5 +0,0 @@ -import DashboardSkeleton from "@/app/dashboard/components/server/skeletons/skeletons"; - -export default function Loading() { - return <DashboardSkeleton />; -} \ No newline at end of file diff --git a/src/bootstrap/i18n/dictionaries/en.ts b/src/bootstrap/i18n/dictionaries/en.ts new file mode 100644 index 0000000..3bd88ce --- /dev/null +++ b/src/bootstrap/i18n/dictionaries/en.ts @@ -0,0 +1,15 @@ +import langKey from "@/bootstrap/i18n/dictionaries/lang-key" + +const en: typeof langKey = { + global: { + home: "Home", + dashboard: "Dashboard" + }, + dashboard: { + invoice: { + createButton: "Create random Invoice" + } + } +} + +export default en \ No newline at end of file diff --git a/src/bootstrap/i18n/dictionaries/lang-key.ts b/src/bootstrap/i18n/dictionaries/lang-key.ts new file mode 100644 index 0000000..aed439c --- /dev/null +++ b/src/bootstrap/i18n/dictionaries/lang-key.ts @@ -0,0 +1,13 @@ +const langKey = { + global: { + home: "Дом", + dashboard: "Панель приборов" + }, + dashboard: { + invoice: { + createButton: "Создать случайный счет-фактуру" + } + } +} + +export default langKey; \ No newline at end of file diff --git a/src/bootstrap/i18n/dictionaries/ru.ts b/src/bootstrap/i18n/dictionaries/ru.ts new file mode 100644 index 0000000..5b6c4b4 --- /dev/null +++ b/src/bootstrap/i18n/dictionaries/ru.ts @@ -0,0 +1,15 @@ +import langKey from "@/bootstrap/i18n/dictionaries/lang-key" + +const ru: typeof langKey = { + global: { + home: "Дом", + dashboard: "Панель приборов" + }, + dashboard: { + invoice: { + createButton: "Создать случайный счет-фактуру" + } + } +} + +export default ru \ No newline at end of file diff --git a/src/bootstrap/i18n/i18n.ts b/src/bootstrap/i18n/i18n.ts new file mode 100644 index 0000000..9cc5fb0 --- /dev/null +++ b/src/bootstrap/i18n/i18n.ts @@ -0,0 +1,21 @@ +import { getOptions } from '@/bootstrap/i18n/settings' +import { createInstance } from 'i18next' +import resourcesToBackend from 'i18next-resources-to-backend' +import { initReactI18next } from 'react-i18next/initReactI18next' + +const initI18next = async (lng: string, ns?: string) => { + const i18nInstance = createInstance() + await i18nInstance + .use(initReactI18next) + .use(resourcesToBackend((language: string) => import(`./dictionaries/${language}.ts`))) + .init(getOptions(lng, ns)) + return i18nInstance +} + +export async function getTranslation(lng: string, ns?: string, options: {keyPrefix?: string} = {}) { + const i18nextInstance = await initI18next(lng, ns) + return { + t: i18nextInstance.getFixedT(lng, Array.isArray(ns) ? ns[0] : ns, options?.keyPrefix), + i18n: i18nextInstance + } +} \ No newline at end of file diff --git a/src/bootstrap/i18n/settings.ts b/src/bootstrap/i18n/settings.ts new file mode 100644 index 0000000..90f4fa0 --- /dev/null +++ b/src/bootstrap/i18n/settings.ts @@ -0,0 +1,15 @@ +export const fallbackLng = 'en' +export const languages = [fallbackLng, 'ru'] +export const defaultNS = 'translation' + +export function getOptions (lng = fallbackLng, ns = defaultNS) { + return { + // debug: true, + supportedLngs: languages, + fallbackLng, + lng, + fallbackNS: defaultNS, + defaultNS, + ns + } +} \ No newline at end of file diff --git a/src/middleware.ts b/src/middleware.ts new file mode 100644 index 0000000..ee54225 --- /dev/null +++ b/src/middleware.ts @@ -0,0 +1,23 @@ +import { fallbackLng, languages } from "@/bootstrap/i18n/settings"; +import { NextRequest, NextResponse } from "next/server"; + +export function middleware(request: NextRequest) { + const { pathname } = request.nextUrl + const pathnameHasLocale = languages.some( + (lang) => pathname.startsWith(`/${lang}/`) || pathname === `/${lang}` + ) + + if (pathnameHasLocale) return + + request.nextUrl.pathname = `/${fallbackLng}${pathname}` + // e.g. incoming request is /products + // The new URL is now /en-US/products + return NextResponse.redirect(request.nextUrl) +} + +export const config = { + matcher: [ + // Skip all internal paths (_next) + '/((?!api|_next/static|_next/image|favicon.ico).*)' + ], +} \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index 0d0b9fb..9f3a85a 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -25,6 +25,6 @@ "@/*": ["./src/*"] } }, - "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts", "src/bootstrap/boundaries/db/seed.js", "src/bootstrap/boundaries/db/placeholder-data.js"], + "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts", "src/bootstrap/boundaries/db/seed.js", "src/bootstrap/boundaries/db/placeholder-data.js", "src/middleware.ts"], "exclude": ["node_modules"] } diff --git a/yarn.lock b/yarn.lock index 194f43b..4fc4079 100644 --- a/yarn.lock +++ b/yarn.lock @@ -138,7 +138,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.25.9" -"@babel/runtime@^7.12.5": +"@babel/runtime@^7.12.5", "@babel/runtime@^7.23.2", "@babel/runtime@^7.25.0": version "7.26.0" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.26.0.tgz#8600c2f595f277c60815256418b85356a65173c1" integrity sha512-FDSOghenHTiToteC/QRlv2q3DhPZ/oOXTBoirfWNx1Cx3TMVcGWQtMMmQcSvb/JjpNeGzx8Pq/b4fKEJuWm1sw== @@ -2342,6 +2342,13 @@ html-encoding-sniffer@^4.0.0: dependencies: whatwg-encoding "^3.1.1" +html-parse-stringify@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/html-parse-stringify/-/html-parse-stringify-3.0.1.tgz#dfc1017347ce9f77c8141a507f233040c59c55d2" + integrity sha512-KknJ50kTInJ7qIScF3jeaFRpMpE8/lfiTdzf/twXyPBLAGrLRTmkz3AdTnKeh40X8k9L2fdYwEp/42WGXIRGcg== + dependencies: + void-elements "3.1.0" + http-proxy-agent@^7.0.2: version "7.0.2" resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz#9a8b1f246866c028509486585f62b8f2c18c270e" @@ -2366,6 +2373,20 @@ https-proxy-agent@^7.0.5: agent-base "^7.0.2" debug "4" +i18next-resources-to-backend@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/i18next-resources-to-backend/-/i18next-resources-to-backend-1.2.1.tgz#fded121e63e3139ce839c9901b9449dbbea7351d" + integrity sha512-okHbVA+HZ7n1/76MsfhPqDou0fptl2dAlhRDu2ideXloRRduzHsqDOznJBef+R3DFZnbvWoBW+KxJ7fnFjd6Yw== + dependencies: + "@babel/runtime" "^7.23.2" + +i18next@^23.16.4: + version "23.16.4" + resolved "https://registry.yarnpkg.com/i18next/-/i18next-23.16.4.tgz#79c07544f6d6fa803fe8427108d547542c1d6cf4" + integrity sha512-9NIYBVy9cs4wIqzurf7nLXPyf3R78xYbxExVqHLK9od3038rjpyOEzW+XB130kZ1N4PZ9inTtJ471CRJ4Ituyg== + dependencies: + "@babel/runtime" "^7.23.2" + iconv-lite@0.6.3: version "0.6.3" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501" @@ -3291,6 +3312,14 @@ react-dom@19.0.0-rc-69d4b800-20241021: dependencies: scheduler "0.25.0-rc-69d4b800-20241021" +react-i18next@^15.1.0: + version "15.1.0" + resolved "https://registry.yarnpkg.com/react-i18next/-/react-i18next-15.1.0.tgz#9494e4add2389f04c205dd7628c1aa75747b98a3" + integrity sha512-zj3nJynMnZsy2gPZiOTC7XctCY5eQGqT3tcKMmfJWC9FMvgd+960w/adq61j8iPzpwmsXejqID9qC3Mqu1Xu2Q== + dependencies: + "@babel/runtime" "^7.25.0" + html-parse-stringify "^3.0.1" + react-is@^16.13.1: version "16.13.1" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" @@ -4099,6 +4128,11 @@ vitest@^2.1.4: vite-node "2.1.4" why-is-node-running "^2.3.0" +void-elements@3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-3.1.0.tgz#614f7fbf8d801f0bb5f0661f5b2f5785750e4f09" + integrity sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w== + w3c-xmlserializer@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz#f925ba26855158594d907313cedd1476c5967f6c" -- 2.39.5 From 7f51bb6a69c4b717dcb72c09a6a68b78fc5e0efd Mon Sep 17 00:00:00 2001 From: behnam <behnamrahimpour74@gmail.com> Date: Sat, 2 Nov 2024 20:41:38 +0300 Subject: [PATCH 32/37] Add i18n --- package.json | 4 + src/app/[lang]/dashboard/page.tsx | 7 +- .../vm/create-random-invoice-button-vm.ts | 6 +- src/app/[lang]/layout.tsx | 9 ++ src/app/layout.tsx | 2 +- src/bootstrap/helpers/global-helpers.ts | 2 + src/bootstrap/helpers/lib/actions.ts | 117 ------------------ src/bootstrap/i18n/dictionaries/en.ts | 1 + src/bootstrap/i18n/dictionaries/lang-key.ts | 7 +- src/bootstrap/i18n/dictionaries/ru.ts | 1 + src/bootstrap/i18n/i18n-provider.tsx | 13 ++ src/bootstrap/i18n/i18n.ts | 29 +++-- src/bootstrap/i18n/settings.ts | 1 + src/middleware.ts | 55 ++++---- yarn.lock | 85 ++++++++++++- 15 files changed, 183 insertions(+), 156 deletions(-) create mode 100644 src/app/[lang]/layout.tsx delete mode 100644 src/bootstrap/helpers/lib/actions.ts create mode 100644 src/bootstrap/i18n/i18n-provider.tsx diff --git a/package.json b/package.json index 8fee4df..818e3a6 100644 --- a/package.json +++ b/package.json @@ -14,15 +14,19 @@ "@heroicons/react": "^2.1.5", "@radix-ui/react-icons": "^1.3.1", "@radix-ui/react-slot": "^1.1.0", + "accept-language": "^3.0.20", "class-variance-authority": "^0.7.0", "clsx": "^2.1.1", "fp-ts": "^2.16.9", "i18next": "^23.16.4", + "i18next-browser-languagedetector": "^8.0.0", "i18next-resources-to-backend": "^1.2.1", "lucide-react": "^0.454.0", "next": "15.0.2", + "next-i18n-router": "^5.5.1", "postgres": "^3.4.5", "react": "19.0.0-rc-69d4b800-20241021", + "react-cookie": "^7.2.2", "react-dom": "19.0.0-rc-69d4b800-20241021", "react-i18next": "^15.1.0", "reflect-metadata": "^0.2.2", diff --git a/src/app/[lang]/dashboard/page.tsx b/src/app/[lang]/dashboard/page.tsx index a77f734..0035a7b 100644 --- a/src/app/[lang]/dashboard/page.tsx +++ b/src/app/[lang]/dashboard/page.tsx @@ -3,15 +3,16 @@ import CardWrapper from "@/app/[lang]/dashboard/components/server/cards/cards"; import LatestInvoices from "@/app/[lang]/dashboard/components/server/latest-invoices/latest-invoices"; import RevenueChart from "@/app/[lang]/dashboard/components/server/revenue-chart/revenue-chart"; import { Suspense } from "react"; -import { getTranslation } from "@/bootstrap/i18n/i18n"; +import { getServerTranslation } from "@/bootstrap/i18n/i18n"; +import langKey from "@/bootstrap/i18n/dictionaries/lang-key"; export default async function Dashboard(props: {params: Promise<{lang: string}>}) { const {lang} = await props.params - const { t } = await getTranslation(lang) + const { t } = await getServerTranslation(lang) return ( <main> <h1 className={`mb-4 text-xl md:text-2xl`}> - {t("global.dashboard")} + {t(langKey.global.dashboard)} </h1> <div className="grid gap-6 sm:grid-cols-2 lg:grid-cols-4"> <CardWrapper /> diff --git a/src/app/[lang]/dashboard/vm/create-random-invoice-button-vm.ts b/src/app/[lang]/dashboard/vm/create-random-invoice-button-vm.ts index c5ceb13..136f5b0 100644 --- a/src/app/[lang]/dashboard/vm/create-random-invoice-button-vm.ts +++ b/src/app/[lang]/dashboard/vm/create-random-invoice-button-vm.ts @@ -2,10 +2,12 @@ import ButtonVm from "@/app/components/button/button-vm"; import { useServerAction } from "@/bootstrap/helpers/hooks/use-server-action"; import useThrottle from "@/bootstrap/helpers/hooks/use-throttle"; import BaseVM from "@/bootstrap/helpers/vm/base-vm"; +import langKey from "@/bootstrap/i18n/dictionaries/lang-key"; import { InvoiceParam } from "@/feature/core/invoice/domain/param/invoice-param"; import createInvoiceUsecase from "@/feature/core/invoice/domain/usecase/create-invoice-usecase"; import { faker } from "@faker-js/faker"; import { useRouter } from "next/navigation"; +import { useTranslation } from "react-i18next"; export default class CreateRandomInvoiceButtonVM extends BaseVM<ButtonVm> { private createInvoice: typeof createInvoiceUsecase @@ -19,9 +21,11 @@ export default class CreateRandomInvoiceButtonVM extends BaseVM<ButtonVm> { const [action, isPending] = useServerAction(() => this.onClickHandler(router.refresh)) const throttledOnClick = useThrottle(action, 5000) + const {t} = useTranslation() + return { props: { - title: isPending ? "Loading" : "Create Random Invoice", + title: t(isPending ? langKey.global.loading : langKey.dashboard.invoice.createButton), isDisable: isPending ? true : false }, onClick: throttledOnClick.bind(this) diff --git a/src/app/[lang]/layout.tsx b/src/app/[lang]/layout.tsx new file mode 100644 index 0000000..dedc58e --- /dev/null +++ b/src/app/[lang]/layout.tsx @@ -0,0 +1,9 @@ +import { initI18next } from "@/bootstrap/i18n/i18n"; +import TranslationsProvider from "@/bootstrap/i18n/i18n-provider"; +import { PropsWithChildren } from "react"; + +export default async function layout(props: PropsWithChildren & {params: Promise<{lang: string}>}) { + const lang = (await props.params).lang + const { resources} = await initI18next({lng: lang}) + return <TranslationsProvider lng={lang} resources={resources}>{props.children}</TranslationsProvider> +} \ No newline at end of file diff --git a/src/app/layout.tsx b/src/app/layout.tsx index ba8b4a7..8a8df4e 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -23,7 +23,7 @@ export default function RootLayout({ children: React.ReactNode; }>) { return ( - <html lang="en"> + <html> <body className={`${geistSans.variable} ${geistMono.variable} antialiased`} > diff --git a/src/bootstrap/helpers/global-helpers.ts b/src/bootstrap/helpers/global-helpers.ts index e69de29..cf37914 100644 --- a/src/bootstrap/helpers/global-helpers.ts +++ b/src/bootstrap/helpers/global-helpers.ts @@ -0,0 +1,2 @@ + +export const isServer = typeof window === 'undefined' \ No newline at end of file diff --git a/src/bootstrap/helpers/lib/actions.ts b/src/bootstrap/helpers/lib/actions.ts deleted file mode 100644 index a408241..0000000 --- a/src/bootstrap/helpers/lib/actions.ts +++ /dev/null @@ -1,117 +0,0 @@ -'use server'; - -import { z } from 'zod'; -import { revalidatePath } from 'next/cache'; -import { redirect } from 'next/navigation'; -import { sql } from '@/bootstrap/boundaries/db/db'; - -const FormSchema = z.object({ - id: z.string(), - customerId: z.string({ - invalid_type_error: 'Please select a customer.', - }), - amount: z.coerce.number().gt(0, { message: 'Please enter an amount greater than $0.' }), - status: z.enum(['pending', 'paid'], { - invalid_type_error: 'Please select an invoice status.', - }), - date: z.string(), -}); -const CreateInvoice = FormSchema.omit({ id: true, date: true }); - - - -// This is temporary -export type State = { - errors?: { - customerId?: string[]; - amount?: string[]; - status?: string[]; - }; - message?: string | null; -}; - -export async function createInvoice(_prevState: State, formData: FormData) { - // Validate form fields using Zod - console.log('ffor', formData) - const validatedFields = CreateInvoice.safeParse({ - customerId: formData?.get('customerId') || undefined, - amount: formData?.get('amount') || undefined, - status: formData?.get('status') || undefined, - }); - - // If form validation fails, return errors early. Otherwise, continue. - if (!validatedFields.success) { - return { - errors: validatedFields.error.flatten().fieldErrors, - message: 'Missing Fields. Failed to Create Invoice.', - }; - } - - // Prepare data for insertion into the database - const { customerId, amount, status } = validatedFields.data; - const amountInCents = amount * 100; - const date = new Date().toISOString().split('T')[0]; - - // Insert data into the database - try { - await sql` - INSERT INTO invoices (customer_id, amount, status, date) - VALUES (${customerId}, ${amountInCents}, ${status}, ${date}) - `; - } catch { - // If a database error occurs, return a more specific error. - return { - message: 'Database Error: Failed to Create Invoice.', - }; - } - - // Revalidate the cache for the invoices page and redirect the user. - revalidatePath('/dashboard/invoices'); - redirect('/dashboard/invoices'); -} - -const UpdateInvoice = FormSchema.omit({ id: true, date: true }); -export async function updateInvoice( - id: string, - _prevState: State, - formData: FormData, -) { - const validatedFields = UpdateInvoice.safeParse({ - customerId: formData.get('customerId'), - amount: formData.get('amount'), - status: formData.get('status'), - }); - - if (!validatedFields.success) { - return { - errors: validatedFields.error.flatten().fieldErrors, - message: 'Missing Fields. Failed to Update Invoice.', - }; - } - - const { customerId, amount, status } = validatedFields.data; - const amountInCents = amount * 100; - - try { - await sql` - UPDATE invoices - SET customer_id = ${customerId}, amount = ${amountInCents}, status = ${status} - WHERE id = ${id} - `; - } catch { - return { message: 'Database Error: Failed to Update Invoice.' }; - } - - revalidatePath('/dashboard/invoices'); - redirect('/dashboard/invoices'); -} -export async function deleteInvoice(id: string) { - try { - await sql`DELETE FROM invoices WHERE id = ${id}`; - revalidatePath('/dashboard/invoices'); - return { message: 'Deleted Invoice.' }; - } catch { - return { message: 'Database Error: Failed to Delete Invoice.' }; - } -} - diff --git a/src/bootstrap/i18n/dictionaries/en.ts b/src/bootstrap/i18n/dictionaries/en.ts index 3bd88ce..3f0f60c 100644 --- a/src/bootstrap/i18n/dictionaries/en.ts +++ b/src/bootstrap/i18n/dictionaries/en.ts @@ -3,6 +3,7 @@ import langKey from "@/bootstrap/i18n/dictionaries/lang-key" const en: typeof langKey = { global: { home: "Home", + loading: "Loading", dashboard: "Dashboard" }, dashboard: { diff --git a/src/bootstrap/i18n/dictionaries/lang-key.ts b/src/bootstrap/i18n/dictionaries/lang-key.ts index aed439c..69ca04e 100644 --- a/src/bootstrap/i18n/dictionaries/lang-key.ts +++ b/src/bootstrap/i18n/dictionaries/lang-key.ts @@ -1,11 +1,12 @@ const langKey = { global: { - home: "Дом", - dashboard: "Панель приборов" + home: "global.home", + dashboard: "global.dashboard", + loading: "global.loading" }, dashboard: { invoice: { - createButton: "Создать случайный счет-фактуру" + createButton: "dashboard.invoice.createButton" } } } diff --git a/src/bootstrap/i18n/dictionaries/ru.ts b/src/bootstrap/i18n/dictionaries/ru.ts index 5b6c4b4..9c8e561 100644 --- a/src/bootstrap/i18n/dictionaries/ru.ts +++ b/src/bootstrap/i18n/dictionaries/ru.ts @@ -3,6 +3,7 @@ import langKey from "@/bootstrap/i18n/dictionaries/lang-key" const ru: typeof langKey = { global: { home: "Дом", + loading: "Загрузка", dashboard: "Панель приборов" }, dashboard: { diff --git a/src/bootstrap/i18n/i18n-provider.tsx b/src/bootstrap/i18n/i18n-provider.tsx new file mode 100644 index 0000000..d15b347 --- /dev/null +++ b/src/bootstrap/i18n/i18n-provider.tsx @@ -0,0 +1,13 @@ +"use client" +import { I18nextProvider } from "react-i18next" +import { initI18next } from "@/bootstrap/i18n/i18n"; +import { createInstance, Resource } from "i18next"; +import { PropsWithChildren } from "react"; + +export default function TranslationsProvider({children, lng, resources}: PropsWithChildren & {lng: string; resources: Resource}) { + const i18n = createInstance() + + initI18next({lng, i18n, resources}) + + return <I18nextProvider i18n={i18n}>{children}</I18nextProvider> +} \ No newline at end of file diff --git a/src/bootstrap/i18n/i18n.ts b/src/bootstrap/i18n/i18n.ts index 9cc5fb0..edd45d5 100644 --- a/src/bootstrap/i18n/i18n.ts +++ b/src/bootstrap/i18n/i18n.ts @@ -1,19 +1,32 @@ -import { getOptions } from '@/bootstrap/i18n/settings' -import { createInstance } from 'i18next' +import { getOptions, languages } from '@/bootstrap/i18n/settings' +import { createInstance, i18n, Resource } from 'i18next' import resourcesToBackend from 'i18next-resources-to-backend' import { initReactI18next } from 'react-i18next/initReactI18next' -const initI18next = async (lng: string, ns?: string) => { - const i18nInstance = createInstance() +export const initI18next = async (params: {lng: string, i18n?: i18n, resources?: Resource, ns?: string}) => { + const { lng, i18n, ns, resources } = params + const i18nInstance = i18n ? i18n : createInstance() await i18nInstance .use(initReactI18next) .use(resourcesToBackend((language: string) => import(`./dictionaries/${language}.ts`))) - .init(getOptions(lng, ns)) - return i18nInstance + .init({ + ...getOptions(lng, ns), + resources, + preload: resources ? [] : languages + },) + + await i18nInstance.init() + + return { + i18n: i18nInstance, + resources: i18nInstance.services.resourceStore.data, + t: i18nInstance.t + } } -export async function getTranslation(lng: string, ns?: string, options: {keyPrefix?: string} = {}) { - const i18nextInstance = await initI18next(lng, ns) +export async function getServerTranslation(lng: string, ns?: string, options: {keyPrefix?: string} = {}) { + const i18nextInstance = (await initI18next({lng, ns})).i18n + return { t: i18nextInstance.getFixedT(lng, Array.isArray(ns) ? ns[0] : ns, options?.keyPrefix), i18n: i18nextInstance diff --git a/src/bootstrap/i18n/settings.ts b/src/bootstrap/i18n/settings.ts index 90f4fa0..7e3030b 100644 --- a/src/bootstrap/i18n/settings.ts +++ b/src/bootstrap/i18n/settings.ts @@ -1,6 +1,7 @@ export const fallbackLng = 'en' export const languages = [fallbackLng, 'ru'] export const defaultNS = 'translation' +export const cookieName = 'i18next' export function getOptions (lng = fallbackLng, ns = defaultNS) { return { diff --git a/src/middleware.ts b/src/middleware.ts index ee54225..8c6f760 100644 --- a/src/middleware.ts +++ b/src/middleware.ts @@ -1,23 +1,36 @@ -import { fallbackLng, languages } from "@/bootstrap/i18n/settings"; -import { NextRequest, NextResponse } from "next/server"; - -export function middleware(request: NextRequest) { - const { pathname } = request.nextUrl - const pathnameHasLocale = languages.some( - (lang) => pathname.startsWith(`/${lang}/`) || pathname === `/${lang}` - ) - - if (pathnameHasLocale) return - - request.nextUrl.pathname = `/${fallbackLng}${pathname}` - // e.g. incoming request is /products - // The new URL is now /en-US/products - return NextResponse.redirect(request.nextUrl) -} - +import { NextRequest, NextResponse } from 'next/server' +import acceptLanguage from 'accept-language' +import { cookieName, fallbackLng, languages } from '@/bootstrap/i18n/settings' + +acceptLanguage.languages(languages) + export const config = { - matcher: [ - // Skip all internal paths (_next) - '/((?!api|_next/static|_next/image|favicon.ico).*)' - ], + matcher: ["/((?!api|static|.*\\..*|_next).*)"] +} + +export function middleware(req: NextRequest) { + let lng + if (req.cookies.has(cookieName)) lng = acceptLanguage.get(req?.cookies?.get(cookieName)?.value) + if (!lng) lng = acceptLanguage.get(req.headers.get('Accept-Language')) + if (!lng) lng = fallbackLng + + // Redirect if lng in path is not supported + if ( + !languages.some(loc => req.nextUrl.pathname.startsWith(`/${loc}`)) && + !req.nextUrl.pathname.startsWith('/_next') + ) { + return NextResponse.redirect(new URL(`/${lng}${req.nextUrl.pathname}`, req.url)) + } + + if (req.headers.has('referer')) { + const refererUrl = new URL(req?.headers?.get('referer') ?? "") + const lngInReferer = languages.find((l) => refererUrl.pathname.startsWith(`/${l}`)) + const response = NextResponse.next() + if (lngInReferer) { + response.cookies.set(cookieName, lngInReferer) + } + return response + } + + return NextResponse.next() } \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 4fc4079..cac9504 100644 --- a/yarn.lock +++ b/yarn.lock @@ -334,6 +334,13 @@ resolved "https://registry.yarnpkg.com/@faker-js/faker/-/faker-9.1.0.tgz#5d7957df87e2fb0eee5dcfd311ba83b34ec8eead" integrity sha512-GJvX9iM9PBtKScJVlXQ0tWpihK3i0pha/XAhzQa1hPK/ILLa1Wq3I63Ij7lRtqTwmdTxRCyrUhLC5Sly9SLbug== +"@formatjs/intl-localematcher@^0.5.2": + version "0.5.6" + resolved "https://registry.yarnpkg.com/@formatjs/intl-localematcher/-/intl-localematcher-0.5.6.tgz#cd0cd99483673d3196a15b4e2c924cfda7f002f8" + integrity sha512-roz1+Ba5e23AHX6KUAWmLEyTRZegM5YDuxuvkHCyK3RJddf/UXB2f+s7pOMm9ktfPGla0g+mQXOn5vsuYirnaA== + dependencies: + tslib "2" + "@heroicons/react@^2.1.5": version "2.1.5" resolved "https://registry.yarnpkg.com/@heroicons/react/-/react-2.1.5.tgz#1e13f34976cc542deae92353c01c8b3d7942e9ba" @@ -801,11 +808,24 @@ dependencies: "@babel/types" "^7.20.7" +"@types/cookie@^0.6.0": + version "0.6.0" + resolved "https://registry.yarnpkg.com/@types/cookie/-/cookie-0.6.0.tgz#eac397f28bf1d6ae0ae081363eca2f425bedf0d5" + integrity sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA== + "@types/estree@1.0.6", "@types/estree@^1.0.0": version "1.0.6" resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.6.tgz#628effeeae2064a1b4e79f78e81d87b7e5fc7b50" integrity sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw== +"@types/hoist-non-react-statics@^3.3.5": + version "3.3.5" + resolved "https://registry.yarnpkg.com/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.5.tgz#dab7867ef789d87e2b4b0003c9d65c49cc44a494" + integrity sha512-SbcrWzkKBw2cdwRTwQAswfpB9g9LJWfjtUeW/jvNwbhC8cpmmNYVePa+ncbUe0rGTQ7G3Ff6mYUN2VMfLVr+Sg== + dependencies: + "@types/react" "*" + hoist-non-react-statics "^3.3.0" + "@types/json5@^0.0.29": version "0.0.29" resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" @@ -999,6 +1019,13 @@ abbrev@1: resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== +accept-language@^3.0.20: + version "3.0.20" + resolved "https://registry.yarnpkg.com/accept-language/-/accept-language-3.0.20.tgz#e825601d3b59f5ac7487698569b6640e80240cda" + integrity sha512-xklPzRma4aoDEPk0ZfMjeuxB2FP4JBYlAR25OFUqCoOYDjYo6wGwAs49SnTN/MoB5VpnNX9tENfZ+vEIFmHQMQ== + dependencies: + bcp47 "^1.1.2" + acorn-jsx@^5.3.2: version "5.3.2" resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" @@ -1234,6 +1261,11 @@ balanced-match@^1.0.0: resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== +bcp47@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/bcp47/-/bcp47-1.1.2.tgz#354be3307ffd08433a78f5e1e2095845f89fc7fe" + integrity sha512-JnkkL4GUpOvvanH9AZPX38CxhiLsXMBicBY2IAtqiVN8YulGDQybUydWA4W6yAMtw6iShtw+8HEF6cfrTHU+UQ== + bcrypt@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/bcrypt/-/bcrypt-5.1.1.tgz#0f732c6dcb4e12e5b70a25e326a72965879ba6e2" @@ -1443,6 +1475,11 @@ convert-source-map@^2.0.0: resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a" integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg== +cookie@^0.7.2: + version "0.7.2" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.7.2.tgz#556369c472a2ba910f2979891b526b3436237ed7" + integrity sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w== + cross-spawn@^7.0.0, cross-spawn@^7.0.2: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" @@ -2335,6 +2372,13 @@ hasown@^2.0.0, hasown@^2.0.1, hasown@^2.0.2: dependencies: function-bind "^1.1.2" +hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.2: + version "3.3.2" + resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45" + integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw== + dependencies: + react-is "^16.7.0" + html-encoding-sniffer@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz#696df529a7cfd82446369dc5193e590a3735b448" @@ -2373,6 +2417,13 @@ https-proxy-agent@^7.0.5: agent-base "^7.0.2" debug "4" +i18next-browser-languagedetector@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/i18next-browser-languagedetector/-/i18next-browser-languagedetector-8.0.0.tgz#b6fdd9b43af67c47f2c26c9ba27710a1eaf31e2f" + integrity sha512-zhXdJXTTCoG39QsrOCiOabnWj2jecouOqbchu3EfhtSHxIB5Uugnm9JaizenOy39h7ne3+fLikIjeW88+rgszw== + dependencies: + "@babel/runtime" "^7.23.2" + i18next-resources-to-backend@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/i18next-resources-to-backend/-/i18next-resources-to-backend-1.2.1.tgz#fded121e63e3139ce839c9901b9449dbbea7351d" @@ -2956,6 +3007,19 @@ natural-compare@^1.4.0: resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== +negotiator@^0.6.3: + version "0.6.4" + resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.4.tgz#777948e2452651c570b712dd01c23e262713fff7" + integrity sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w== + +next-i18n-router@^5.5.1: + version "5.5.1" + resolved "https://registry.yarnpkg.com/next-i18n-router/-/next-i18n-router-5.5.1.tgz#3d4c34d431e38aa4ba8f52cd54d4387fc70db6d2" + integrity sha512-uJGYUAQS33LbRT3Jx+kurR/E79iPQo1jWZUYmc+614UkPt58k2XYyGloSvHR74b21i4K/d6eksdBj6T2WojjdA== + dependencies: + "@formatjs/intl-localematcher" "^0.5.2" + negotiator "^0.6.3" + next@15.0.2: version "15.0.2" resolved "https://registry.yarnpkg.com/next/-/next-15.0.2.tgz#4a2224c007856118010b8cef5e9b2383cd743388" @@ -3305,6 +3369,15 @@ queue-microtask@^1.2.2: resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== +react-cookie@^7.2.2: + version "7.2.2" + resolved "https://registry.yarnpkg.com/react-cookie/-/react-cookie-7.2.2.tgz#a7559e552ea9cca39a4b3686723a5acf504b8f84" + integrity sha512-e+hi6axHcw9VODoeVu8WyMWyoosa1pzpyjfvrLdF7CexfU+WSGZdDuRfHa4RJgTpfv3ZjdIpHE14HpYBieHFhg== + dependencies: + "@types/hoist-non-react-statics" "^3.3.5" + hoist-non-react-statics "^3.3.2" + universal-cookie "^7.0.0" + react-dom@19.0.0-rc-69d4b800-20241021: version "19.0.0-rc-69d4b800-20241021" resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-19.0.0-rc-69d4b800-20241021.tgz#e27b4f2c962236e9ece496a0ea1c9c7161608ea0" @@ -3320,7 +3393,7 @@ react-i18next@^15.1.0: "@babel/runtime" "^7.25.0" html-parse-stringify "^3.0.1" -react-is@^16.13.1: +react-is@^16.13.1, react-is@^16.7.0: version "16.13.1" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== @@ -3968,7 +4041,7 @@ tsconfig-paths@^3.15.0: minimist "^1.2.6" strip-bom "^3.0.0" -tslib@*, tslib@^2.4.0: +tslib@*, tslib@2, tslib@^2.4.0: version "2.8.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== @@ -4061,6 +4134,14 @@ undici-types@~6.19.2: resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.19.8.tgz#35111c9d1437ab83a7cdc0abae2f26d88eda0a02" integrity sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw== +universal-cookie@^7.0.0: + version "7.2.2" + resolved "https://registry.yarnpkg.com/universal-cookie/-/universal-cookie-7.2.2.tgz#93ae9ec55baab89b24300473543170bb8112773c" + integrity sha512-fMiOcS3TmzP2x5QV26pIH3mvhexLIT0HmPa3V7Q7knRfT9HG6kTwq02HZGLPw0sAOXrAmotElGRvTLCMbJsvxQ== + dependencies: + "@types/cookie" "^0.6.0" + cookie "^0.7.2" + update-browserslist-db@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz#80846fba1d79e82547fb661f8d141e0945755fe5" -- 2.39.5 From 55c82982370af8f3a1ea44738ec1fca930d50785 Mon Sep 17 00:00:00 2001 From: behnam <behnamrahimpour74@gmail.com> Date: Fri, 15 Nov 2024 19:44:26 +0300 Subject: [PATCH 33/37] Fix linting issues --- .eslintrc.json | 84 ++++++++- package.json | 8 +- .../create-random-invoice.tsx | 18 +- .../client/nav-links/nav-link-controller.ts | 29 --- .../client/nav-links/nav-link-vm.ts | 28 +++ .../components/client/nav-links/nav-links.tsx | 15 +- .../components/server/card/card-controller.ts | 28 +-- .../dashboard/components/server/card/card.tsx | 12 +- .../server/cards/cards-controller.ts | 4 +- .../components/server/cards/cards.tsx | 18 +- .../latest-invoices-controller.ts | 6 +- .../latest-invoices/latest-invoices.tsx | 90 ++++----- .../revenue-chart/revenue-chart-controller.ts | 6 +- .../server/revenue-chart/revenue-chart.tsx | 13 +- .../dashboard/components/server/sidenav.tsx | 10 +- .../components/server/skeletons/skeletons.tsx | 47 ++--- src/app/[lang]/dashboard/layout.tsx | 12 +- src/app/[lang]/dashboard/loading.tsx | 2 +- .../dashboard/module/dashboard-app-module.ts | 19 +- src/app/[lang]/dashboard/page.tsx | 22 ++- .../vm/create-random-invoice-button-vm.ts | 69 +++---- src/app/[lang]/layout.tsx | 16 +- src/app/[lang]/page.tsx | 10 +- src/app/components/button/button-vm.ts | 12 +- src/app/components/button/button.tsx | 43 +++-- src/app/components/icons/document.tsx | 25 ++- src/app/components/icons/home.tsx | 25 ++- src/app/components/icons/user.tsx | 26 ++- src/app/layout.tsx | 3 +- src/bootstrap/boundaries/db/db.ts | 13 +- .../boundaries/db/placeholder-data.js | 172 +++++++++--------- src/bootstrap/boundaries/db/seed.js | 21 ++- src/bootstrap/di/di-context.tsx | 22 +-- src/bootstrap/di/init-di.ts | 4 +- src/bootstrap/helpers/global-helpers.ts | 3 +- .../helpers/hooks/use-server-action.ts | 8 +- src/bootstrap/helpers/hooks/use-throttle.ts | 28 +-- src/bootstrap/helpers/lib/ui-utils.ts | 6 +- src/bootstrap/helpers/type-helper.ts | 2 +- src/bootstrap/helpers/view/base-view.tsx | 17 +- src/bootstrap/helpers/vm/base-vm.ts | 6 +- src/bootstrap/i18n/dictionaries/en.ts | 24 +-- src/bootstrap/i18n/dictionaries/lang-key.ts | 22 +-- src/bootstrap/i18n/dictionaries/ru.ts | 24 +-- src/bootstrap/i18n/i18n-provider.tsx | 19 +- src/bootstrap/i18n/i18n.ts | 71 +++++--- src/bootstrap/i18n/settings.ts | 16 +- src/feature/common/data/api-task.ts | 7 +- src/feature/common/failures/base-failure.ts | 4 +- .../common/failures/dev/arguments-failure.ts | 4 +- .../common/failures/dev/base-dev-failure.ts | 4 +- .../common/failures/dev/dependency-failure.ts | 4 +- src/feature/common/failures/params-failure.ts | 2 +- src/feature/common/feature-helpers.ts | 9 +- src/feature/common/server-di.ts | 30 +-- .../data/module/customer-invoice-di.ts | 8 +- .../data/repo/customer-invoice-db-repo.ts | 59 +++--- .../domain/entity/customer-invoice.ts | 42 +++-- .../domain/i-repo/customer-invoice-repo.ts | 8 +- .../fetch-customer-invoices-usecase.ts | 18 +- .../customer-invoice/invoice-module-key.ts | 2 +- src/feature/core/customer/customer-key.ts | 2 +- .../core/customer/data/module/customer-di.ts | 8 +- .../customer/data/repo/customer-db-repo.ts | 104 ++++++----- .../core/customer/domain/entity/customer.ts | 56 +++--- .../customer/domain/i-repo/customer-repo.ts | 10 +- .../usecase/fetch-customers-amount-usecase.ts | 10 +- .../domain/usecase/fetch-customers-usecase.ts | 19 +- .../core/invoice/data/module/invoice-di.ts | 8 +- .../core/invoice/data/repo/invoice-db-repo.ts | 85 ++++----- .../invoice/domain/i-repo/invoice-repo.ts | 14 +- .../invoice/domain/param/invoice-param.ts | 10 +- .../domain/usecase/create-invoice-usecase.ts | 40 ++-- .../fetch-all-invoices-amount-usecase.ts | 13 +- .../usecase/fetch-invoices-status-summary.ts | 10 +- .../domain/value-object/invoice-status.ts | 18 +- .../core/invoice/invoice-module-key.ts | 2 +- .../core/revenue/data/module/revenue-di.ts | 14 +- .../core/revenue/data/repo/revenue-db-repo.ts | 48 +++-- .../core/revenue/domain/entity/revenue.ts | 20 +- .../revenue/domain/i-repo/revenue-repo.ts | 4 +- .../core/revenue/domain/revenue-module-key.ts | 2 +- .../domain/usecase/fetch-revenues-usecase.ts | 10 +- .../data/module/summary-info-di.ts | 32 ++-- .../domain/summary-info-module-key.ts | 2 +- .../usecase/fetch-summary-info-usecase.ts | 49 ++--- .../domain/value-object/summary-info.ts | 28 +-- src/middleware.ts | 47 ++--- .../customer/customer-fake-factory.ts | 33 ++-- src/test/common/mock/mock-di.ts | 10 +- src/test/setup.ts | 2 +- .../usecase/fetch-customers-usecase.test.ts | 55 +++--- yarn.lock | 82 ++++++++- 93 files changed, 1268 insertions(+), 958 deletions(-) delete mode 100644 src/app/[lang]/dashboard/components/client/nav-links/nav-link-controller.ts create mode 100644 src/app/[lang]/dashboard/components/client/nav-links/nav-link-vm.ts diff --git a/.eslintrc.json b/.eslintrc.json index 60d067f..6307415 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -9,5 +9,87 @@ } } ], - "extends": ["next/core-web-vitals", "next/typescript"] + "plugins": [ + "prettier" + ], + "settings": { + "react": { + "version": "detect" + }, + "import/resolver": { + "alias": { + "map": [ + [ + "~", + "./src" + ] + ], + "extensions": [ + ".js", + ".ts", + ".tsx", + ".d.ts", + ".test.ts", + ".json" + ] + } + } + }, + "rules": { + "no-use-before-define": "off", + "class-methods-use-this": "off", + "import/prefer-default-export": "off", + "import/no-cycle": "off", + "no-promise-executor-return": "off", + "@typescript-eslint/no-shadow": "off", + "react/require-default-props": "off", + "no-shadow": "off", + "prettier/prettier": [ + "warn", + { + "printWidth": 80, + "tabWidth": 2, + "endOfLine":"auto", + "useTabs": false, + "semi": true, + "singleQuote": false, + "quoteProps": "as-needed", + "jsxSingleQuote": false, + "trailingComma": "all", + "bracketSpacing": true, + "arrowParens": "always" + } + ], + "import/extensions": [ + "error", + "ignorePackages", + { + "js": "never", + "jsx": "never", + "ts": "never", + "tsx": "never" + } + ], + "react/jsx-filename-extension": [ + 1, + { + "extensions": [ + ".ts", + ".tsx" + ] + } + ], + "import/no-extraneous-dependencies": [ + "error", + { + "devDependencies": true + } + ] + }, + "extends": [ + "airbnb", + "next/core-web-vitals", + "next/typescript", + "prettier" + ] } diff --git a/package.json b/package.json index 818e3a6..3223cf1 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "dev": "next dev --turbopack", "build": "next build", "start": "next start --port 4000", - "lint": "next lint", + "lint": "next lint --fix", "test": "vitest", "seed": "node -r dotenv/config ./src/bootstrap/boundaries/db/seed.js" }, @@ -46,10 +46,16 @@ "bcrypt": "^5.1.1", "dotenv": "^16.4.5", "eslint": "^8", + "eslint-config-airbnb": "^19.0.4", "eslint-config-next": "15.0.1", + "eslint-config-prettier": "^9.1.0", + "eslint-import-resolver-alias": "^1.1.2", + "eslint-import-resolver-typescript": "^3.6.3", + "eslint-plugin-prettier": "^5.2.1", "jsdom": "^25.0.1", "moq.ts": "^10.0.8", "postcss": "^8", + "prettier": "^3.3.3", "tailwindcss": "^3.4.1", "typescript": "^5", "vitest": "^2.1.4" diff --git a/src/app/[lang]/dashboard/components/client/create-random-invoice/create-random-invoice.tsx b/src/app/[lang]/dashboard/components/client/create-random-invoice/create-random-invoice.tsx index f3f95a4..68742c2 100644 --- a/src/app/[lang]/dashboard/components/client/create-random-invoice/create-random-invoice.tsx +++ b/src/app/[lang]/dashboard/components/client/create-random-invoice/create-random-invoice.tsx @@ -1,13 +1,13 @@ -"use client" +"use client"; -import Button from "@/app/components/button/button" -import CreateRandomInvoiceButtonVM from "@/app/[lang]/dashboard/vm/create-random-invoice-button-vm" -import { useDI } from "@/bootstrap/di/di-context" -import { useRef } from "react" +import Button from "@/app/components/button/button"; +import CreateRandomInvoiceButtonVM from "@/app/[lang]/dashboard/vm/create-random-invoice-button-vm"; +import { useDI } from "@/bootstrap/di/di-context"; +import { useRef } from "react"; export default function CreateRandomInvoiceContainer() { - const di = useDI() - const vm = useRef(di.resolve(CreateRandomInvoiceButtonVM)) + const di = useDI(); + const vm = useRef(di.resolve(CreateRandomInvoiceButtonVM)); - return <Button vm={vm.current}/> -} \ No newline at end of file + return <Button vm={vm.current} />; +} diff --git a/src/app/[lang]/dashboard/components/client/nav-links/nav-link-controller.ts b/src/app/[lang]/dashboard/components/client/nav-links/nav-link-controller.ts deleted file mode 100644 index b6a3aa9..0000000 --- a/src/app/[lang]/dashboard/components/client/nav-links/nav-link-controller.ts +++ /dev/null @@ -1,29 +0,0 @@ - -import { DocumentIcon } from '@/app/components/icons/document'; -import HomeIcon from '@/app/components/icons/home'; -import { UserIcon } from '@/app/components/icons/user'; -import { usePathname } from 'next/navigation'; - -type LinkItem = { - name: string; - href: string; - icon: (props: {className?: string}) => JSX.Element -} -export default function navLinkPersonalVM() { - const pathname = usePathname() - // Map of links to display in the side navigation. - // Depending on the size of the application, this would be stored in a database. - const links: LinkItem[] = [ - { name: 'Home', href: '/dashboard', icon: HomeIcon }, - { - name: 'Invoices', - href: '/dashboard/invoices', - icon: DocumentIcon, - }, - { name: 'Customers', href: '/dashboard/customers', icon: UserIcon }, - ]; - return { - links, - isLinkActive: (link: LinkItem) => pathname === link.href - } -} \ No newline at end of file diff --git a/src/app/[lang]/dashboard/components/client/nav-links/nav-link-vm.ts b/src/app/[lang]/dashboard/components/client/nav-links/nav-link-vm.ts new file mode 100644 index 0000000..bdf58b2 --- /dev/null +++ b/src/app/[lang]/dashboard/components/client/nav-links/nav-link-vm.ts @@ -0,0 +1,28 @@ +import { DocumentIcon } from "@/app/components/icons/document"; +import HomeIcon from "@/app/components/icons/home"; +import { UserIcon } from "@/app/components/icons/user"; +import { usePathname } from "next/navigation"; + +type LinkItem = { + name: string; + href: string; + icon: (props: { className?: string }) => JSX.Element; +}; +export default function navLinkPersonalVM() { + const pathname = usePathname(); + // Map of links to display in the side navigation. + // Depending on the size of the application, this would be stored in a database. + const links: LinkItem[] = [ + { name: "Home", href: "/dashboard", icon: HomeIcon }, + { + name: "Invoices", + href: "/dashboard/invoices", + icon: DocumentIcon, + }, + { name: "Customers", href: "/dashboard/customers", icon: UserIcon }, + ]; + return { + links, + isLinkActive: (link: LinkItem) => pathname === link.href, + }; +} diff --git a/src/app/[lang]/dashboard/components/client/nav-links/nav-links.tsx b/src/app/[lang]/dashboard/components/client/nav-links/nav-links.tsx index 6aa2ce8..edb724c 100644 --- a/src/app/[lang]/dashboard/components/client/nav-links/nav-links.tsx +++ b/src/app/[lang]/dashboard/components/client/nav-links/nav-links.tsx @@ -1,10 +1,11 @@ -'use client' -import navLinkPersonalVM from '@/app/[lang]/dashboard/components/client/nav-links/nav-link-controller'; -import clsx from 'clsx'; -import Link from 'next/link' +"use client"; + +import navLinkPersonalVM from "@/app/[lang]/dashboard/components/client/nav-links/nav-link-vm"; +import clsx from "clsx"; +import Link from "next/link"; export default function NavLinks() { - const { links, isLinkActive } = navLinkPersonalVM() + const { links, isLinkActive } = navLinkPersonalVM(); return ( <> {links.map((link) => { @@ -14,9 +15,9 @@ export default function NavLinks() { key={link.name} href={link.href} className={clsx( - 'flex h-[48px] grow items-center justify-center gap-2 rounded-md bg-gray-50 p-3 text-sm font-medium hover:bg-sky-100 hover:text-blue-600 md:flex-none md:justify-start md:p-2 md:px-3', + "flex h-[48px] grow items-center justify-center gap-2 rounded-md bg-gray-50 p-3 text-sm font-medium hover:bg-sky-100 hover:text-blue-600 md:flex-none md:justify-start md:p-2 md:px-3", { - 'bg-sky-100 text-blue-600': isLinkActive(link), + "bg-sky-100 text-blue-600": isLinkActive(link), }, )} > diff --git a/src/app/[lang]/dashboard/components/server/card/card-controller.ts b/src/app/[lang]/dashboard/components/server/card/card-controller.ts index 43c40f7..5f28e88 100644 --- a/src/app/[lang]/dashboard/components/server/card/card-controller.ts +++ b/src/app/[lang]/dashboard/components/server/card/card-controller.ts @@ -3,17 +3,19 @@ import { ClockIcon, UserGroupIcon, InboxIcon, -} from '@heroicons/react/24/outline'; +} from "@heroicons/react/24/outline"; -export default function cardController(props: { type: 'invoices' | 'customers' | 'pending' | 'collected'; }) { - const { type } = props - const iconMap = { - collected: BanknotesIcon, - customers: UserGroupIcon, - pending: ClockIcon, - invoices: InboxIcon, - }; - return { - Icon: iconMap[type] - } -} \ No newline at end of file +export default function cardController(props: { + type: "invoices" | "customers" | "pending" | "collected"; +}) { + const { type } = props; + const iconMap = { + collected: BanknotesIcon, + customers: UserGroupIcon, + pending: ClockIcon, + invoices: InboxIcon, + }; + return { + Icon: iconMap[type], + }; +} diff --git a/src/app/[lang]/dashboard/components/server/card/card.tsx b/src/app/[lang]/dashboard/components/server/card/card.tsx index 303eaec..0bb192a 100644 --- a/src/app/[lang]/dashboard/components/server/card/card.tsx +++ b/src/app/[lang]/dashboard/components/server/card/card.tsx @@ -1,7 +1,5 @@ import cardController from "@/app/[lang]/dashboard/components/server/card/card-controller"; - - export function Card({ title, value, @@ -9,9 +7,9 @@ export function Card({ }: { title: string; value: number | string; - type: 'invoices' | 'customers' | 'pending' | 'collected'; + type: "invoices" | "customers" | "pending" | "collected"; }) { - const { Icon } = cardController({type}) + const { Icon } = cardController({ type }); return ( <div className="rounded-xl bg-gray-50 p-2 shadow-sm"> @@ -19,11 +17,9 @@ export function Card({ {Icon ? <Icon className="h-5 w-5 text-gray-700" /> : null} <h3 className="ml-2 text-sm font-medium">{title}</h3> </div> - <p - className="rounded-xl bg-white px-4 py-8 text-center text-2xl" - > + <p className="rounded-xl bg-white px-4 py-8 text-center text-2xl"> {value} </p> </div> ); -} \ No newline at end of file +} diff --git a/src/app/[lang]/dashboard/components/server/cards/cards-controller.ts b/src/app/[lang]/dashboard/components/server/cards/cards-controller.ts index b8aaf19..53c601a 100644 --- a/src/app/[lang]/dashboard/components/server/cards/cards-controller.ts +++ b/src/app/[lang]/dashboard/components/server/cards/cards-controller.ts @@ -1,5 +1,5 @@ import fetchSummaryInfoUsecase from "@/feature/core/summary-info/domain/usecase/fetch-summary-info-usecase"; export default function cardsController() { - return fetchSummaryInfoUsecase(); -} \ No newline at end of file + return fetchSummaryInfoUsecase(); +} diff --git a/src/app/[lang]/dashboard/components/server/cards/cards.tsx b/src/app/[lang]/dashboard/components/server/cards/cards.tsx index a0aea58..91c641d 100644 --- a/src/app/[lang]/dashboard/components/server/cards/cards.tsx +++ b/src/app/[lang]/dashboard/components/server/cards/cards.tsx @@ -1,20 +1,16 @@ -import { Card } from '@/app/[lang]/dashboard/components/server/card/card'; -import cardsController from '@/app/[lang]/dashboard/components/server/cards/cards-controller'; - +import { Card } from "@/app/[lang]/dashboard/components/server/card/card"; +import cardsController from "@/app/[lang]/dashboard/components/server/cards/cards-controller"; export default async function CardWrapper() { - const {customersNumber, invoicesNumber, invoicesSummary } = await cardsController(); - + const { customersNumber, invoicesNumber, invoicesSummary } = + await cardsController(); + return ( <> <Card title="Collected" value={invoicesSummary.paid} type="collected" /> <Card title="Pending" value={invoicesSummary.pending} type="pending" /> <Card title="Total Invoices" value={invoicesNumber} type="invoices" /> - <Card - title="Total Customers" - value={customersNumber} - type="customers" - /> + <Card title="Total Customers" value={customersNumber} type="customers" /> </> ); -} \ No newline at end of file +} diff --git a/src/app/[lang]/dashboard/components/server/latest-invoices/latest-invoices-controller.ts b/src/app/[lang]/dashboard/components/server/latest-invoices/latest-invoices-controller.ts index 8fbbde9..9f34a9a 100644 --- a/src/app/[lang]/dashboard/components/server/latest-invoices/latest-invoices-controller.ts +++ b/src/app/[lang]/dashboard/components/server/latest-invoices/latest-invoices-controller.ts @@ -1,5 +1,5 @@ import fetchCustomerInvoicesUsecase from "@/feature/core/customer-invoice/domain/usecase/fetch-customer-invoices-usecase"; -export default async function latestInvoicesController() { - return await fetchCustomerInvoicesUsecase() -} \ No newline at end of file +export default function latestInvoicesController() { + return fetchCustomerInvoicesUsecase(); +} diff --git a/src/app/[lang]/dashboard/components/server/latest-invoices/latest-invoices.tsx b/src/app/[lang]/dashboard/components/server/latest-invoices/latest-invoices.tsx index 3c3e687..e55a6e1 100644 --- a/src/app/[lang]/dashboard/components/server/latest-invoices/latest-invoices.tsx +++ b/src/app/[lang]/dashboard/components/server/latest-invoices/latest-invoices.tsx @@ -1,61 +1,49 @@ -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 { ArrowPathIcon } from '@heroicons/react/24/outline'; -import clsx from 'clsx'; -import { isLeft } from 'fp-ts/lib/Either'; -import Image from 'next/image'; +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 { ArrowPathIcon } from "@heroicons/react/24/outline"; +import clsx from "clsx"; +import { isLeft } from "fp-ts/lib/Either"; +import Image from "next/image"; export default async function LatestInvoices() { const latestInvoices = await latestInvoicesController(); - if (isLeft(latestInvoices)) return <div>Error</div> - - const invoices = latestInvoices.right.map((invoice, i) => { - return ( - <div - key={invoice.id} - className={clsx( - 'flex flex-row items-center justify-between py-4', - { - 'border-t': i !== 0, - }, - )} - > - <div className="flex items-center"> - <Image - src={invoice.customerImageUrl} - alt={`${invoice.customerName}'s profile picture`} - className="mr-4 rounded-full" - width={32} - height={32} - /> - <div className="min-w-0"> - <p className="truncate text-sm font-semibold md:text-base"> - {invoice.customerName} - </p> - <p className="hidden text-sm text-gray-500 sm:block"> - {invoice.customerEmail} - </p> - </div> - </div> - <p - className="truncate text-sm font-medium md:text-base" - > - {invoice.invoicesAmount} - </p> - </div> - ); - }) + if (isLeft(latestInvoices)) return <div>Error</div>; + + const invoices = latestInvoices.right.map((invoice, i) => ( + <div + key={invoice.id} + className={clsx("flex flex-row items-center justify-between py-4", { + "border-t": i !== 0, + })} + > + <div className="flex items-center"> + <Image + src={invoice.customerImageUrl} + alt={`${invoice.customerName}'s profile picture`} + className="mr-4 rounded-full" + width={32} + height={32} + /> + <div className="min-w-0"> + <p className="truncate text-sm font-semibold md:text-base"> + {invoice.customerName} + </p> + <p className="hidden text-sm text-gray-500 sm:block"> + {invoice.customerEmail} + </p> + </div> + </div> + <p className="truncate text-sm font-medium md:text-base"> + {invoice.invoicesAmount} + </p> + </div> + )); return ( <div className="flex w-full flex-col md:col-span-4"> - <h2 className="mb-4 text-xl md:text-2xl"> - Latest Invoices - </h2> + <h2 className="mb-4 text-xl md:text-2xl">Latest Invoices</h2> <div className="flex grow flex-col max-h-[66.5vh] justify-between rounded-xl bg-gray-50 p-4"> - - <div className="bg-white px-6 h-full overflow-y-auto"> - {invoices} - </div> + <div className="bg-white px-6 h-full overflow-y-auto">{invoices}</div> <div className="flex items-end mt-auto pb-2 pt-6"> <ArrowPathIcon className="h-5 w-5 text-gray-500" /> <h3 className="ml-2 text-sm text-gray-500 ">Updated just now</h3> diff --git a/src/app/[lang]/dashboard/components/server/revenue-chart/revenue-chart-controller.ts b/src/app/[lang]/dashboard/components/server/revenue-chart/revenue-chart-controller.ts index becc678..55c0797 100644 --- a/src/app/[lang]/dashboard/components/server/revenue-chart/revenue-chart-controller.ts +++ b/src/app/[lang]/dashboard/components/server/revenue-chart/revenue-chart-controller.ts @@ -11,8 +11,8 @@ export default async function revenueChartController() { revenue, chartHeight, yAxisLabels, - topLabel - } + topLabel, + }; } function generateYAxis(revenue: Revenue[]) { @@ -27,4 +27,4 @@ function generateYAxis(revenue: Revenue[]) { } return { yAxisLabels, topLabel }; -}; +} diff --git a/src/app/[lang]/dashboard/components/server/revenue-chart/revenue-chart.tsx b/src/app/[lang]/dashboard/components/server/revenue-chart/revenue-chart.tsx index fb778f2..e6bc5a0 100644 --- a/src/app/[lang]/dashboard/components/server/revenue-chart/revenue-chart.tsx +++ b/src/app/[lang]/dashboard/components/server/revenue-chart/revenue-chart.tsx @@ -1,8 +1,9 @@ -import revenueChartController from '@/app/[lang]/dashboard/components/server/revenue-chart/revenue-chart-controller'; -import { CalendarIcon } from '@heroicons/react/24/outline'; +import revenueChartController from "@/app/[lang]/dashboard/components/server/revenue-chart/revenue-chart-controller"; +import { CalendarIcon } from "@heroicons/react/24/outline"; export default async function RevenueChart() { - const { chartHeight, revenue, topLabel, yAxisLabels } = await revenueChartController() + const { chartHeight, revenue, topLabel, yAxisLabels } = + await revenueChartController(); if (!revenue || revenue.length === 0) { return <p className="mt-4 text-gray-400">No data available.</p>; @@ -10,9 +11,7 @@ export default async function RevenueChart() { return ( <div className="w-full md:col-span-4"> - <h2 className={` mb-4 text-xl md:text-2xl`}> - Recent Revenue - </h2> + <h2 className={` mb-4 text-xl md:text-2xl`}>Recent Revenue</h2> <div className="rounded-xl bg-gray-50 p-4"> <div className="sm:grid-cols-13 mt-0 grid grid-cols-12 items-end gap-2 rounded-md bg-white p-4 md:gap-4"> <div @@ -31,7 +30,7 @@ export default async function RevenueChart() { style={{ height: `${(chartHeight / topLabel) * month.revenue}px`, }} - ></div> + /> <p className="-rotate-90 text-sm text-gray-400 sm:rotate-0"> {month.month} </p> diff --git a/src/app/[lang]/dashboard/components/server/sidenav.tsx b/src/app/[lang]/dashboard/components/server/sidenav.tsx index bc396c4..e89a0e6 100644 --- a/src/app/[lang]/dashboard/components/server/sidenav.tsx +++ b/src/app/[lang]/dashboard/components/server/sidenav.tsx @@ -1,5 +1,5 @@ -import NavLinks from '@/app/[lang]/dashboard/components/client/nav-links/nav-links'; -import Link from 'next/link'; +import NavLinks from "@/app/[lang]/dashboard/components/client/nav-links/nav-links"; +import Link from "next/link"; export default function SideNav() { return ( @@ -8,13 +8,11 @@ export default function SideNav() { className="mb-2 flex h-20 items-end justify-start rounded-md bg-blue-600 p-4 md:h-40" href="/" > - <div className="w-32 text-white md:w-40"> - Home - </div> + <div className="w-32 text-white md:w-40">Home</div> </Link> <div className="flex grow flex-row justify-between space-x-2 md:flex-col md:space-x-0 md:space-y-2"> <NavLinks /> - <div className="hidden h-auto w-full grow rounded-md bg-gray-50 md:block"></div> + <div className="hidden h-auto w-full grow rounded-md bg-gray-50 md:block" /> </div> </div> ); diff --git a/src/app/[lang]/dashboard/components/server/skeletons/skeletons.tsx b/src/app/[lang]/dashboard/components/server/skeletons/skeletons.tsx index 52b8a87..c7b2e60 100644 --- a/src/app/[lang]/dashboard/components/server/skeletons/skeletons.tsx +++ b/src/app/[lang]/dashboard/components/server/skeletons/skeletons.tsx @@ -1,6 +1,6 @@ // Loading animation const shimmer = - 'before:absolute before:inset-0 before:-translate-x-full before:animate-[shimmer_2s_infinite] before:bg-gradient-to-r before:from-transparent before:via-white/60 before:to-transparent'; + "before:absolute before:inset-0 before:-translate-x-full before:animate-[shimmer_2s_infinite] before:bg-gradient-to-r before:from-transparent before:via-white/60 before:to-transparent"; export function CardSkeleton() { return ( @@ -106,33 +106,36 @@ export function TableRowSkeleton() { return ( <tr className="w-full border-b border-gray-100 last-of-type:border-none [&:first-child>td:first-child]:rounded-tl-lg [&:first-child>td:last-child]:rounded-tr-lg [&:last-child>td:first-child]:rounded-bl-lg [&:last-child>td:last-child]:rounded-br-lg"> {/* Customer Name and Image */} - <td className="relative overflow-hidden whitespace-nowrap py-3 pl-6 pr-3"> + <td + aria-label="Customer name" + className="relative overflow-hidden whitespace-nowrap py-3 pl-6 pr-3" + > <div className="flex items-center gap-3"> - <div className="h-8 w-8 rounded-full bg-gray-100"></div> - <div className="h-6 w-24 rounded bg-gray-100"></div> + <div className="h-8 w-8 rounded-full bg-gray-100" /> + <div className="h-6 w-24 rounded bg-gray-100" /> </div> </td> {/* Email */} - <td className="whitespace-nowrap px-3 py-3"> - <div className="h-6 w-32 rounded bg-gray-100"></div> + <td aria-label="Email" className="whitespace-nowrap px-3 py-3"> + <div className="h-6 w-32 rounded bg-gray-100" /> </td> {/* Amount */} - <td className="whitespace-nowrap px-3 py-3"> - <div className="h-6 w-16 rounded bg-gray-100"></div> + <td aria-label="Amount" className="whitespace-nowrap px-3 py-3"> + <div className="h-6 w-16 rounded bg-gray-100" /> </td> {/* Date */} - <td className="whitespace-nowrap px-3 py-3"> - <div className="h-6 w-16 rounded bg-gray-100"></div> + <td aria-label="Date" className="whitespace-nowrap px-3 py-3"> + <div className="h-6 w-16 rounded bg-gray-100" /> </td> {/* Status */} - <td className="whitespace-nowrap px-3 py-3"> - <div className="h-6 w-16 rounded bg-gray-100"></div> + <td aria-label="Status" className="whitespace-nowrap px-3 py-3"> + <div className="h-6 w-16 rounded bg-gray-100" /> </td> {/* Actions */} - <td className="whitespace-nowrap py-3 pl-6 pr-3"> + <td aria-label="Actions" className="whitespace-nowrap py-3 pl-6 pr-3"> <div className="flex justify-end gap-3"> - <div className="h-[38px] w-[38px] rounded bg-gray-100"></div> - <div className="h-[38px] w-[38px] rounded bg-gray-100"></div> + <div className="h-[38px] w-[38px] rounded bg-gray-100" /> + <div className="h-[38px] w-[38px] rounded bg-gray-100" /> </div> </td> </tr> @@ -144,19 +147,19 @@ export function InvoicesMobileSkeleton() { <div className="mb-2 w-full rounded-md bg-white p-4"> <div className="flex items-center justify-between border-b border-gray-100 pb-8"> <div className="flex items-center"> - <div className="mr-2 h-8 w-8 rounded-full bg-gray-100"></div> - <div className="h-6 w-16 rounded bg-gray-100"></div> + <div className="mr-2 h-8 w-8 rounded-full bg-gray-100" /> + <div className="h-6 w-16 rounded bg-gray-100" /> </div> - <div className="h-6 w-16 rounded bg-gray-100"></div> + <div className="h-6 w-16 rounded bg-gray-100" /> </div> <div className="flex w-full items-center justify-between pt-4"> <div> - <div className="h-6 w-16 rounded bg-gray-100"></div> - <div className="mt-2 h-6 w-24 rounded bg-gray-100"></div> + <div className="h-6 w-16 rounded bg-gray-100" /> + <div className="mt-2 h-6 w-24 rounded bg-gray-100" /> </div> <div className="flex justify-end gap-2"> - <div className="h-10 w-10 rounded bg-gray-100"></div> - <div className="h-10 w-10 rounded bg-gray-100"></div> + <div className="h-10 w-10 rounded bg-gray-100" /> + <div className="h-10 w-10 rounded bg-gray-100" /> </div> </div> </div> diff --git a/src/app/[lang]/dashboard/layout.tsx b/src/app/[lang]/dashboard/layout.tsx index 4e678cf..308e2a7 100644 --- a/src/app/[lang]/dashboard/layout.tsx +++ b/src/app/[lang]/dashboard/layout.tsx @@ -1,20 +1,22 @@ -"use client" +"use client"; + import SideNav from "@/app/[lang]/dashboard/components/server/sidenav"; import dashboardAppModule from "@/app/[lang]/dashboard/module/dashboard-app-module"; import { DiContext } from "@/bootstrap/di/di-context"; import { useRef } from "react"; - export default function Layout({ children }: { children: React.ReactNode }) { - const di = useRef(dashboardAppModule()) + const di = useRef(dashboardAppModule()); return ( <DiContext.Provider value={di.current}> <div className="flex h-screen flex-col md:flex-row md:overflow-hidden"> <div className="w-full flex-none md:w-64"> <SideNav /> </div> - <div className="flex-grow p-6 md:overflow-y-auto md:p-12">{children}</div> + <div className="flex-grow p-6 md:overflow-y-auto md:p-12"> + {children} + </div> </div> </DiContext.Provider> ); -} \ No newline at end of file +} diff --git a/src/app/[lang]/dashboard/loading.tsx b/src/app/[lang]/dashboard/loading.tsx index 9c38c20..0002d3a 100644 --- a/src/app/[lang]/dashboard/loading.tsx +++ b/src/app/[lang]/dashboard/loading.tsx @@ -2,4 +2,4 @@ import DashboardSkeleton from "@/app/[lang]/dashboard/components/server/skeleton export default function Loading() { return <DashboardSkeleton />; -} \ No newline at end of file +} diff --git a/src/app/[lang]/dashboard/module/dashboard-app-module.ts b/src/app/[lang]/dashboard/module/dashboard-app-module.ts index 10992a6..323a2f2 100644 --- a/src/app/[lang]/dashboard/module/dashboard-app-module.ts +++ b/src/app/[lang]/dashboard/module/dashboard-app-module.ts @@ -1,13 +1,16 @@ 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"; export default function dashboardAppModule() { - const dashboardDi = di.createChildContainer() - - dashboardDi.register(createInvoiceUsecase.name, { - useValue: createInvoiceUsecase - }) - dashboardDi.register(CreateRandomInvoiceButtonVM, CreateRandomInvoiceButtonVM) - return dashboardDi + const dashboardDi = di.createChildContainer(); + + dashboardDi.register(createInvoiceUsecase.name, { + useValue: createInvoiceUsecase, + }); + dashboardDi.register( + CreateRandomInvoiceButtonVM, + CreateRandomInvoiceButtonVM, + ); + return dashboardDi; } diff --git a/src/app/[lang]/dashboard/page.tsx b/src/app/[lang]/dashboard/page.tsx index 0035a7b..f9f980f 100644 --- a/src/app/[lang]/dashboard/page.tsx +++ b/src/app/[lang]/dashboard/page.tsx @@ -1,4 +1,7 @@ -import { LatestInvoicesSkeleton, RevenueChartSkeleton } from "@/app/[lang]/dashboard/components/server/skeletons/skeletons"; +import { + LatestInvoicesSkeleton, + RevenueChartSkeleton, +} from "@/app/[lang]/dashboard/components/server/skeletons/skeletons"; import CardWrapper from "@/app/[lang]/dashboard/components/server/cards/cards"; import LatestInvoices from "@/app/[lang]/dashboard/components/server/latest-invoices/latest-invoices"; import RevenueChart from "@/app/[lang]/dashboard/components/server/revenue-chart/revenue-chart"; @@ -6,25 +9,28 @@ import { Suspense } from "react"; import { getServerTranslation } from "@/bootstrap/i18n/i18n"; import langKey from "@/bootstrap/i18n/dictionaries/lang-key"; -export default async function Dashboard(props: {params: Promise<{lang: string}>}) { - const {lang} = await props.params - const { t } = await getServerTranslation(lang) +export default async function Dashboard(props: { + params: Promise<{ lang: string }>; +}) { + const { params } = props; + const { lang } = await params; + const { t } = await getServerTranslation(lang); return ( <main> - <h1 className={`mb-4 text-xl md:text-2xl`}> - {t(langKey.global.dashboard)} + <h1 className="mb-4 text-xl md:text-2xl"> + {t(langKey.global.dashboard)} </h1> <div className="grid gap-6 sm:grid-cols-2 lg:grid-cols-4"> <CardWrapper /> </div> <div className="mt-6 grid grid-cols-1 gap-6 md:grid-cols-4 lg:grid-cols-8"> <Suspense fallback={<RevenueChartSkeleton />}> - <RevenueChart /> + <RevenueChart /> </Suspense> <Suspense fallback={<LatestInvoicesSkeleton />}> <LatestInvoices /> </Suspense> </div> </main> - ) + ); } diff --git a/src/app/[lang]/dashboard/vm/create-random-invoice-button-vm.ts b/src/app/[lang]/dashboard/vm/create-random-invoice-button-vm.ts index 136f5b0..44abdcb 100644 --- a/src/app/[lang]/dashboard/vm/create-random-invoice-button-vm.ts +++ b/src/app/[lang]/dashboard/vm/create-random-invoice-button-vm.ts @@ -8,39 +8,46 @@ import createInvoiceUsecase from "@/feature/core/invoice/domain/usecase/create-i import { faker } from "@faker-js/faker"; import { useRouter } from "next/navigation"; import { useTranslation } from "react-i18next"; + export default class CreateRandomInvoiceButtonVM extends BaseVM<ButtonVm> { - private createInvoice: typeof createInvoiceUsecase + private createInvoice: typeof createInvoiceUsecase; - constructor() { - super() - this.createInvoice = this.di.resolve(createInvoiceUsecase.name) - } + constructor() { + super(); + this.createInvoice = this.di.resolve(createInvoiceUsecase.name); + } - useVM(): ButtonVm { - const router = useRouter() - const [action, isPending] = useServerAction(() => this.onClickHandler(router.refresh)) - const throttledOnClick = useThrottle(action, 5000) + useVM(): ButtonVm { + const router = useRouter(); + const [action, isPending] = useServerAction(() => + this.onClickHandler(router.refresh), + ); + const throttledOnClick = useThrottle(action, 5000); - const {t} = useTranslation() - - return { - props: { - title: t(isPending ? langKey.global.loading : langKey.dashboard.invoice.createButton), - isDisable: isPending ? true : false - }, - onClick: throttledOnClick.bind(this) - } - } + const { t } = useTranslation(); - async onClickHandler(refreshPage: () => void) { - const fakedParams: InvoiceParam = { - amount: faker.number.int({ - min: 1, - max: 10 - }), - status: "paid" - } - await this.createInvoice(fakedParams) - refreshPage() - } -} \ No newline at end of file + return { + props: { + title: t( + isPending + ? langKey.global.loading + : langKey.dashboard.invoice.createButton, + ), + isDisable: !!isPending, + }, + onClick: throttledOnClick.bind(this), + }; + } + + async onClickHandler(refreshPage: () => void) { + const fakedParams: InvoiceParam = { + amount: faker.number.int({ + min: 1, + max: 10, + }), + status: "paid", + }; + await this.createInvoice(fakedParams); + refreshPage(); + } +} diff --git a/src/app/[lang]/layout.tsx b/src/app/[lang]/layout.tsx index dedc58e..4fbaf40 100644 --- a/src/app/[lang]/layout.tsx +++ b/src/app/[lang]/layout.tsx @@ -2,8 +2,14 @@ import { initI18next } from "@/bootstrap/i18n/i18n"; import TranslationsProvider from "@/bootstrap/i18n/i18n-provider"; import { PropsWithChildren } from "react"; -export default async function layout(props: PropsWithChildren & {params: Promise<{lang: string}>}) { - const lang = (await props.params).lang - const { resources} = await initI18next({lng: lang}) - return <TranslationsProvider lng={lang} resources={resources}>{props.children}</TranslationsProvider> -} \ No newline at end of file +export default async function layout( + props: PropsWithChildren & { params: Promise<{ lang: string }> }, +) { + const { lang } = await props.params; + const { resources } = await initI18next({ lng: lang }); + return ( + <TranslationsProvider lng={lang} resources={resources}> + {props.children} + </TranslationsProvider> + ); +} diff --git a/src/app/[lang]/page.tsx b/src/app/[lang]/page.tsx index b34fd95..1e9c77c 100644 --- a/src/app/[lang]/page.tsx +++ b/src/app/[lang]/page.tsx @@ -1,14 +1,12 @@ - export default function Home() { return ( <main className="flex min-h-screen flex-col p-6"> <div className="mt-4 flex grow flex-col gap-4 md:flex-row"> <div className="flex flex-col justify-center gap-6 rounded-lg bg-gray-50 px-6 py-10 md:w-2/5 md:px-20"> - <div /> - <p className={`text-xl text-gray-800 md:text-3xl md:leading-normal`}> - <strong>Welcome to Acme.</strong> This is the example for the{' '} - - , brought to you by Vercel. + <div /> + <p className="text-xl text-gray-800 md:text-3xl md:leading-normal"> + <strong>Welcome to Acme.</strong> This is the example for the , + brought to you by Vercel. </p> </div> </div> diff --git a/src/app/components/button/button-vm.ts b/src/app/components/button/button-vm.ts index ef0d7af..fa23606 100644 --- a/src/app/components/button/button-vm.ts +++ b/src/app/components/button/button-vm.ts @@ -1,7 +1,7 @@ export default interface ButtonVm { - props: { - title: string; - isDisable: boolean; - } - onClick(): void -} \ No newline at end of file + props: { + title: string; + isDisable: boolean; + }; + onClick(): void; +} diff --git a/src/app/components/button/button.tsx b/src/app/components/button/button.tsx index df0de5b..5520728 100644 --- a/src/app/components/button/button.tsx +++ b/src/app/components/button/button.tsx @@ -1,20 +1,24 @@ -"use client" +"use client"; + import BaseView, { BuildProps } from "@/bootstrap/helpers/view/base-view"; import ButtonVm from "@/app/components/button/button-vm"; import { ReactNode } from "react"; -import * as React from "react" -import { Slot } from "@radix-ui/react-slot" -import { cva, type VariantProps } from "class-variance-authority" +import * as React from "react"; +import { Slot } from "@radix-ui/react-slot"; +import { cva, type VariantProps } from "class-variance-authority"; import { cn } from "@/bootstrap/helpers/lib/ui-utils"; export default class Button extends BaseView<ButtonVm> { - protected Build(props: BuildProps<ButtonVm>): ReactNode { - const {vm} = props - - return <ButtonUi disabled={vm.props.isDisable} onClick={vm.onClick} >{vm.props.title}</ButtonUi> - } -} + protected Build(props: BuildProps<ButtonVm>): ReactNode { + const { vm } = props; + return ( + <ButtonUi disabled={vm.props.isDisable} onClick={vm.onClick}> + {vm.props.title} + </ButtonUi> + ); + } +} const buttonVariants = cva( "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0", @@ -43,27 +47,28 @@ const buttonVariants = cva( variant: "default", size: "default", }, - } -) + }, +); export interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement>, VariantProps<typeof buttonVariants> { - asChild?: boolean + asChild?: boolean; } const ButtonUi = React.forwardRef<HTMLButtonElement, ButtonProps>( ({ className, variant, size, asChild = false, ...props }, ref) => { - const Comp = asChild ? Slot : "button" + const Comp = asChild ? Slot : "button"; return ( <Comp className={cn(buttonVariants({ variant, size, className }))} ref={ref} + // eslint-disable-next-line react/jsx-props-no-spreading {...props} /> - ) - } -) -ButtonUi.displayName = "Button" + ); + }, +); +ButtonUi.displayName = "Button"; -export { buttonVariants } \ No newline at end of file +export { buttonVariants }; diff --git a/src/app/components/icons/document.tsx b/src/app/components/icons/document.tsx index a8cbcb6..eeb669e 100644 --- a/src/app/components/icons/document.tsx +++ b/src/app/components/icons/document.tsx @@ -1,5 +1,20 @@ -export function DocumentIcon(props: {className?: string}) { - return ( - <svg className={props.className} width="15" height="15" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M3 2.5C3 2.22386 3.22386 2 3.5 2H9.08579C9.21839 2 9.34557 2.05268 9.43934 2.14645L11.8536 4.56066C11.9473 4.65443 12 4.78161 12 4.91421V12.5C12 12.7761 11.7761 13 11.5 13H3.5C3.22386 13 3 12.7761 3 12.5V2.5ZM3.5 1C2.67157 1 2 1.67157 2 2.5V12.5C2 13.3284 2.67157 14 3.5 14H11.5C12.3284 14 13 13.3284 13 12.5V4.91421C13 4.51639 12.842 4.13486 12.5607 3.85355L10.1464 1.43934C9.86514 1.15804 9.48361 1 9.08579 1H3.5ZM4.5 4C4.22386 4 4 4.22386 4 4.5C4 4.77614 4.22386 5 4.5 5H7.5C7.77614 5 8 4.77614 8 4.5C8 4.22386 7.77614 4 7.5 4H4.5ZM4.5 7C4.22386 7 4 7.22386 4 7.5C4 7.77614 4.22386 8 4.5 8H10.5C10.7761 8 11 7.77614 11 7.5C11 7.22386 10.7761 7 10.5 7H4.5ZM4.5 10C4.22386 10 4 10.2239 4 10.5C4 10.7761 4.22386 11 4.5 11H10.5C10.7761 11 11 10.7761 11 10.5C11 10.2239 10.7761 10 10.5 10H4.5Z" fill="currentColor" fillRule="evenodd" clipRule="evenodd"></path></svg> - ) -} \ No newline at end of file +export function DocumentIcon(props: { className?: string }) { + const { className } = props; + return ( + <svg + className={className} + width="15" + height="15" + viewBox="0 0 15 15" + fill="none" + xmlns="http://www.w3.org/2000/svg" + > + <path + d="M3 2.5C3 2.22386 3.22386 2 3.5 2H9.08579C9.21839 2 9.34557 2.05268 9.43934 2.14645L11.8536 4.56066C11.9473 4.65443 12 4.78161 12 4.91421V12.5C12 12.7761 11.7761 13 11.5 13H3.5C3.22386 13 3 12.7761 3 12.5V2.5ZM3.5 1C2.67157 1 2 1.67157 2 2.5V12.5C2 13.3284 2.67157 14 3.5 14H11.5C12.3284 14 13 13.3284 13 12.5V4.91421C13 4.51639 12.842 4.13486 12.5607 3.85355L10.1464 1.43934C9.86514 1.15804 9.48361 1 9.08579 1H3.5ZM4.5 4C4.22386 4 4 4.22386 4 4.5C4 4.77614 4.22386 5 4.5 5H7.5C7.77614 5 8 4.77614 8 4.5C8 4.22386 7.77614 4 7.5 4H4.5ZM4.5 7C4.22386 7 4 7.22386 4 7.5C4 7.77614 4.22386 8 4.5 8H10.5C10.7761 8 11 7.77614 11 7.5C11 7.22386 10.7761 7 10.5 7H4.5ZM4.5 10C4.22386 10 4 10.2239 4 10.5C4 10.7761 4.22386 11 4.5 11H10.5C10.7761 11 11 10.7761 11 10.5C11 10.2239 10.7761 10 10.5 10H4.5Z" + fill="currentColor" + fillRule="evenodd" + clipRule="evenodd" + /> + </svg> + ); +} diff --git a/src/app/components/icons/home.tsx b/src/app/components/icons/home.tsx index 8270d4e..ac7a258 100644 --- a/src/app/components/icons/home.tsx +++ b/src/app/components/icons/home.tsx @@ -1,5 +1,20 @@ -export default function HomeIcon(props: {className?: string}) { - return ( - <svg className={props.className} width="15" height="15" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M7.07926 0.222253C7.31275 -0.007434 7.6873 -0.007434 7.92079 0.222253L14.6708 6.86227C14.907 7.09465 14.9101 7.47453 14.6778 7.71076C14.4454 7.947 14.0655 7.95012 13.8293 7.71773L13 6.90201V12.5C13 12.7761 12.7762 13 12.5 13H2.50002C2.22388 13 2.00002 12.7761 2.00002 12.5V6.90201L1.17079 7.71773C0.934558 7.95012 0.554672 7.947 0.32229 7.71076C0.0899079 7.47453 0.0930283 7.09465 0.32926 6.86227L7.07926 0.222253ZM7.50002 1.49163L12 5.91831V12H10V8.49999C10 8.22385 9.77617 7.99999 9.50002 7.99999H6.50002C6.22388 7.99999 6.00002 8.22385 6.00002 8.49999V12H3.00002V5.91831L7.50002 1.49163ZM7.00002 12H9.00002V8.99999H7.00002V12Z" fill="currentColor" fillRule="evenodd" clipRule="evenodd"></path></svg> - ) -} \ No newline at end of file +export default function HomeIcon(props: { className?: string }) { + const { className } = props; + return ( + <svg + className={className} + width="15" + height="15" + viewBox="0 0 15 15" + fill="none" + xmlns="http://www.w3.org/2000/svg" + > + <path + d="M7.07926 0.222253C7.31275 -0.007434 7.6873 -0.007434 7.92079 0.222253L14.6708 6.86227C14.907 7.09465 14.9101 7.47453 14.6778 7.71076C14.4454 7.947 14.0655 7.95012 13.8293 7.71773L13 6.90201V12.5C13 12.7761 12.7762 13 12.5 13H2.50002C2.22388 13 2.00002 12.7761 2.00002 12.5V6.90201L1.17079 7.71773C0.934558 7.95012 0.554672 7.947 0.32229 7.71076C0.0899079 7.47453 0.0930283 7.09465 0.32926 6.86227L7.07926 0.222253ZM7.50002 1.49163L12 5.91831V12H10V8.49999C10 8.22385 9.77617 7.99999 9.50002 7.99999H6.50002C6.22388 7.99999 6.00002 8.22385 6.00002 8.49999V12H3.00002V5.91831L7.50002 1.49163ZM7.00002 12H9.00002V8.99999H7.00002V12Z" + fill="currentColor" + fillRule="evenodd" + clipRule="evenodd" + /> + </svg> + ); +} diff --git a/src/app/components/icons/user.tsx b/src/app/components/icons/user.tsx index 02b56ed..dcd7f93 100644 --- a/src/app/components/icons/user.tsx +++ b/src/app/components/icons/user.tsx @@ -1,7 +1,19 @@ -export function UserIcon(props: {className?: string}) { - return ( - <svg className={props.className} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor"> - <path strokeLinecap="round" strokeLinejoin="round" d="M15.75 6a3.75 3.75 0 1 1-7.5 0 3.75 3.75 0 0 1 7.5 0ZM4.501 20.118a7.5 7.5 0 0 1 14.998 0A17.933 17.933 0 0 1 12 21.75c-2.676 0-5.216-.584-7.499-1.632Z" /> - </svg> - ) -} \ No newline at end of file +export function UserIcon(props: { className?: string }) { + const { className } = props; + return ( + <svg + className={className} + xmlns="http://www.w3.org/2000/svg" + fill="none" + viewBox="0 0 24 24" + strokeWidth={1.5} + stroke="currentColor" + > + <path + strokeLinecap="round" + strokeLinejoin="round" + d="M15.75 6a3.75 3.75 0 1 1-7.5 0 3.75 3.75 0 0 1 7.5 0ZM4.501 20.118a7.5 7.5 0 0 1 14.998 0A17.933 17.933 0 0 1 12 21.75c-2.676 0-5.216-.584-7.499-1.632Z" + /> + </svg> + ); +} diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 8a8df4e..a36cde0 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -1,6 +1,7 @@ import type { Metadata } from "next"; import localFont from "next/font/local"; import "./globals.css"; + const geistSans = localFont({ src: "./fonts/GeistVF.woff", variable: "--font-geist-sans", @@ -23,7 +24,7 @@ export default function RootLayout({ children: React.ReactNode; }>) { return ( - <html> + <html lang="en"> <body className={`${geistSans.variable} ${geistMono.variable} antialiased`} > diff --git a/src/bootstrap/boundaries/db/db.ts b/src/bootstrap/boundaries/db/db.ts index d6962af..2757311 100644 --- a/src/bootstrap/boundaries/db/db.ts +++ b/src/bootstrap/boundaries/db/db.ts @@ -1,13 +1,12 @@ import postgres from "postgres"; - const envs = process.env; const dbConfigs = { - host: envs.POSTGRES_HOST, - port: Number(envs.POSTGRES_PORT), - username: envs.POSTGRES_USER, - password: envs.POSTGRES_PASS, - database: envs.POSTGRES_DB, -} + host: envs.POSTGRES_HOST, + port: Number(envs.POSTGRES_PORT), + username: envs.POSTGRES_USER, + password: envs.POSTGRES_PASS, + database: envs.POSTGRES_DB, +}; export const sql = postgres(dbConfigs); diff --git a/src/bootstrap/boundaries/db/placeholder-data.js b/src/bootstrap/boundaries/db/placeholder-data.js index 15a4156..be007ee 100644 --- a/src/bootstrap/boundaries/db/placeholder-data.js +++ b/src/bootstrap/boundaries/db/placeholder-data.js @@ -2,73 +2,73 @@ // https://nextjs.org/learn/dashboard-app/fetching-data const users = [ { - id: '410544b2-4001-4271-9855-fec4b6a6442a', - name: 'User', - email: 'user@nextmail.com', - password: '123456', + id: "410544b2-4001-4271-9855-fec4b6a6442a", + name: "User", + email: "user@nextmail.com", + password: "123456", }, ]; const customers = [ { - id: '3958dc9e-712f-4377-85e9-fec4b6a6442a', - name: 'Delba de Oliveira', - email: 'delba@oliveira.com', - image_url: '/customers/delba-de-oliveira.png', + id: "3958dc9e-712f-4377-85e9-fec4b6a6442a", + name: "Delba de Oliveira", + email: "delba@oliveira.com", + image_url: "/customers/delba-de-oliveira.png", }, { - id: '3958dc9e-742f-4377-85e9-fec4b6a6442a', - name: 'Lee Robinson', - email: 'lee@robinson.com', - image_url: '/customers/lee-robinson.png', + id: "3958dc9e-742f-4377-85e9-fec4b6a6442a", + name: "Lee Robinson", + email: "lee@robinson.com", + image_url: "/customers/lee-robinson.png", }, { - id: '3958dc9e-737f-4377-85e9-fec4b6a6442a', - name: 'Hector Simpson', - email: 'hector@simpson.com', - image_url: '/customers/hector-simpson.png', + id: "3958dc9e-737f-4377-85e9-fec4b6a6442a", + name: "Hector Simpson", + email: "hector@simpson.com", + image_url: "/customers/hector-simpson.png", }, { - id: '50ca3e18-62cd-11ee-8c99-0242ac120002', - name: 'Steven Tey', - email: 'steven@tey.com', - image_url: '/customers/steven-tey.png', + id: "50ca3e18-62cd-11ee-8c99-0242ac120002", + name: "Steven Tey", + email: "steven@tey.com", + image_url: "/customers/steven-tey.png", }, { - id: '3958dc9e-787f-4377-85e9-fec4b6a6442a', - name: 'Steph Dietz', - email: 'steph@dietz.com', - image_url: '/customers/steph-dietz.png', + id: "3958dc9e-787f-4377-85e9-fec4b6a6442a", + name: "Steph Dietz", + email: "steph@dietz.com", + image_url: "/customers/steph-dietz.png", }, { - id: '76d65c26-f784-44a2-ac19-586678f7c2f2', - name: 'Michael Novotny', - email: 'michael@novotny.com', - image_url: '/customers/michael-novotny.png', + id: "76d65c26-f784-44a2-ac19-586678f7c2f2", + name: "Michael Novotny", + email: "michael@novotny.com", + image_url: "/customers/michael-novotny.png", }, { - id: 'd6e15727-9fe1-4961-8c5b-ea44a9bd81aa', - name: 'Evil Rabbit', - email: 'evil@rabbit.com', - image_url: '/customers/evil-rabbit.png', + id: "d6e15727-9fe1-4961-8c5b-ea44a9bd81aa", + name: "Evil Rabbit", + email: "evil@rabbit.com", + image_url: "/customers/evil-rabbit.png", }, { - id: '126eed9c-c90c-4ef6-a4a8-fcf7408d3c66', - name: 'Emil Kowalski', - email: 'emil@kowalski.com', - image_url: '/customers/emil-kowalski.png', + id: "126eed9c-c90c-4ef6-a4a8-fcf7408d3c66", + name: "Emil Kowalski", + email: "emil@kowalski.com", + image_url: "/customers/emil-kowalski.png", }, { - id: 'CC27C14A-0ACF-4F4A-A6C9-D45682C144B9', - name: 'Amy Burns', - email: 'amy@burns.com', - image_url: '/customers/amy-burns.png', + id: "CC27C14A-0ACF-4F4A-A6C9-D45682C144B9", + name: "Amy Burns", + email: "amy@burns.com", + image_url: "/customers/amy-burns.png", }, { - id: '13D07535-C59E-4157-A011-F8D2EF4E0CBB', - name: 'Balazs Orban', - email: 'balazs@orban.com', - image_url: '/customers/balazs-orban.png', + id: "13D07535-C59E-4157-A011-F8D2EF4E0CBB", + name: "Balazs Orban", + email: "balazs@orban.com", + image_url: "/customers/balazs-orban.png", }, ]; @@ -76,108 +76,108 @@ const invoices = [ { customer_id: customers[0].id, amount: 15795, - status: 'pending', - date: '2022-12-06', + status: "pending", + date: "2022-12-06", }, { customer_id: customers[1].id, amount: 20348, - status: 'pending', - date: '2022-11-14', + status: "pending", + date: "2022-11-14", }, { customer_id: customers[4].id, amount: 3040, - status: 'paid', - date: '2022-10-29', + status: "paid", + date: "2022-10-29", }, { customer_id: customers[3].id, amount: 44800, - status: 'paid', - date: '2023-09-10', + status: "paid", + date: "2023-09-10", }, { customer_id: customers[5].id, amount: 34577, - status: 'pending', - date: '2023-08-05', + status: "pending", + date: "2023-08-05", }, { customer_id: customers[7].id, amount: 54246, - status: 'pending', - date: '2023-07-16', + status: "pending", + date: "2023-07-16", }, { customer_id: customers[6].id, amount: 666, - status: 'pending', - date: '2023-06-27', + status: "pending", + date: "2023-06-27", }, { customer_id: customers[3].id, amount: 32545, - status: 'paid', - date: '2023-06-09', + status: "paid", + date: "2023-06-09", }, { customer_id: customers[4].id, amount: 1250, - status: 'paid', - date: '2023-06-17', + status: "paid", + date: "2023-06-17", }, { customer_id: customers[5].id, amount: 8546, - status: 'paid', - date: '2023-06-07', + status: "paid", + date: "2023-06-07", }, { customer_id: customers[1].id, amount: 500, - status: 'paid', - date: '2023-08-19', + status: "paid", + date: "2023-08-19", }, { customer_id: customers[5].id, amount: 8945, - status: 'paid', - date: '2023-06-03', + status: "paid", + date: "2023-06-03", }, { customer_id: customers[2].id, amount: 8945, - status: 'paid', - date: '2023-06-18', + status: "paid", + date: "2023-06-18", }, { customer_id: customers[0].id, amount: 8945, - status: 'paid', - date: '2023-10-04', + status: "paid", + date: "2023-10-04", }, { customer_id: customers[2].id, amount: 1000, - status: 'paid', - date: '2022-06-05', + status: "paid", + date: "2022-06-05", }, ]; const revenue = [ - { month: 'Jan', revenue: 2000 }, - { month: 'Feb', revenue: 1800 }, - { month: 'Mar', revenue: 2200 }, - { month: 'Apr', revenue: 2500 }, - { month: 'May', revenue: 2300 }, - { month: 'Jun', revenue: 3200 }, - { month: 'Jul', revenue: 3500 }, - { month: 'Aug', revenue: 3700 }, - { month: 'Sep', revenue: 2500 }, - { month: 'Oct', revenue: 2800 }, - { month: 'Nov', revenue: 3000 }, - { month: 'Dec', revenue: 4800 }, + { month: "Jan", revenue: 2000 }, + { month: "Feb", revenue: 1800 }, + { month: "Mar", revenue: 2200 }, + { month: "Apr", revenue: 2500 }, + { month: "May", revenue: 2300 }, + { month: "Jun", revenue: 3200 }, + { month: "Jul", revenue: 3500 }, + { month: "Aug", revenue: 3700 }, + { month: "Sep", revenue: 2500 }, + { month: "Oct", revenue: 2800 }, + { month: "Nov", revenue: 3000 }, + { month: "Dec", revenue: 4800 }, ]; module.exports = { diff --git a/src/bootstrap/boundaries/db/seed.js b/src/bootstrap/boundaries/db/seed.js index 1b4273f..530caf5 100644 --- a/src/bootstrap/boundaries/db/seed.js +++ b/src/bootstrap/boundaries/db/seed.js @@ -1,12 +1,14 @@ +/* eslint-disable no-console */ /* eslint-disable @typescript-eslint/no-require-imports */ +const bcrypt = require("bcrypt"); +const postgres = require("postgres"); const { invoices, customers, revenue, users, -} = require('./placeholder-data.js'); -const bcrypt = require('bcrypt'); -const postgres = require('postgres'); + // eslint-disable-next-line import/extensions +} = require("./placeholder-data.js"); async function seedUsers(sql) { try { @@ -42,7 +44,7 @@ async function seedUsers(sql) { users: insertedUsers, }; } catch (error) { - console.error('Error seeding users:', error); + console.error("Error seeding users:", error); throw error; } } @@ -82,7 +84,7 @@ async function seedInvoices(sql) { invoices: insertedInvoices, }; } catch (error) { - console.error('Error seeding invoices:', error); + console.error("Error seeding invoices:", error); throw error; } } @@ -121,7 +123,7 @@ async function seedCustomers(sql) { customers: insertedCustomers, }; } catch (error) { - console.error('Error seeding customers:', error); + console.error("Error seeding customers:", error); throw error; } } @@ -156,7 +158,7 @@ async function seedRevenue(sql) { revenue: insertedRevenue, }; } catch (error) { - console.error('Error seeding revenue:', error); + console.error("Error seeding revenue:", error); throw error; } } @@ -169,7 +171,7 @@ async function main() { username: envs.POSTGRES_USER, password: envs.POSTGRES_PASS, database: envs.POSTGRES_DB, - } + }; const sql = postgres(dbConfigs); @@ -177,12 +179,11 @@ async function main() { await seedCustomers(sql); await seedInvoices(sql); await seedRevenue(sql); - } main().catch((err) => { console.error( - 'An error occurred while attempting to seed the database:', + "An error occurred while attempting to seed the database:", err, ); }); diff --git a/src/bootstrap/di/di-context.tsx b/src/bootstrap/di/di-context.tsx index 2474156..3505eff 100644 --- a/src/bootstrap/di/di-context.tsx +++ b/src/bootstrap/di/di-context.tsx @@ -1,21 +1,19 @@ -"use client" +"use client"; + import di from "@/bootstrap/di/init-di"; import { createContext, use } from "react"; import { DependencyContainer } from "tsyringe"; -const DiContext = createContext<null | DependencyContainer>(di) +const DiContext = createContext<null | DependencyContainer>(di); const useDI = () => { - const di = use(DiContext) + const di = use(DiContext); - if (!di) { - throw new Error("Di has not provided") - } + if (!di) { + throw new Error("Di has not provided"); + } - return di -} + return di; +}; -export { - DiContext, - useDI, -} \ No newline at end of file +export { DiContext, useDI }; diff --git a/src/bootstrap/di/init-di.ts b/src/bootstrap/di/init-di.ts index 3ebdeef..4bf4261 100644 --- a/src/bootstrap/di/init-di.ts +++ b/src/bootstrap/di/init-di.ts @@ -1,5 +1,5 @@ // "use client" -import "reflect-metadata" +import "reflect-metadata"; import { container, DependencyContainer } from "tsyringe"; /** @@ -15,4 +15,4 @@ const InitDI = (): DependencyContainer => { const di = InitDI(); -export default di; \ No newline at end of file +export default di; diff --git a/src/bootstrap/helpers/global-helpers.ts b/src/bootstrap/helpers/global-helpers.ts index cf37914..ca617a8 100644 --- a/src/bootstrap/helpers/global-helpers.ts +++ b/src/bootstrap/helpers/global-helpers.ts @@ -1,2 +1 @@ - -export const isServer = typeof window === 'undefined' \ No newline at end of file +export const isServer = typeof window === "undefined"; diff --git a/src/bootstrap/helpers/hooks/use-server-action.ts b/src/bootstrap/helpers/hooks/use-server-action.ts index abb7516..a4a5034 100644 --- a/src/bootstrap/helpers/hooks/use-server-action.ts +++ b/src/bootstrap/helpers/hooks/use-server-action.ts @@ -1,11 +1,11 @@ -import { useState, useEffect, useTransition, useRef } from 'react'; +import { useState, useEffect, useTransition, useRef } from "react"; /** - * + * * @param action Main server action to run * @param onFinished Callback to run after action * @returns transitioned action to run and is pending variable -*/ + */ // eslint-disable-next-line @typescript-eslint/no-explicit-any export const useServerAction = <P extends any[], R>( action: (...args: P) => Promise<R>, @@ -37,4 +37,4 @@ export const useServerAction = <P extends any[], R>( }; return [runAction, isPending]; -}; \ No newline at end of file +}; diff --git a/src/bootstrap/helpers/hooks/use-throttle.ts b/src/bootstrap/helpers/hooks/use-throttle.ts index ff2344f..6f8213b 100644 --- a/src/bootstrap/helpers/hooks/use-throttle.ts +++ b/src/bootstrap/helpers/hooks/use-throttle.ts @@ -1,18 +1,22 @@ -"use client" +"use client"; -import { useEffect, useRef } from "react" +import { useRef } from "react"; /** - * - * @param callback + * + * @param callback * @param time In miliseconds */ -export default function useThrottle<T extends Function>(callback: T, time: number = 2000) { - const lastRun = useRef(Date.now()) +export default function useThrottle<T extends () => unknown>( + callback: T, + time: number = 2000, +) { + const lastRun = useRef(Date.now()); - return function() { - if (Date.now() - lastRun.current <= time) return; - lastRun.current = Date.now() - return callback() - } -} \ No newline at end of file + // eslint-disable-next-line func-names + return function () { + if (Date.now() - lastRun.current <= time) return; + lastRun.current = Date.now(); + callback(); + }; +} diff --git a/src/bootstrap/helpers/lib/ui-utils.ts b/src/bootstrap/helpers/lib/ui-utils.ts index bd0c391..a5ef193 100644 --- a/src/bootstrap/helpers/lib/ui-utils.ts +++ b/src/bootstrap/helpers/lib/ui-utils.ts @@ -1,6 +1,6 @@ -import { clsx, type ClassValue } from "clsx" -import { twMerge } from "tailwind-merge" +import { clsx, type ClassValue } from "clsx"; +import { twMerge } from "tailwind-merge"; export function cn(...inputs: ClassValue[]) { - return twMerge(clsx(inputs)) + return twMerge(clsx(inputs)); } diff --git a/src/bootstrap/helpers/type-helper.ts b/src/bootstrap/helpers/type-helper.ts index c484e86..a1effb7 100644 --- a/src/bootstrap/helpers/type-helper.ts +++ b/src/bootstrap/helpers/type-helper.ts @@ -5,4 +5,4 @@ type Forbidden = { [_]: typeof _ }; /** * You can use this type to make your parent class method forbidden to overwrite */ -export type NoOverride<T = void> = T & Forbidden; \ No newline at end of file +export type NoOverride<T = void> = T & Forbidden; diff --git a/src/bootstrap/helpers/view/base-view.tsx b/src/bootstrap/helpers/view/base-view.tsx index 990cd19..b0d4f57 100644 --- a/src/bootstrap/helpers/view/base-view.tsx +++ b/src/bootstrap/helpers/view/base-view.tsx @@ -1,4 +1,5 @@ -"use client" +"use client"; + // import gdi from "@/bootstrap/di/init-di"; /* eslint-disable react/display-name */ /* eslint-disable @typescript-eslint/no-explicit-any */ @@ -23,7 +24,7 @@ const VvmConnector = memo( <IVM, PROPS>(props: IVvmConnector<IVM, PROPS>) => { const { View, Vm, restProps, children } = props; - const vm = Vm.useVM() + const vm = Vm.useVM(); const allProps = { restProps, @@ -69,17 +70,17 @@ export default abstract class BaseView< IVM extends IVMParent, PROPS extends IPropParent = undefined, > extends Component<BaseProps<IVM, PROPS>> { - protected abstract Build(props: BuildProps<IVM, PROPS>): ReactNode; - protected get componentName() { - return this.constructor.name + return this.constructor.name; } + protected abstract Build(props: BuildProps<IVM, PROPS>): ReactNode; + render(): ReactNode { const { vm, restProps, memoizedByVM, children, ...rest } = this.props; - - VvmConnector.displayName = this.componentName - + + VvmConnector.displayName = this.componentName; + return ( <VvmConnector View={this.Build} diff --git a/src/bootstrap/helpers/vm/base-vm.ts b/src/bootstrap/helpers/vm/base-vm.ts index b9bb379..003443c 100644 --- a/src/bootstrap/helpers/vm/base-vm.ts +++ b/src/bootstrap/helpers/vm/base-vm.ts @@ -1,4 +1,5 @@ -"use client" +"use client"; + import { useDI } from "@/bootstrap/di/di-context"; import { NoOverride } from "@/bootstrap/helpers/type-helper"; import IBaseVM from "@/bootstrap/helpers/vm/i-base-vm"; @@ -31,8 +32,9 @@ export default abstract class BaseVM< /* -------------------------------------------------------------------------- */ protected get di() { - return useDI() + return useDI(); } + /* -------------------------------------------------------------------------- */ /** * You can use this hook in your useVm method to get rerender method diff --git a/src/bootstrap/i18n/dictionaries/en.ts b/src/bootstrap/i18n/dictionaries/en.ts index 3f0f60c..1c8313b 100644 --- a/src/bootstrap/i18n/dictionaries/en.ts +++ b/src/bootstrap/i18n/dictionaries/en.ts @@ -1,16 +1,16 @@ -import langKey from "@/bootstrap/i18n/dictionaries/lang-key" +import langKey from "@/bootstrap/i18n/dictionaries/lang-key"; const en: typeof langKey = { - global: { - home: "Home", - loading: "Loading", - dashboard: "Dashboard" + global: { + home: "Home", + loading: "Loading", + dashboard: "Dashboard", + }, + dashboard: { + invoice: { + createButton: "Create random Invoice", }, - dashboard: { - invoice: { - createButton: "Create random Invoice" - } - } -} + }, +}; -export default en \ No newline at end of file +export default en; diff --git a/src/bootstrap/i18n/dictionaries/lang-key.ts b/src/bootstrap/i18n/dictionaries/lang-key.ts index 69ca04e..1bc2143 100644 --- a/src/bootstrap/i18n/dictionaries/lang-key.ts +++ b/src/bootstrap/i18n/dictionaries/lang-key.ts @@ -1,14 +1,14 @@ const langKey = { - global: { - home: "global.home", - dashboard: "global.dashboard", - loading: "global.loading" + global: { + home: "global.home", + dashboard: "global.dashboard", + loading: "global.loading", + }, + dashboard: { + invoice: { + createButton: "dashboard.invoice.createButton", }, - dashboard: { - invoice: { - createButton: "dashboard.invoice.createButton" - } - } -} + }, +}; -export default langKey; \ No newline at end of file +export default langKey; diff --git a/src/bootstrap/i18n/dictionaries/ru.ts b/src/bootstrap/i18n/dictionaries/ru.ts index 9c8e561..48b6221 100644 --- a/src/bootstrap/i18n/dictionaries/ru.ts +++ b/src/bootstrap/i18n/dictionaries/ru.ts @@ -1,16 +1,16 @@ -import langKey from "@/bootstrap/i18n/dictionaries/lang-key" +import langKey from "@/bootstrap/i18n/dictionaries/lang-key"; const ru: typeof langKey = { - global: { - home: "Дом", - loading: "Загрузка", - dashboard: "Панель приборов" + global: { + home: "Дом", + loading: "Загрузка", + dashboard: "Панель приборов", + }, + dashboard: { + invoice: { + createButton: "Создать случайный счет-фактуру", }, - dashboard: { - invoice: { - createButton: "Создать случайный счет-фактуру" - } - } -} + }, +}; -export default ru \ No newline at end of file +export default ru; diff --git a/src/bootstrap/i18n/i18n-provider.tsx b/src/bootstrap/i18n/i18n-provider.tsx index d15b347..c3272d8 100644 --- a/src/bootstrap/i18n/i18n-provider.tsx +++ b/src/bootstrap/i18n/i18n-provider.tsx @@ -1,13 +1,18 @@ -"use client" -import { I18nextProvider } from "react-i18next" +"use client"; + +import { I18nextProvider } from "react-i18next"; import { initI18next } from "@/bootstrap/i18n/i18n"; import { createInstance, Resource } from "i18next"; import { PropsWithChildren } from "react"; -export default function TranslationsProvider({children, lng, resources}: PropsWithChildren & {lng: string; resources: Resource}) { - const i18n = createInstance() +export default function TranslationsProvider({ + children, + lng, + resources, +}: PropsWithChildren & { lng: string; resources: Resource }) { + const i18n = createInstance(); - initI18next({lng, i18n, resources}) + initI18next({ lng, i18n, resources }); - return <I18nextProvider i18n={i18n}>{children}</I18nextProvider> -} \ No newline at end of file + return <I18nextProvider i18n={i18n}>{children}</I18nextProvider>; +} diff --git a/src/bootstrap/i18n/i18n.ts b/src/bootstrap/i18n/i18n.ts index edd45d5..8b348f2 100644 --- a/src/bootstrap/i18n/i18n.ts +++ b/src/bootstrap/i18n/i18n.ts @@ -1,34 +1,51 @@ -import { getOptions, languages } from '@/bootstrap/i18n/settings' -import { createInstance, i18n, Resource } from 'i18next' -import resourcesToBackend from 'i18next-resources-to-backend' -import { initReactI18next } from 'react-i18next/initReactI18next' +import { getOptions, languages } from "@/bootstrap/i18n/settings"; +import { createInstance, i18n, Resource } from "i18next"; +import resourcesToBackend from "i18next-resources-to-backend"; +import { initReactI18next } from "react-i18next/initReactI18next"; -export const initI18next = async (params: {lng: string, i18n?: i18n, resources?: Resource, ns?: string}) => { - const { lng, i18n, ns, resources } = params - const i18nInstance = i18n ? i18n : createInstance() +export const initI18next = async (params: { + lng: string; + i18n?: i18n; + resources?: Resource; + ns?: string; +}) => { + const { lng, i18n, ns, resources } = params; + const i18nInstance = i18n || createInstance(); await i18nInstance .use(initReactI18next) - .use(resourcesToBackend((language: string) => import(`./dictionaries/${language}.ts`))) + .use( + resourcesToBackend( + (language: string) => import(`./dictionaries/${language}.ts`), + ), + ) .init({ - ...getOptions(lng, ns), - resources, - preload: resources ? [] : languages - },) + ...getOptions(lng, ns), + resources, + preload: resources ? [] : languages, + }); - await i18nInstance.init() - - return { - i18n: i18nInstance, - resources: i18nInstance.services.resourceStore.data, - t: i18nInstance.t - } -} + await i18nInstance.init(); -export async function getServerTranslation(lng: string, ns?: string, options: {keyPrefix?: string} = {}) { - const i18nextInstance = (await initI18next({lng, ns})).i18n - return { - t: i18nextInstance.getFixedT(lng, Array.isArray(ns) ? ns[0] : ns, options?.keyPrefix), - i18n: i18nextInstance - } -} \ No newline at end of file + i18n: i18nInstance, + resources: i18nInstance.services.resourceStore.data, + t: i18nInstance.t, + }; +}; + +export async function getServerTranslation( + lng: string, + ns?: string, + options: { keyPrefix?: string } = {}, +) { + const i18nextInstance = (await initI18next({ lng, ns })).i18n; + + return { + t: i18nextInstance.getFixedT( + lng, + Array.isArray(ns) ? ns[0] : ns, + options?.keyPrefix, + ), + i18n: i18nextInstance, + }; +} diff --git a/src/bootstrap/i18n/settings.ts b/src/bootstrap/i18n/settings.ts index 7e3030b..384dfd0 100644 --- a/src/bootstrap/i18n/settings.ts +++ b/src/bootstrap/i18n/settings.ts @@ -1,9 +1,9 @@ -export const fallbackLng = 'en' -export const languages = [fallbackLng, 'ru'] -export const defaultNS = 'translation' -export const cookieName = 'i18next' +export const fallbackLng = "en"; +export const languages = [fallbackLng, "ru"]; +export const defaultNS = "translation"; +export const cookieName = "i18next"; -export function getOptions (lng = fallbackLng, ns = defaultNS) { +export function getOptions(lng = fallbackLng, ns = defaultNS) { return { // debug: true, supportedLngs: languages, @@ -11,6 +11,6 @@ export function getOptions (lng = fallbackLng, ns = defaultNS) { lng, fallbackNS: defaultNS, defaultNS, - ns - } -} \ No newline at end of file + ns, + }; +} diff --git a/src/feature/common/data/api-task.ts b/src/feature/common/data/api-task.ts index f234898..2f85177 100644 --- a/src/feature/common/data/api-task.ts +++ b/src/feature/common/data/api-task.ts @@ -2,7 +2,10 @@ import { Either } from "fp-ts/lib/Either"; import { TaskEither } from "fp-ts/lib/TaskEither"; import BaseFailure from "@/feature/common/failures/base-failure"; -type ApiTask<ResponseType> = TaskEither<BaseFailure, ResponseType>; -export type ApiEither<ResponseType> = Either<BaseFailure, ResponseType>; +type ApiTask<ResponseType> = TaskEither<BaseFailure<unknown>, ResponseType>; +export type ApiEither<ResponseType> = Either< + BaseFailure<unknown>, + ResponseType +>; export default ApiTask; diff --git a/src/feature/common/failures/base-failure.ts b/src/feature/common/failures/base-failure.ts index 43e6117..2719351 100644 --- a/src/feature/common/failures/base-failure.ts +++ b/src/feature/common/failures/base-failure.ts @@ -15,12 +15,12 @@ export default abstract class BaseFailure<META_DATA> { message = this.BASE_FAILURE_MESSAGE; /* -------------------------------------------------------------------------- */ - metadata: META_DATA | undefined; + metadata: META_DATA | undefined; /* -------------------------------------------------------------------------- */ constructor(key: string, metadata?: META_DATA) { this.message = makeFailureMessage(this.message, key); - this.metadata = metadata ?? undefined + this.metadata = metadata ?? undefined; } /* -------------------------------------------------------------------------- */ } diff --git a/src/feature/common/failures/dev/arguments-failure.ts b/src/feature/common/failures/dev/arguments-failure.ts index 11d01c2..6e0d266 100644 --- a/src/feature/common/failures/dev/arguments-failure.ts +++ b/src/feature/common/failures/dev/arguments-failure.ts @@ -3,7 +3,9 @@ import BaseDevFailure from "@/feature/common/failures/dev/base-dev-failure"; /** * Failure for needed arguments in a method but sent wrong one */ -export default class ArgumentsFailure<META_DATA> extends BaseDevFailure<META_DATA> { +export default class ArgumentsFailure< + META_DATA, +> extends BaseDevFailure<META_DATA> { /* ------------------------------- Constructor ------------------------------ */ constructor(metadata?: META_DATA) { super("arguments", metadata); diff --git a/src/feature/common/failures/dev/base-dev-failure.ts b/src/feature/common/failures/dev/base-dev-failure.ts index ad404d1..94bea0c 100644 --- a/src/feature/common/failures/dev/base-dev-failure.ts +++ b/src/feature/common/failures/dev/base-dev-failure.ts @@ -1,3 +1,5 @@ import BaseFailure from "@/feature/common/failures/base-failure"; -export default abstract class BaseDevFailure<META_DATA> extends BaseFailure<META_DATA> {} +export default abstract class BaseDevFailure< + META_DATA, +> extends BaseFailure<META_DATA> {} diff --git a/src/feature/common/failures/dev/dependency-failure.ts b/src/feature/common/failures/dev/dependency-failure.ts index 6f16f8f..5b81b13 100644 --- a/src/feature/common/failures/dev/dependency-failure.ts +++ b/src/feature/common/failures/dev/dependency-failure.ts @@ -3,7 +3,9 @@ import BaseDevFailure from "@/feature/common/failures/dev/base-dev-failure"; /** * This is a failure of not having specific dependency */ -export default class DependencyFailure<META_DATA> extends BaseDevFailure<META_DATA> { +export default class DependencyFailure< + META_DATA, +> extends BaseDevFailure<META_DATA> { constructor(metadata: META_DATA) { super("DependencyFailure", metadata); } diff --git a/src/feature/common/failures/params-failure.ts b/src/feature/common/failures/params-failure.ts index df50d8c..67f8cb9 100644 --- a/src/feature/common/failures/params-failure.ts +++ b/src/feature/common/failures/params-failure.ts @@ -1,7 +1,7 @@ import BaseFailure from "./base-failure"; /** - * Failure for params failure + * Failure for params failure */ export default class ParamsFailure<META_DATA> extends BaseFailure<META_DATA> { /* ------------------------------- Constructor ------------------------------ */ diff --git a/src/feature/common/feature-helpers.ts b/src/feature/common/feature-helpers.ts index 4269137..cb37dd2 100644 --- a/src/feature/common/feature-helpers.ts +++ b/src/feature/common/feature-helpers.ts @@ -1,6 +1,5 @@ -export const formatCurrency = (amount: number) => { - return (amount / 100).toLocaleString('en-US', { - style: 'currency', - currency: 'USD', +export const formatCurrency = (amount: number) => + (amount / 100).toLocaleString("en-US", { + style: "currency", + currency: "USD", }); -}; \ No newline at end of file diff --git a/src/feature/common/server-di.ts b/src/feature/common/server-di.ts index cec83f7..71ddbfa 100644 --- a/src/feature/common/server-di.ts +++ b/src/feature/common/server-di.ts @@ -10,21 +10,21 @@ import getSummaryInfoDi from "@/feature/core/summary-info/data/module/summary-in import { revenueModuleKey } from "@/feature/core/revenue/domain/revenue-module-key"; import getRevenueDi from "@/feature/core/revenue/data/module/revenue-di"; -const memoizedDis: Record<string, DependencyContainer> = {} +const memoizedDis: Record<string, DependencyContainer> = {}; export default function serverDi(module: string): DependencyContainer { - if (memoizedDis[module]) return memoizedDis[module] - const getDi = { - [customerKey]: getCustomerDi, - [customerInvoiceModuleKey]: getCustomerInvoiceDi, - [invoiceModuleKey]: getInvoiceDi, - [summaryInfoModuleKey]: getSummaryInfoDi, - [revenueModuleKey]: getRevenueDi, - }[module] + if (memoizedDis[module]) return memoizedDis[module]; + const getDi = { + [customerKey]: getCustomerDi, + [customerInvoiceModuleKey]: getCustomerInvoiceDi, + [invoiceModuleKey]: getInvoiceDi, + [summaryInfoModuleKey]: getSummaryInfoDi, + [revenueModuleKey]: getRevenueDi, + }[module]; - if (!getDi) throw new Error("Server Di didn't found for module: " + module) - - const di = getDi() - memoizedDis[module] = di - return di -} \ No newline at end of file + if (!getDi) throw new Error(`Server Di didn't found for module: ${module}`); + + const di = getDi(); + memoizedDis[module] = di; + return di; +} diff --git a/src/feature/core/customer-invoice/data/module/customer-invoice-di.ts b/src/feature/core/customer-invoice/data/module/customer-invoice-di.ts index 5364a92..e470b22 100644 --- a/src/feature/core/customer-invoice/data/module/customer-invoice-di.ts +++ b/src/feature/core/customer-invoice/data/module/customer-invoice-di.ts @@ -4,8 +4,8 @@ import { customerInvoiceRepoKey } from "@/feature/core/customer-invoice/domain/i import { DependencyContainer } from "tsyringe"; export default function getCustomerInvoiceDi(): DependencyContainer { - const customerInvoiceDi = di.createChildContainer() + const customerInvoiceDi = di.createChildContainer(); - customerInvoiceDi.register(customerInvoiceRepoKey, CustomerInvoiceDbRepo) - return customerInvoiceDi -} \ No newline at end of file + customerInvoiceDi.register(customerInvoiceRepoKey, CustomerInvoiceDbRepo); + return customerInvoiceDi; +} diff --git a/src/feature/core/customer-invoice/data/repo/customer-invoice-db-repo.ts b/src/feature/core/customer-invoice/data/repo/customer-invoice-db-repo.ts index bc35087..243b8e1 100644 --- a/src/feature/core/customer-invoice/data/repo/customer-invoice-db-repo.ts +++ b/src/feature/core/customer-invoice/data/repo/customer-invoice-db-repo.ts @@ -15,39 +15,44 @@ type customerInvoiceDbResponse = { image_url: string; email: string; amount: string; -} +}; export default class CustomerInvoiceDbRepo implements CustomerInvoiceRepo { - fetchList(): ApiTask<CustomerInvoice[]> { - return pipe( - tryCatch( - async () => { - const response = await sql` + fetchList(): ApiTask<CustomerInvoice[]> { + return pipe( + tryCatch( + async () => { + const response = (await sql` SELECT invoices.amount, customers.name, customers.image_url, customers.email, invoices.id FROM invoices JOIN customers ON invoices.customer_id = customers.id ORDER BY invoices.date DESC - LIMIT 20 ` as postgres.RowList<customerInvoiceDbResponse[]>; - - return this.customerInvoicesDto(response) - }, - (l) => failureOr(l, new NetworkFailure()) - ) - ) - } + LIMIT 20 `) as postgres.RowList< + customerInvoiceDbResponse[] + >; - private customerInvoicesDto(dbCustomers: customerInvoiceDbResponse[]): CustomerInvoice[] { - return dbCustomers.map((customer) => this.customerInvoiceDto(customer)); - } + return this.customerInvoicesDto(response); + }, + (l) => failureOr(l, new NetworkFailure()), + ), + ); + } - private customerInvoiceDto(dbCustomer: customerInvoiceDbResponse): CustomerInvoice { - return new CustomerInvoice({ - id: dbCustomer.id, - customerName: dbCustomer.name, - customerEmail: dbCustomer.email, - customerImageUrl: dbCustomer.image_url, - invoicesAmount: formatCurrency(+dbCustomer.amount), - }) - } + private customerInvoicesDto( + dbCustomers: customerInvoiceDbResponse[], + ): CustomerInvoice[] { + return dbCustomers.map((customer) => this.customerInvoiceDto(customer)); + } -} \ No newline at end of file + private customerInvoiceDto( + dbCustomer: customerInvoiceDbResponse, + ): CustomerInvoice { + return new CustomerInvoice({ + id: dbCustomer.id, + customerName: dbCustomer.name, + customerEmail: dbCustomer.email, + customerImageUrl: dbCustomer.image_url, + invoicesAmount: formatCurrency(+dbCustomer.amount), + }); + } +} diff --git a/src/feature/core/customer-invoice/domain/entity/customer-invoice.ts b/src/feature/core/customer-invoice/domain/entity/customer-invoice.ts index 783654c..9619393 100644 --- a/src/feature/core/customer-invoice/domain/entity/customer-invoice.ts +++ b/src/feature/core/customer-invoice/domain/entity/customer-invoice.ts @@ -1,21 +1,25 @@ export default class CustomerInvoice { - id: string; - customerName: string; - customerImageUrl: string; - customerEmail: string; - invoicesAmount: string; + id: string; - constructor({ - id, - customerEmail, - customerImageUrl, - customerName, - invoicesAmount - }: CustomerInvoice) { - this.id = id; - this.customerEmail = customerEmail - this.customerImageUrl = customerImageUrl - this.customerName = customerName - this.invoicesAmount = invoicesAmount - } -} \ No newline at end of file + customerName: string; + + customerImageUrl: string; + + customerEmail: string; + + invoicesAmount: string; + + constructor({ + id, + customerEmail, + customerImageUrl, + customerName, + invoicesAmount, + }: CustomerInvoice) { + this.id = id; + this.customerEmail = customerEmail; + this.customerImageUrl = customerImageUrl; + this.customerName = customerName; + this.invoicesAmount = invoicesAmount; + } +} diff --git a/src/feature/core/customer-invoice/domain/i-repo/customer-invoice-repo.ts b/src/feature/core/customer-invoice/domain/i-repo/customer-invoice-repo.ts index ab4b486..17a7f4d 100644 --- a/src/feature/core/customer-invoice/domain/i-repo/customer-invoice-repo.ts +++ b/src/feature/core/customer-invoice/domain/i-repo/customer-invoice-repo.ts @@ -1,8 +1,8 @@ -import ApiTask from "@/feature/common/data/api-task" -import CustomerInvoice from "@/feature/core/customer-invoice/domain/entity/customer-invoice" +import ApiTask from "@/feature/common/data/api-task"; +import CustomerInvoice from "@/feature/core/customer-invoice/domain/entity/customer-invoice"; export default interface CustomerInvoiceRepo { - fetchList(): ApiTask<CustomerInvoice[]> + fetchList(): ApiTask<CustomerInvoice[]>; } -export const customerInvoiceRepoKey = "customerInvoiceRepoKey" \ No newline at end of file +export const customerInvoiceRepoKey = "customerInvoiceRepoKey"; diff --git a/src/feature/core/customer-invoice/domain/usecase/fetch-customer-invoices-usecase.ts b/src/feature/core/customer-invoice/domain/usecase/fetch-customer-invoices-usecase.ts index 5d2df55..a2bd48e 100644 --- a/src/feature/core/customer-invoice/domain/usecase/fetch-customer-invoices-usecase.ts +++ b/src/feature/core/customer-invoice/domain/usecase/fetch-customer-invoices-usecase.ts @@ -1,12 +1,18 @@ import { ApiEither } from "@/feature/common/data/api-task"; import serverDi from "@/feature/common/server-di"; import CustomerInvoice from "@/feature/core/customer-invoice/domain/entity/customer-invoice"; -import CustomerInvoiceRepo, { customerInvoiceRepoKey } from "@/feature/core/customer-invoice/domain/i-repo/customer-invoice-repo"; +import CustomerInvoiceRepo, { + customerInvoiceRepoKey, +} from "@/feature/core/customer-invoice/domain/i-repo/customer-invoice-repo"; import { customerInvoiceModuleKey } from "@/feature/core/customer-invoice/invoice-module-key"; import { connection } from "next/server"; -export default async function fetchCustomerInvoicesUsecase(): Promise<ApiEither<CustomerInvoice[]>> { - connection() - const repo = serverDi(customerInvoiceModuleKey).resolve<CustomerInvoiceRepo>(customerInvoiceRepoKey) - return repo.fetchList()() -} \ No newline at end of file +export default async function fetchCustomerInvoicesUsecase(): Promise< + ApiEither<CustomerInvoice[]> +> { + connection(); + const repo = serverDi(customerInvoiceModuleKey).resolve<CustomerInvoiceRepo>( + customerInvoiceRepoKey, + ); + return repo.fetchList()(); +} diff --git a/src/feature/core/customer-invoice/invoice-module-key.ts b/src/feature/core/customer-invoice/invoice-module-key.ts index 6ab1512..3094d82 100644 --- a/src/feature/core/customer-invoice/invoice-module-key.ts +++ b/src/feature/core/customer-invoice/invoice-module-key.ts @@ -1 +1 @@ -export const customerInvoiceModuleKey = "customerInvoiceModuleKey" \ No newline at end of file +export const customerInvoiceModuleKey = "customerInvoiceModuleKey"; diff --git a/src/feature/core/customer/customer-key.ts b/src/feature/core/customer/customer-key.ts index 9ae5f45..d3e55c2 100644 --- a/src/feature/core/customer/customer-key.ts +++ b/src/feature/core/customer/customer-key.ts @@ -1 +1 @@ -export const customerKey = "customerKey" \ No newline at end of file +export const customerKey = "customerKey"; diff --git a/src/feature/core/customer/data/module/customer-di.ts b/src/feature/core/customer/data/module/customer-di.ts index c3806ee..99afe05 100644 --- a/src/feature/core/customer/data/module/customer-di.ts +++ b/src/feature/core/customer/data/module/customer-di.ts @@ -4,8 +4,8 @@ import { customerRepoKey } from "@/feature/core/customer/domain/i-repo/customer- import { DependencyContainer } from "tsyringe"; export default function getCustomerDi(): DependencyContainer { - const customerDi = di.createChildContainer() + const customerDi = di.createChildContainer(); - customerDi.register(customerRepoKey, CustomerDbRepo) - return customerDi -} \ No newline at end of file + customerDi.register(customerRepoKey, CustomerDbRepo); + return customerDi; +} diff --git a/src/feature/core/customer/data/repo/customer-db-repo.ts b/src/feature/core/customer/data/repo/customer-db-repo.ts index 8c6fba4..5d08bc7 100644 --- a/src/feature/core/customer/data/repo/customer-db-repo.ts +++ b/src/feature/core/customer/data/repo/customer-db-repo.ts @@ -1,7 +1,12 @@ import { sql } from "@/bootstrap/boundaries/db/db"; +import ApiTask from "@/feature/common/data/api-task"; +import { failureOr } from "@/feature/common/failures/failure-helpers"; +import NetworkFailure from "@/feature/common/failures/network-failure"; import { formatCurrency } from "@/feature/common/feature-helpers"; import Customer from "@/feature/core/customer/domain/entity/customer"; import CustomerRepo from "@/feature/core/customer/domain/i-repo/customer-repo"; +import { pipe } from "fp-ts/lib/function"; +import { map, tryCatch } from "fp-ts/lib/TaskEither"; import postgres from "postgres"; type customerDbResponse = { @@ -12,57 +17,60 @@ type customerDbResponse = { total_invoices: string; total_pending: string; total_paid: string; -} +}; export default class CustomerDbRepo implements CustomerRepo { - async fetchList(query: string): Promise<Customer[]> { - try { - const data = await sql` - SELECT - customers.id, - customers.name, - customers.email, - customers.image_url, - COUNT(invoices.id) AS total_invoices, - SUM(CASE WHEN invoices.status = 'pending' THEN invoices.amount ELSE 0 END) AS total_pending, - SUM(CASE WHEN invoices.status = 'paid' THEN invoices.amount ELSE 0 END) AS total_paid - FROM customers - LEFT JOIN invoices ON customers.id = invoices.customer_id - WHERE - customers.name ILIKE ${`%${query}%`} OR - customers.email ILIKE ${`%${query}%`} - GROUP BY customers.id, customers.name, customers.email, customers.image_url - ORDER BY customers.name ASC - ` as postgres.RowList<customerDbResponse[]>; + fetchList(query: string): ApiTask<Customer[]> { + return pipe( + tryCatch( + async () => { + const data = (await sql` + SELECT + customers.id, + customers.name, + customers.email, + customers.image_url, + COUNT(invoices.id) AS total_invoices, + SUM(CASE WHEN invoices.status = 'pending' THEN invoices.amount ELSE 0 END) AS total_pending, + SUM(CASE WHEN invoices.status = 'paid' THEN invoices.amount ELSE 0 END) AS total_paid + FROM customers + LEFT JOIN invoices ON customers.id = invoices.customer_id + WHERE + customers.name ILIKE ${`%${query}%`} OR + customers.email ILIKE ${`%${query}%`} + GROUP BY customers.id, customers.name, customers.email, customers.image_url + ORDER BY customers.name ASC + `) as postgres.RowList<customerDbResponse[]>; + return data; + }, + (l) => failureOr(l, new NetworkFailure(l as Error)), + ), + map(this.customersDto.bind(this)), + ) as ApiTask<Customer[]>; + } - return this.customersDto(data); - } catch (err) { - console.error('Database Error:', err); - throw new Error('Failed to fetch customer table.'); - } - } + async fetchCustomersAmount(): Promise<number> { + const data = + (await sql`SELECT COUNT(*) FROM customers`) as postgres.RowList< + unknown[] + >; + return Number(data.count ?? "0"); + } - async fetchCustomersAmount(): Promise<number> { - const data = await sql`SELECT COUNT(*) FROM customers`as postgres.RowList<unknown[]>; - return Number(data.count ?? '0'); - } + private customersDto(dbCustomers: customerDbResponse[]): Customer[] { + return dbCustomers.map((customer) => this.customerDto(customer)); + } - - private customersDto(dbCustomers: customerDbResponse[]): Customer[] { - return dbCustomers.map((customer) => this.customerDto(customer)); - } - - private customerDto(dbCustomer: customerDbResponse): Customer { - return new Customer({ - id: dbCustomer.id, - name: dbCustomer.name, - email: dbCustomer.email, - imageUrl: dbCustomer.image_url, - totalInvoices: dbCustomer.total_invoices, - totalPending: formatCurrency(Number(dbCustomer.total_pending)), - totalPaid: formatCurrency(Number(dbCustomer.total_paid)), - }) - } - -} \ No newline at end of file + private customerDto(dbCustomer: customerDbResponse): Customer { + return new Customer({ + id: dbCustomer.id, + name: dbCustomer.name, + email: dbCustomer.email, + imageUrl: dbCustomer.image_url, + totalInvoices: dbCustomer.total_invoices, + totalPending: formatCurrency(Number(dbCustomer.total_pending)), + totalPaid: formatCurrency(Number(dbCustomer.total_paid)), + }); + } +} diff --git a/src/feature/core/customer/domain/entity/customer.ts b/src/feature/core/customer/domain/entity/customer.ts index 6f32ec3..ced9522 100644 --- a/src/feature/core/customer/domain/entity/customer.ts +++ b/src/feature/core/customer/domain/entity/customer.ts @@ -1,27 +1,33 @@ export default class Customer { - id: string; - name: string; - email: string; - imageUrl: string; - totalInvoices: string; - totalPending: string; - totalPaid: string; + id: string; - constructor({ - id, - email, - imageUrl, - name, - totalInvoices, - totalPaid, - totalPending - }: Customer) { - this.id = id; - this.name = name; - this.email = email; - this.imageUrl = imageUrl; - this.totalInvoices = totalInvoices; - this.totalPaid = totalPaid; - this.totalPending = totalPending; - } -} \ No newline at end of file + name: string; + + email: string; + + imageUrl: string; + + totalInvoices: string; + + totalPending: string; + + totalPaid: string; + + constructor({ + id, + email, + imageUrl, + name, + totalInvoices, + totalPaid, + totalPending, + }: Customer) { + this.id = id; + this.name = name; + this.email = email; + this.imageUrl = imageUrl; + this.totalInvoices = totalInvoices; + this.totalPaid = totalPaid; + this.totalPending = totalPending; + } +} diff --git a/src/feature/core/customer/domain/i-repo/customer-repo.ts b/src/feature/core/customer/domain/i-repo/customer-repo.ts index 86b890e..f631be0 100644 --- a/src/feature/core/customer/domain/i-repo/customer-repo.ts +++ b/src/feature/core/customer/domain/i-repo/customer-repo.ts @@ -1,9 +1,9 @@ -import ApiTask from "@/feature/common/data/api-task" -import Customer from "@/feature/core/customer/domain/entity/customer" +import ApiTask from "@/feature/common/data/api-task"; +import Customer from "@/feature/core/customer/domain/entity/customer"; export default interface CustomerRepo { - fetchList(query: string): ApiTask<Customer[]> - fetchCustomersAmount(): Promise<number> + fetchList(query: string): ApiTask<Customer[]>; + fetchCustomersAmount(): Promise<number>; } -export const customerRepoKey = "customerRepoKey" \ No newline at end of file +export const customerRepoKey = "customerRepoKey"; diff --git a/src/feature/core/customer/domain/usecase/fetch-customers-amount-usecase.ts b/src/feature/core/customer/domain/usecase/fetch-customers-amount-usecase.ts index 71cd13d..2f5f620 100644 --- a/src/feature/core/customer/domain/usecase/fetch-customers-amount-usecase.ts +++ b/src/feature/core/customer/domain/usecase/fetch-customers-amount-usecase.ts @@ -1,8 +1,10 @@ import serverDi from "@/feature/common/server-di"; import { customerKey } from "@/feature/core/customer/customer-key"; -import CustomerRepo, { customerRepoKey } from "@/feature/core/customer/domain/i-repo/customer-repo"; +import CustomerRepo, { + customerRepoKey, +} from "@/feature/core/customer/domain/i-repo/customer-repo"; export default async function fetchCustomersAmountUsecase(): Promise<number> { - const repo = serverDi(customerKey).resolve<CustomerRepo>(customerRepoKey) - return repo.fetchCustomersAmount() -} \ No newline at end of file + const repo = serverDi(customerKey).resolve<CustomerRepo>(customerRepoKey); + return repo.fetchCustomersAmount(); +} diff --git a/src/feature/core/customer/domain/usecase/fetch-customers-usecase.ts b/src/feature/core/customer/domain/usecase/fetch-customers-usecase.ts index c83a252..716b190 100644 --- a/src/feature/core/customer/domain/usecase/fetch-customers-usecase.ts +++ b/src/feature/core/customer/domain/usecase/fetch-customers-usecase.ts @@ -1,14 +1,19 @@ -"use server" +"use server"; +import { ApiEither } from "@/feature/common/data/api-task"; import serverDi from "@/feature/common/server-di"; import { customerKey } from "@/feature/core/customer/customer-key"; import Customer from "@/feature/core/customer/domain/entity/customer"; -import CustomerRepo, { customerRepoKey } from "@/feature/core/customer/domain/i-repo/customer-repo"; +import CustomerRepo, { + customerRepoKey, +} from "@/feature/core/customer/domain/i-repo/customer-repo"; import { connection } from "next/server"; -export default async function fetchCustomersUsecase(query: string): Promise<Customer[]> { - connection() - const repo = serverDi(customerKey).resolve<CustomerRepo>(customerRepoKey) +export default function fetchCustomersUsecase( + query: string, +): Promise<ApiEither<Customer[]>> { + connection(); + const repo = serverDi(customerKey).resolve<CustomerRepo>(customerRepoKey); - return repo.fetchList(query) -} \ No newline at end of file + return repo.fetchList(query)(); +} diff --git a/src/feature/core/invoice/data/module/invoice-di.ts b/src/feature/core/invoice/data/module/invoice-di.ts index 1434954..e42ae4b 100644 --- a/src/feature/core/invoice/data/module/invoice-di.ts +++ b/src/feature/core/invoice/data/module/invoice-di.ts @@ -4,8 +4,8 @@ import { invoiceRepoKey } from "@/feature/core/invoice/domain/i-repo/invoice-rep import { DependencyContainer } from "tsyringe"; export default function getInvoiceDi(): DependencyContainer { - const invoiceDi = di.createChildContainer() + const invoiceDi = di.createChildContainer(); - invoiceDi.register(invoiceRepoKey, invoiceDbRepo) - return invoiceDi -} \ No newline at end of file + invoiceDi.register(invoiceRepoKey, invoiceDbRepo); + return invoiceDi; +} diff --git a/src/feature/core/invoice/data/repo/invoice-db-repo.ts b/src/feature/core/invoice/data/repo/invoice-db-repo.ts index 416c060..9c7603a 100644 --- a/src/feature/core/invoice/data/repo/invoice-db-repo.ts +++ b/src/feature/core/invoice/data/repo/invoice-db-repo.ts @@ -10,57 +10,60 @@ import { pipe } from "fp-ts/lib/function"; import { tryCatch } from "fp-ts/lib/TaskEither"; import postgres from "postgres"; -type InvoiceSummaryDbResponse = {paid: string, pending: string} +type InvoiceSummaryDbResponse = { paid: string; pending: string }; export default class InvoiceDbRepo implements InvoiceRepo { - async fetchAllInvoicesAmount(): Promise<number> { - const data = await sql`SELECT COUNT(*) FROM invoices` as postgres.RowList<unknown[]>; - - return data.count ?? 0 - } + async fetchAllInvoicesAmount(): Promise<number> { + const data = (await sql`SELECT COUNT(*) FROM invoices`) as postgres.RowList< + unknown[] + >; - createInvoice(params: InvoiceParam): ApiTask<string> { - return pipe( - tryCatch( - async () => { - const firstCustomerIdDb = await sql`SELECT + return data.count ?? 0; + } + + createInvoice(params: InvoiceParam): ApiTask<string> { + return pipe( + tryCatch( + async () => { + const firstCustomerIdDb = await sql`SELECT id FROM customers ORDER BY id DESC LIMIT 1 - ` - const customerId = firstCustomerIdDb.at(0)?.id - if (!customerId) throw new Error("There is no customer") - - const { amount, status } = params; - const amountInCents = amount * 100; - const date = new Date().toISOString().split('T')[0]; - - // Insert data into the database - const result = await sql` + `; + const customerId = firstCustomerIdDb.at(0)?.id; + if (!customerId) throw new Error("There is no customer"); + + const { amount, status } = params; + const amountInCents = amount * 100; + const date = new Date().toISOString().split("T")[0]; + + // Insert data into the database + const result = await sql` INSERT INTO invoices (customer_id, amount, status, date) VALUES (${customerId}, ${amountInCents}, ${status}, ${date}) RETURNING id `; - return result.at(0)?.id ?? "" - }, - (l) => failureOr(l, new NetworkFailure(l as Error)) - ), - ) - } + return result.at(0)?.id ?? ""; + }, + (l) => failureOr(l, new NetworkFailure(l as Error)), + ), + ); + } - async fetchInvoicesStatusSummary(): Promise<InvoiceStatusSummary> { - const invoiceStatusPromise = await sql`SELECT + async fetchInvoicesStatusSummary(): Promise<InvoiceStatusSummary> { + const invoiceStatusPromise = (await sql`SELECT SUM(CASE WHEN status = 'paid' THEN amount ELSE 0 END) AS "paid", SUM(CASE WHEN status = 'pending' THEN amount ELSE 0 END) AS "pending" - FROM invoices` as postgres.RowList<InvoiceSummaryDbResponse[]>; - - return this.invoiceSummaryDto(invoiceStatusPromise.at(0)) - - } + FROM invoices`) as postgres.RowList<InvoiceSummaryDbResponse[]>; - private invoiceSummaryDto(dbResponse?: InvoiceSummaryDbResponse): InvoiceStatusSummary { - return new InvoiceStatusSummary({ - paid: formatCurrency(Number(dbResponse?.paid ?? '0')), - pending: formatCurrency(Number(dbResponse?.pending ?? '0')) - }) - } -} \ No newline at end of file + return this.invoiceSummaryDto(invoiceStatusPromise.at(0)); + } + + private invoiceSummaryDto( + dbResponse?: InvoiceSummaryDbResponse, + ): InvoiceStatusSummary { + return new InvoiceStatusSummary({ + paid: formatCurrency(Number(dbResponse?.paid ?? "0")), + pending: formatCurrency(Number(dbResponse?.pending ?? "0")), + }); + } +} diff --git a/src/feature/core/invoice/domain/i-repo/invoice-repo.ts b/src/feature/core/invoice/domain/i-repo/invoice-repo.ts index ca5096d..049fa98 100644 --- a/src/feature/core/invoice/domain/i-repo/invoice-repo.ts +++ b/src/feature/core/invoice/domain/i-repo/invoice-repo.ts @@ -1,11 +1,11 @@ -import ApiTask from "@/feature/common/data/api-task" -import { InvoiceParam } from "@/feature/core/invoice/domain/param/invoice-param" -import InvoiceStatusSummary from "@/feature/core/invoice/domain/value-object/invoice-status" +import ApiTask from "@/feature/common/data/api-task"; +import { InvoiceParam } from "@/feature/core/invoice/domain/param/invoice-param"; +import InvoiceStatusSummary from "@/feature/core/invoice/domain/value-object/invoice-status"; export default interface InvoiceRepo { - fetchAllInvoicesAmount(): Promise<number> - fetchInvoicesStatusSummary(): Promise<InvoiceStatusSummary> - createInvoice(params: InvoiceParam): ApiTask<string> + fetchAllInvoicesAmount(): Promise<number>; + fetchInvoicesStatusSummary(): Promise<InvoiceStatusSummary>; + createInvoice(params: InvoiceParam): ApiTask<string>; } -export const invoiceRepoKey = "invoiceRepoKey" \ No newline at end of file +export const invoiceRepoKey = "invoiceRepoKey"; diff --git a/src/feature/core/invoice/domain/param/invoice-param.ts b/src/feature/core/invoice/domain/param/invoice-param.ts index 1dce62a..fadf7da 100644 --- a/src/feature/core/invoice/domain/param/invoice-param.ts +++ b/src/feature/core/invoice/domain/param/invoice-param.ts @@ -1,10 +1,12 @@ import { z } from "zod"; export const invoiceSchema = z.object({ - amount: z.coerce.number().gt(0, { message: 'Please enter an amount greater than $0.' }), - status: z.enum(['pending', 'paid'], { - invalid_type_error: 'Please select an invoice status.', + amount: z.coerce + .number() + .gt(0, { message: "Please enter an amount greater than $0." }), + status: z.enum(["pending", "paid"], { + invalid_type_error: "Please select an invoice status.", }), }); -export type InvoiceParam = z.infer<typeof invoiceSchema> \ No newline at end of file +export type InvoiceParam = z.infer<typeof invoiceSchema>; diff --git a/src/feature/core/invoice/domain/usecase/create-invoice-usecase.ts b/src/feature/core/invoice/domain/usecase/create-invoice-usecase.ts index 9cfc63d..7c2f136 100644 --- a/src/feature/core/invoice/domain/usecase/create-invoice-usecase.ts +++ b/src/feature/core/invoice/domain/usecase/create-invoice-usecase.ts @@ -1,24 +1,32 @@ -"use server" +"use server"; + import { ApiEither } from "@/feature/common/data/api-task"; import ParamsFailure from "@/feature/common/failures/params-failure"; import serverDi from "@/feature/common/server-di"; -import InvoiceRepo, { invoiceRepoKey } from "@/feature/core/invoice/domain/i-repo/invoice-repo"; -import { InvoiceParam, invoiceSchema } from "@/feature/core/invoice/domain/param/invoice-param"; +import InvoiceRepo, { + invoiceRepoKey, +} from "@/feature/core/invoice/domain/i-repo/invoice-repo"; +import { + InvoiceParam, + invoiceSchema, +} from "@/feature/core/invoice/domain/param/invoice-param"; import { invoiceModuleKey } from "@/feature/core/invoice/invoice-module-key"; import { pipe } from "fp-ts/lib/function"; import { chain, fromNullable, left, map, right } from "fp-ts/lib/TaskEither"; -export default async function createInvoiceUsecase(params: InvoiceParam): Promise<ApiEither<string>> { - const repo = serverDi(invoiceModuleKey).resolve<InvoiceRepo>(invoiceRepoKey) +export default async function createInvoiceUsecase( + params: InvoiceParam, +): Promise<ApiEither<string>> { + const repo = serverDi(invoiceModuleKey).resolve<InvoiceRepo>(invoiceRepoKey); - return pipe( - fromNullable(new ParamsFailure())(params), - map((params) => invoiceSchema.safeParse(params)), - chain((params) => { - const isParamsValid = invoiceSchema.safeParse(params) - if (!isParamsValid.success) left(new ParamsFailure()) - return right(params.data as InvoiceParam) - }), - chain((params) => repo.createInvoice(params)) - )() -} \ No newline at end of file + return pipe( + fromNullable(new ParamsFailure())(params), + map((params) => invoiceSchema.safeParse(params)), + chain((params) => { + const isParamsValid = invoiceSchema.safeParse(params); + if (!isParamsValid.success) left(new ParamsFailure()); + return right(params.data as InvoiceParam); + }), + chain((params) => repo.createInvoice(params)), + )(); +} diff --git a/src/feature/core/invoice/domain/usecase/fetch-all-invoices-amount-usecase.ts b/src/feature/core/invoice/domain/usecase/fetch-all-invoices-amount-usecase.ts index 48840f4..8b8d04a 100644 --- a/src/feature/core/invoice/domain/usecase/fetch-all-invoices-amount-usecase.ts +++ b/src/feature/core/invoice/domain/usecase/fetch-all-invoices-amount-usecase.ts @@ -1,10 +1,13 @@ -"use server" +"use server"; + import serverDi from "@/feature/common/server-di"; -import InvoiceRepo, { invoiceRepoKey } from "@/feature/core/invoice/domain/i-repo/invoice-repo"; +import InvoiceRepo, { + invoiceRepoKey, +} from "@/feature/core/invoice/domain/i-repo/invoice-repo"; import { invoiceModuleKey } from "@/feature/core/invoice/invoice-module-key"; export default async function fetchAllInvoicesAmountUsecase(): Promise<number> { - const repo = serverDi(invoiceModuleKey).resolve<InvoiceRepo>(invoiceRepoKey) + const repo = serverDi(invoiceModuleKey).resolve<InvoiceRepo>(invoiceRepoKey); - return repo.fetchAllInvoicesAmount() -} \ No newline at end of file + return repo.fetchAllInvoicesAmount(); +} diff --git a/src/feature/core/invoice/domain/usecase/fetch-invoices-status-summary.ts b/src/feature/core/invoice/domain/usecase/fetch-invoices-status-summary.ts index 3bb9a5e..68c96ad 100644 --- a/src/feature/core/invoice/domain/usecase/fetch-invoices-status-summary.ts +++ b/src/feature/core/invoice/domain/usecase/fetch-invoices-status-summary.ts @@ -1,9 +1,11 @@ import serverDi from "@/feature/common/server-di"; -import InvoiceRepo, { invoiceRepoKey } from "@/feature/core/invoice/domain/i-repo/invoice-repo"; +import InvoiceRepo, { + invoiceRepoKey, +} from "@/feature/core/invoice/domain/i-repo/invoice-repo"; import InvoiceStatusSummary from "@/feature/core/invoice/domain/value-object/invoice-status"; import { invoiceModuleKey } from "@/feature/core/invoice/invoice-module-key"; export default async function fetchInvoicesStatusSummary(): Promise<InvoiceStatusSummary> { - const repo = serverDi(invoiceModuleKey).resolve<InvoiceRepo>(invoiceRepoKey) - return repo.fetchInvoicesStatusSummary() -} \ No newline at end of file + const repo = serverDi(invoiceModuleKey).resolve<InvoiceRepo>(invoiceRepoKey); + return repo.fetchInvoicesStatusSummary(); +} diff --git a/src/feature/core/invoice/domain/value-object/invoice-status.ts b/src/feature/core/invoice/domain/value-object/invoice-status.ts index b2c393c..39b99c8 100644 --- a/src/feature/core/invoice/domain/value-object/invoice-status.ts +++ b/src/feature/core/invoice/domain/value-object/invoice-status.ts @@ -1,12 +1,10 @@ export default class InvoiceStatusSummary { - paid: string; - pending: string; + paid: string; - constructor({ - paid, - pending - }: InvoiceStatusSummary) { - this.paid = paid; - this.pending = pending; - } -} \ No newline at end of file + pending: string; + + constructor({ paid, pending }: InvoiceStatusSummary) { + this.paid = paid; + this.pending = pending; + } +} diff --git a/src/feature/core/invoice/invoice-module-key.ts b/src/feature/core/invoice/invoice-module-key.ts index c9cafd9..118ae9a 100644 --- a/src/feature/core/invoice/invoice-module-key.ts +++ b/src/feature/core/invoice/invoice-module-key.ts @@ -1 +1 @@ -export const invoiceModuleKey = "invoiceModuleKey" \ No newline at end of file +export const invoiceModuleKey = "invoiceModuleKey"; diff --git a/src/feature/core/revenue/data/module/revenue-di.ts b/src/feature/core/revenue/data/module/revenue-di.ts index 921a2ed..8e1f828 100644 --- a/src/feature/core/revenue/data/module/revenue-di.ts +++ b/src/feature/core/revenue/data/module/revenue-di.ts @@ -1,10 +1,10 @@ -import di from "@/bootstrap/di/init-di" -import RevenueDbRepo from "@/feature/core/revenue/data/repo/revenue-db-repo" -import { revenueRepoKey } from "@/feature/core/revenue/domain/i-repo/revenue-repo" +import di from "@/bootstrap/di/init-di"; +import RevenueDbRepo from "@/feature/core/revenue/data/repo/revenue-db-repo"; +import { revenueRepoKey } from "@/feature/core/revenue/domain/i-repo/revenue-repo"; export default function getRevenueDi() { - const revenueDi = di.createChildContainer() + const revenueDi = di.createChildContainer(); - revenueDi.register(revenueRepoKey, RevenueDbRepo) - return revenueDi -} \ No newline at end of file + revenueDi.register(revenueRepoKey, RevenueDbRepo); + return revenueDi; +} diff --git a/src/feature/core/revenue/data/repo/revenue-db-repo.ts b/src/feature/core/revenue/data/repo/revenue-db-repo.ts index d8d771d..2b89341 100644 --- a/src/feature/core/revenue/data/repo/revenue-db-repo.ts +++ b/src/feature/core/revenue/data/repo/revenue-db-repo.ts @@ -1,7 +1,6 @@ import { sql } from "@/bootstrap/boundaries/db/db"; import Revenue from "@/feature/core/revenue/domain/entity/revenue"; import RevenueRepo from "@/feature/core/revenue/domain/i-repo/revenue-repo"; -import { connection } from "next/server"; import postgres from "postgres"; export type RevenueDbResponse = { @@ -9,33 +8,30 @@ export type RevenueDbResponse = { revenue: number; }; export default class RevenueDbRepo implements RevenueRepo { - async fetchRevenues(): Promise<Revenue[]> { - try { - // Artificially delay a response for demo purposes. - // Don't do this in production :) - await new Promise((resolve) => setTimeout(resolve, 3000)); + async fetchRevenues(): Promise<Revenue[]> { + try { + // Artificially delay a response for demo purposes. + // Don't do this in production :) + await new Promise((resolve) => setTimeout(resolve, 3000)); - const data = await sql`SELECT * FROM revenue` as postgres.RowList<RevenueDbResponse[]>; + const data = (await sql`SELECT * FROM revenue`) as postgres.RowList< + RevenueDbResponse[] + >; - console.log('Data fetch completed after 3 seconds.'); - - return this.revenuesDto(data); - } catch (error) { - console.error('Database Error:', error); - throw new Error('Failed to fetch revenue data.'); - } + return this.revenuesDto(data); + } catch { + throw new Error("Failed to fetch revenue data."); } + } + private revenuesDto(dbResponse: RevenueDbResponse[]): Revenue[] { + return dbResponse.map((dbRevenue) => this.revenueDto(dbRevenue)); + } - private revenuesDto(dbResponse: RevenueDbResponse[]): Revenue[] { - return dbResponse.map((dbRevenue) => this.revenueDto(dbRevenue)) - } - - private revenueDto(dbResponse: RevenueDbResponse): Revenue { - return new Revenue({ - month: dbResponse.month, - revenue: dbResponse.revenue - }) - } - -} \ No newline at end of file + private revenueDto(dbResponse: RevenueDbResponse): Revenue { + return new Revenue({ + month: dbResponse.month, + revenue: dbResponse.revenue, + }); + } +} diff --git a/src/feature/core/revenue/domain/entity/revenue.ts b/src/feature/core/revenue/domain/entity/revenue.ts index 290ca32..11bd79e 100644 --- a/src/feature/core/revenue/domain/entity/revenue.ts +++ b/src/feature/core/revenue/domain/entity/revenue.ts @@ -1,14 +1,10 @@ export default class Revenue { - month: string; - revenue: number; + month: string; - constructor( - { - month, - revenue - }: Revenue - ) { - this.month = month - this.revenue = revenue - } -} \ No newline at end of file + revenue: number; + + constructor({ month, revenue }: Revenue) { + this.month = month; + this.revenue = revenue; + } +} diff --git a/src/feature/core/revenue/domain/i-repo/revenue-repo.ts b/src/feature/core/revenue/domain/i-repo/revenue-repo.ts index be6924b..7b67fd5 100644 --- a/src/feature/core/revenue/domain/i-repo/revenue-repo.ts +++ b/src/feature/core/revenue/domain/i-repo/revenue-repo.ts @@ -1,7 +1,7 @@ import Revenue from "@/feature/core/revenue/domain/entity/revenue"; export default interface RevenueRepo { - fetchRevenues(): Promise<Revenue[]> + fetchRevenues(): Promise<Revenue[]>; } -export const revenueRepoKey = "revenueRepoKey" \ No newline at end of file +export const revenueRepoKey = "revenueRepoKey"; diff --git a/src/feature/core/revenue/domain/revenue-module-key.ts b/src/feature/core/revenue/domain/revenue-module-key.ts index 27150fb..ebad37f 100644 --- a/src/feature/core/revenue/domain/revenue-module-key.ts +++ b/src/feature/core/revenue/domain/revenue-module-key.ts @@ -1 +1 @@ -export const revenueModuleKey = "RevenueModuleKey" \ No newline at end of file +export const revenueModuleKey = "RevenueModuleKey"; diff --git a/src/feature/core/revenue/domain/usecase/fetch-revenues-usecase.ts b/src/feature/core/revenue/domain/usecase/fetch-revenues-usecase.ts index 0f428c5..57b5a5d 100644 --- a/src/feature/core/revenue/domain/usecase/fetch-revenues-usecase.ts +++ b/src/feature/core/revenue/domain/usecase/fetch-revenues-usecase.ts @@ -1,9 +1,11 @@ import serverDi from "@/feature/common/server-di"; import Revenue from "@/feature/core/revenue/domain/entity/revenue"; -import RevenueRepo, { revenueRepoKey } from "@/feature/core/revenue/domain/i-repo/revenue-repo"; +import RevenueRepo, { + revenueRepoKey, +} from "@/feature/core/revenue/domain/i-repo/revenue-repo"; import { revenueModuleKey } from "@/feature/core/revenue/domain/revenue-module-key"; export default async function fetchRevenuesUsecase(): Promise<Revenue[]> { - const repo = serverDi(revenueModuleKey).resolve<RevenueRepo>(revenueRepoKey) - return repo.fetchRevenues() -} \ No newline at end of file + const repo = serverDi(revenueModuleKey).resolve<RevenueRepo>(revenueRepoKey); + return repo.fetchRevenues(); +} diff --git a/src/feature/core/summary-info/data/module/summary-info-di.ts b/src/feature/core/summary-info/data/module/summary-info-di.ts index 9172b3d..78e8bc7 100644 --- a/src/feature/core/summary-info/data/module/summary-info-di.ts +++ b/src/feature/core/summary-info/data/module/summary-info-di.ts @@ -1,19 +1,19 @@ -import di from "@/bootstrap/di/init-di" -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 fetchInvoicesStatusSummary from "@/feature/core/invoice/domain/usecase/fetch-invoices-status-summary" +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 fetchInvoicesStatusSummary from "@/feature/core/invoice/domain/usecase/fetch-invoices-status-summary"; +import di from "@/bootstrap/di/init-di"; export default function getSummaryInfoDi() { - const summaryInfoDi = di.createChildContainer() + const summaryInfoDi = di.createChildContainer(); - summaryInfoDi.register(fetchAllInvoicesAmountUsecase.name, { - useValue: fetchAllInvoicesAmountUsecase - }) - summaryInfoDi.register(fetchCustomersAmountUsecase.name, { - useValue: fetchCustomersAmountUsecase - }) - summaryInfoDi.register(fetchInvoicesStatusSummary.name, { - useValue: fetchInvoicesStatusSummary - }) - return summaryInfoDi -} \ No newline at end of file + summaryInfoDi.register(fetchAllInvoicesAmountUsecase.name, { + useValue: fetchAllInvoicesAmountUsecase, + }); + summaryInfoDi.register(fetchCustomersAmountUsecase.name, { + useValue: fetchCustomersAmountUsecase, + }); + summaryInfoDi.register(fetchInvoicesStatusSummary.name, { + useValue: fetchInvoicesStatusSummary, + }); + return summaryInfoDi; +} diff --git a/src/feature/core/summary-info/domain/summary-info-module-key.ts b/src/feature/core/summary-info/domain/summary-info-module-key.ts index a2e027b..45f5966 100644 --- a/src/feature/core/summary-info/domain/summary-info-module-key.ts +++ b/src/feature/core/summary-info/domain/summary-info-module-key.ts @@ -1 +1 @@ -export const summaryInfoModuleKey = "summaryInfoModuleKey" \ No newline at end of file +export const summaryInfoModuleKey = "summaryInfoModuleKey"; diff --git a/src/feature/core/summary-info/domain/usecase/fetch-summary-info-usecase.ts b/src/feature/core/summary-info/domain/usecase/fetch-summary-info-usecase.ts index e0a6305..33bbec4 100644 --- a/src/feature/core/summary-info/domain/usecase/fetch-summary-info-usecase.ts +++ b/src/feature/core/summary-info/domain/usecase/fetch-summary-info-usecase.ts @@ -7,28 +7,33 @@ import SummaryInfo from "@/feature/core/summary-info/domain/value-object/summary import { connection } from "next/server"; export default async function fetchSummaryInfoUsecase(): Promise<SummaryInfo> { - connection() + connection(); - try{ - const summaryInfoDi = serverDi(summaryInfoModuleKey) - const invoicesAmountPromise = summaryInfoDi.resolve<typeof fetchAllInvoicesAmountUsecase>(fetchAllInvoicesAmountUsecase.name)() - const customersAmountPromise = summaryInfoDi.resolve<typeof fetchCustomersAmountUsecase>(fetchCustomersAmountUsecase.name)() - const invoiceSummaryPomise = summaryInfoDi.resolve<typeof fetchInvoicesStatusSummary>(fetchInvoicesStatusSummary.name)() + try { + const summaryInfoDi = serverDi(summaryInfoModuleKey); + const invoicesAmountPromise = summaryInfoDi.resolve< + typeof fetchAllInvoicesAmountUsecase + >(fetchAllInvoicesAmountUsecase.name)(); + const customersAmountPromise = summaryInfoDi.resolve< + typeof fetchCustomersAmountUsecase + >(fetchCustomersAmountUsecase.name)(); + const invoiceSummaryPomise = summaryInfoDi.resolve< + typeof fetchInvoicesStatusSummary + >(fetchInvoicesStatusSummary.name)(); - const [invoicesAmount, customersAmount, invoicesSummary] = await Promise.all([ - invoicesAmountPromise, - customersAmountPromise, - invoiceSummaryPomise, - ]); + const [invoicesAmount, customersAmount, invoicesSummary] = + await Promise.all([ + invoicesAmountPromise, + customersAmountPromise, + invoiceSummaryPomise, + ]); - - return new SummaryInfo({ - invoicesNumber: invoicesAmount, - customersNumber: customersAmount, - invoicesSummary: invoicesSummary - }) - } catch (error) { - console.error('Database Error:', error); - throw new Error('Failed to fetch card data.'); - } -} \ No newline at end of file + return new SummaryInfo({ + invoicesNumber: invoicesAmount, + customersNumber: customersAmount, + invoicesSummary, + }); + } catch { + throw new Error("Failed to fetch card data."); + } +} diff --git a/src/feature/core/summary-info/domain/value-object/summary-info.ts b/src/feature/core/summary-info/domain/value-object/summary-info.ts index 9c30901..19d4fff 100644 --- a/src/feature/core/summary-info/domain/value-object/summary-info.ts +++ b/src/feature/core/summary-info/domain/value-object/summary-info.ts @@ -1,17 +1,19 @@ import InvoiceStatusSummary from "@/feature/core/invoice/domain/value-object/invoice-status"; export default class SummaryInfo { - customersNumber: number; - invoicesNumber: number; - invoicesSummary: InvoiceStatusSummary + customersNumber: number; - constructor({ - customersNumber, - invoicesNumber, - invoicesSummary - }: SummaryInfo) { - this.customersNumber = customersNumber - this.invoicesNumber = invoicesNumber - this.invoicesSummary = invoicesSummary - } -} \ No newline at end of file + invoicesNumber: number; + + invoicesSummary: InvoiceStatusSummary; + + constructor({ + customersNumber, + invoicesNumber, + invoicesSummary, + }: SummaryInfo) { + this.customersNumber = customersNumber; + this.invoicesNumber = invoicesNumber; + this.invoicesSummary = invoicesSummary; + } +} diff --git a/src/middleware.ts b/src/middleware.ts index 8c6f760..b8ead4c 100644 --- a/src/middleware.ts +++ b/src/middleware.ts @@ -1,36 +1,41 @@ -import { NextRequest, NextResponse } from 'next/server' -import acceptLanguage from 'accept-language' -import { cookieName, fallbackLng, languages } from '@/bootstrap/i18n/settings' +import { NextRequest, NextResponse } from "next/server"; +import acceptLanguage from "accept-language"; +import { cookieName, fallbackLng, languages } from "@/bootstrap/i18n/settings"; -acceptLanguage.languages(languages) +acceptLanguage.languages(languages); export const config = { - matcher: ["/((?!api|static|.*\\..*|_next).*)"] -} + matcher: ["/((?!api|static|.*\\..*|_next).*)"], +}; export function middleware(req: NextRequest) { - let lng - if (req.cookies.has(cookieName)) lng = acceptLanguage.get(req?.cookies?.get(cookieName)?.value) - if (!lng) lng = acceptLanguage.get(req.headers.get('Accept-Language')) - if (!lng) lng = fallbackLng + let lng; + if (req.cookies.has(cookieName)) + lng = acceptLanguage.get(req?.cookies?.get(cookieName)?.value); + if (!lng) lng = acceptLanguage.get(req.headers.get("Accept-Language")); + if (!lng) lng = fallbackLng; // Redirect if lng in path is not supported if ( - !languages.some(loc => req.nextUrl.pathname.startsWith(`/${loc}`)) && - !req.nextUrl.pathname.startsWith('/_next') + !languages.some((loc) => req.nextUrl.pathname.startsWith(`/${loc}`)) && + !req.nextUrl.pathname.startsWith("/_next") ) { - return NextResponse.redirect(new URL(`/${lng}${req.nextUrl.pathname}`, req.url)) + return NextResponse.redirect( + new URL(`/${lng}${req.nextUrl.pathname}`, req.url), + ); } - if (req.headers.has('referer')) { - const refererUrl = new URL(req?.headers?.get('referer') ?? "") - const lngInReferer = languages.find((l) => refererUrl.pathname.startsWith(`/${l}`)) - const response = NextResponse.next() + if (req.headers.has("referer")) { + const refererUrl = new URL(req?.headers?.get("referer") ?? ""); + const lngInReferer = languages.find((l) => + refererUrl.pathname.startsWith(`/${l}`), + ); + const response = NextResponse.next(); if (lngInReferer) { - response.cookies.set(cookieName, lngInReferer) + response.cookies.set(cookieName, lngInReferer); } - return response + return response; } - return NextResponse.next() -} \ No newline at end of file + return NextResponse.next(); +} diff --git a/src/test/common/fake-factory/customer/customer-fake-factory.ts b/src/test/common/fake-factory/customer/customer-fake-factory.ts index 319c223..ff2bd38 100644 --- a/src/test/common/fake-factory/customer/customer-fake-factory.ts +++ b/src/test/common/fake-factory/customer/customer-fake-factory.ts @@ -2,20 +2,21 @@ import Customer from "@/feature/core/customer/domain/entity/customer"; import { faker } from "@faker-js/faker"; export default class CustomerFakeFactory { - static getFakeCustomer(): Customer { - return new Customer({ - id: faker.string.uuid(), - name: faker.person.fullName(), - email: faker.internet.email(), - imageUrl: faker.image.url(), - totalInvoices: faker.number.int().toLocaleString(), - totalPaid: faker.finance.amount(), - totalPending: faker.number.int().toLocaleString(), - }) - } + static getFakeCustomer(): Customer { + return new Customer({ + id: faker.string.uuid(), + name: faker.person.fullName(), + email: faker.internet.email(), + imageUrl: faker.image.url(), + totalInvoices: faker.number.int().toLocaleString(), + totalPaid: faker.finance.amount(), + totalPending: faker.number.int().toLocaleString(), + }); + } - - static getFakeCustomerList(length: number = 10): Customer[] { - return Array.from({length}).map(() => CustomerFakeFactory.getFakeCustomer()) - } -} \ No newline at end of file + static getFakeCustomerList(length: number = 10): Customer[] { + return Array.from({ length }).map(() => + CustomerFakeFactory.getFakeCustomer(), + ); + } +} diff --git a/src/test/common/mock/mock-di.ts b/src/test/common/mock/mock-di.ts index 3bb7d4e..6e7b03d 100644 --- a/src/test/common/mock/mock-di.ts +++ b/src/test/common/mock/mock-di.ts @@ -1,7 +1,7 @@ -import di from "@/bootstrap/di/init-di" -import * as serverDi from "@/feature/common/server-di" +import di from "@/bootstrap/di/init-di"; +import * as serverDi from "@/feature/common/server-di"; export default function mockDi() { - vi.spyOn(serverDi, "default").mockReturnValue(di) - return di -} \ No newline at end of file + vi.spyOn(serverDi, "default").mockReturnValue(di); + return di; +} diff --git a/src/test/setup.ts b/src/test/setup.ts index 48d5e07..fded23a 100644 --- a/src/test/setup.ts +++ b/src/test/setup.ts @@ -1 +1 @@ -import "reflect-metadata"; \ No newline at end of file +import "reflect-metadata"; diff --git a/src/test/unit/feature/customer/domain/usecase/fetch-customers-usecase.test.ts b/src/test/unit/feature/customer/domain/usecase/fetch-customers-usecase.test.ts index 9ce5ccd..437f9c9 100644 --- a/src/test/unit/feature/customer/domain/usecase/fetch-customers-usecase.test.ts +++ b/src/test/unit/feature/customer/domain/usecase/fetch-customers-usecase.test.ts @@ -1,48 +1,53 @@ -import CustomerRepo, { customerRepoKey } from "@/feature/core/customer/domain/i-repo/customer-repo"; +import CustomerRepo, { + customerRepoKey, +} from "@/feature/core/customer/domain/i-repo/customer-repo"; import { getMock } from "@/test/common/mock/mock-factory"; import { describe } from "vitest"; import { faker } from "@faker-js/faker"; import CustomerFakeFactory from "@/test/common/fake-factory/customer/customer-fake-factory"; import fetchCustomersUsecase from "@/feature/core/customer/domain/usecase/fetch-customers-usecase"; import mockDi from "@/test/common/mock/mock-di"; +import { right } from "fp-ts/lib/TaskEither"; /* -------------------------------------------------------------------------- */ /* Faking */ /* -------------------------------------------------------------------------- */ -const fakedCustomerList = CustomerFakeFactory.getFakeCustomerList() +const fakedCustomerList = CustomerFakeFactory.getFakeCustomerList(); /* -------------------------------------------------------------------------- */ /* Mocking */ /* -------------------------------------------------------------------------- */ -const customerDi = mockDi() +const customerDi = mockDi(); -const mockedFetchList = vi.fn<CustomerRepo['fetchList']>() -const MockedRepo = getMock<CustomerRepo>() -MockedRepo.setup((instance) => instance.fetchList).returns(mockedFetchList) +const mockedFetchList = vi.fn<CustomerRepo["fetchList"]>(); +const MockedRepo = getMock<CustomerRepo>(); +MockedRepo.setup((instance) => instance.fetchList).returns(mockedFetchList); /* -------------------------------------------------------------------------- */ /* DI */ /* -------------------------------------------------------------------------- */ customerDi.register(fetchCustomersUsecase.name, { - useValue: fetchCustomersUsecase -}) + useValue: fetchCustomersUsecase, +}); customerDi.register(customerRepoKey, { - useValue: MockedRepo.object() -}) + useValue: MockedRepo.object(), +}); /* -------------------------------------------------------------------------- */ /* Testing */ /* -------------------------------------------------------------------------- */ -const usecase = customerDi.resolve<typeof fetchCustomersUsecase>(fetchCustomersUsecase.name) +const usecase = customerDi.resolve<typeof fetchCustomersUsecase>( + fetchCustomersUsecase.name, +); describe("Fetch customers", () => { - describe("On given query string", () => { - const fakedQuery = faker.person.fullName(); - describe("And returning list from repo", () => { - beforeEach(() => { - mockedFetchList.mockResolvedValue(fakedCustomerList) - }) - it("Then should return correct list of customers", async () => { - // ! Act - const response = await usecase(fakedQuery) - // ? Assert - expect(response).toEqual(fakedCustomerList) - }) - }); + describe("On given query string", () => { + const fakedQuery = faker.person.fullName(); + describe("And returning list from repo", () => { + beforeEach(() => { + mockedFetchList.mockResolvedValue(right(fakedCustomerList)); + }); + it("Then should return correct list of customers", async () => { + // ! Act + const response = await usecase(fakedQuery); + // ? Assert + expect(response).toEqual(fakedCustomerList); + }); }); -}); \ No newline at end of file + }); +}); diff --git a/yarn.lock b/yarn.lock index cac9504..32d67a6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -620,6 +620,11 @@ resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33" integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg== +"@pkgr/core@^0.1.0": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@pkgr/core/-/core-0.1.1.tgz#1ec17e2edbec25c8306d424ecfbf13c7de1aaa31" + integrity sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA== + "@radix-ui/react-compose-refs@1.1.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.0.tgz#656432461fc8283d7b591dcf0d79152fae9ecc74" @@ -1465,6 +1470,11 @@ concat-map@0.0.1: resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== +confusing-browser-globals@^1.0.10: + version "1.0.11" + resolved "https://registry.yarnpkg.com/confusing-browser-globals/-/confusing-browser-globals-1.0.11.tgz#ae40e9b57cdd3915408a2805ebd3a5585608dc81" + integrity sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA== + console-control-strings@^1.0.0, console-control-strings@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" @@ -1835,6 +1845,25 @@ escape-string-regexp@^4.0.0: resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== +eslint-config-airbnb-base@^15.0.0: + version "15.0.0" + resolved "https://registry.yarnpkg.com/eslint-config-airbnb-base/-/eslint-config-airbnb-base-15.0.0.tgz#6b09add90ac79c2f8d723a2580e07f3925afd236" + integrity sha512-xaX3z4ZZIcFLvh2oUNvcX5oEofXda7giYmuplVxoOg5A7EXJMrUyqRgR+mhDhPK8LZ4PttFOBvCYDbX3sUoUig== + dependencies: + confusing-browser-globals "^1.0.10" + object.assign "^4.1.2" + object.entries "^1.1.5" + semver "^6.3.0" + +eslint-config-airbnb@^19.0.4: + version "19.0.4" + resolved "https://registry.yarnpkg.com/eslint-config-airbnb/-/eslint-config-airbnb-19.0.4.tgz#84d4c3490ad70a0ffa571138ebcdea6ab085fdc3" + integrity sha512-T75QYQVQX57jiNgpF9r1KegMICE94VYwoFQyMGhrvc+lB8YF2E/M/PYDaQe1AJcWaEgqLE+ErXV1Og/+6Vyzew== + dependencies: + eslint-config-airbnb-base "^15.0.0" + object.assign "^4.1.2" + object.entries "^1.1.5" + eslint-config-next@15.0.1: version "15.0.1" resolved "https://registry.yarnpkg.com/eslint-config-next/-/eslint-config-next-15.0.1.tgz#5f49a01d312420cdbf1e87299396ef779ae99004" @@ -1851,6 +1880,16 @@ eslint-config-next@15.0.1: eslint-plugin-react "^7.35.0" eslint-plugin-react-hooks "^5.0.0" +eslint-config-prettier@^9.1.0: + version "9.1.0" + resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz#31af3d94578645966c082fcb71a5846d3c94867f" + integrity sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw== + +eslint-import-resolver-alias@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/eslint-import-resolver-alias/-/eslint-import-resolver-alias-1.1.2.tgz#297062890e31e4d6651eb5eba9534e1f6e68fc97" + integrity sha512-WdviM1Eu834zsfjHtcGHtGfcu+F30Od3V7I9Fi57uhBEwPkjDcii7/yW8jAT+gOhn4P/vOxxNAXbFAKsrrc15w== + eslint-import-resolver-node@^0.3.6, eslint-import-resolver-node@^0.3.9: version "0.3.9" resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz#d4eaac52b8a2e7c3cd1903eb00f7e053356118ac" @@ -1860,7 +1899,7 @@ eslint-import-resolver-node@^0.3.6, eslint-import-resolver-node@^0.3.9: is-core-module "^2.13.0" resolve "^1.22.4" -eslint-import-resolver-typescript@^3.5.2: +eslint-import-resolver-typescript@^3.5.2, eslint-import-resolver-typescript@^3.6.3: version "3.6.3" resolved "https://registry.yarnpkg.com/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.6.3.tgz#bb8e388f6afc0f940ce5d2c5fd4a3d147f038d9e" integrity sha512-ud9aw4szY9cCT1EWWdGv1L1XR6hh2PaRWif0j2QjQ0pgTY/69iw+W0Z4qZv5wHahOl8isEr+k/JnyAqNQkLkIA== @@ -1927,6 +1966,14 @@ eslint-plugin-jsx-a11y@^6.10.0: safe-regex-test "^1.0.3" string.prototype.includes "^2.0.1" +eslint-plugin-prettier@^5.2.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.1.tgz#d1c8f972d8f60e414c25465c163d16f209411f95" + integrity sha512-gH3iR3g4JfF+yYPaJYkN7jEl9QbweL/YfkoRlNnuIEHEz1vHVlCmWOS+eGGiRuzHQXdJFCOTxRgvju9b8VUmrw== + dependencies: + prettier-linter-helpers "^1.0.0" + synckit "^0.9.1" + eslint-plugin-react-hooks@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.0.0.tgz#72e2eefbac4b694f5324154619fee44f5f60f101" @@ -2063,6 +2110,11 @@ fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== +fast-diff@^1.1.2: + version "1.3.0" + resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.3.0.tgz#ece407fa550a64d638536cd727e129c61616e0f0" + integrity sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw== + fast-glob@3.3.1: version "3.3.1" resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.1.tgz#784b4e897340f3dbbef17413b3f11acf03c874c4" @@ -3107,7 +3159,7 @@ object-keys@^1.1.1: resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== -object.assign@^4.1.4, object.assign@^4.1.5: +object.assign@^4.1.2, object.assign@^4.1.4, object.assign@^4.1.5: version "4.1.5" resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.5.tgz#3a833f9ab7fdb80fc9e8d2300c803d216d8fdbb0" integrity sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ== @@ -3117,7 +3169,7 @@ object.assign@^4.1.4, object.assign@^4.1.5: has-symbols "^1.0.3" object-keys "^1.1.1" -object.entries@^1.1.8: +object.entries@^1.1.5, object.entries@^1.1.8: version "1.1.8" resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.8.tgz#bffe6f282e01f4d17807204a24f8edd823599c41" integrity sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ== @@ -3341,6 +3393,18 @@ prelude-ls@^1.2.1: resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== +prettier-linter-helpers@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz#d23d41fe1375646de2d0104d3454a3008802cf7b" + integrity sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w== + dependencies: + fast-diff "^1.1.2" + +prettier@^3.3.3: + version "3.3.3" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.3.3.tgz#30c54fe0be0d8d12e6ae61dbb10109ea00d53105" + integrity sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew== + pretty-format@^27.0.2: version "27.5.1" resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-27.5.1.tgz#2181879fdea51a7a5851fb39d920faa63f01d88e" @@ -3589,7 +3653,7 @@ scheduler@0.25.0-rc-69d4b800-20241021: resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.25.0-rc-69d4b800-20241021.tgz#336e47ef2bd5eddb0ebacfd910b5df1b236d92bd" integrity sha512-S5AYX/YhMAN6u9AXgKYbZP4U4ZklC6R9Q7HmFSBk7d4DLiHVNxvAvlSvuM4nxFkwOk50MnpfTKQ7UWHXDOc9Eg== -semver@^6.0.0, semver@^6.3.1: +semver@^6.0.0, semver@^6.3.0, semver@^6.3.1: version "6.3.1" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== @@ -3884,6 +3948,14 @@ symbol-tree@^3.2.4: resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2" integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw== +synckit@^0.9.1: + version "0.9.2" + resolved "https://registry.yarnpkg.com/synckit/-/synckit-0.9.2.tgz#a3a935eca7922d48b9e7d6c61822ee6c3ae4ec62" + integrity sha512-vrozgXDQwYO72vHjUb/HnFbQx1exDjoKzqx23aXEg2a9VIg2TSFZ8FmeZpTjUCFMYw7mpX4BE2SFu8wI7asYsw== + dependencies: + "@pkgr/core" "^0.1.0" + tslib "^2.6.2" + tailwind-merge@^2.5.4: version "2.5.4" resolved "https://registry.yarnpkg.com/tailwind-merge/-/tailwind-merge-2.5.4.tgz#4bf574e81fa061adeceba099ae4df56edcee78d1" @@ -4041,7 +4113,7 @@ tsconfig-paths@^3.15.0: minimist "^1.2.6" strip-bom "^3.0.0" -tslib@*, tslib@2, tslib@^2.4.0: +tslib@*, tslib@2, tslib@^2.4.0, tslib@^2.6.2: version "2.8.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== -- 2.39.5 From d6fb515d61f806b5c7ebc068045f096e80d205b9 Mon Sep 17 00:00:00 2001 From: behnam <behnamrahimpour74@gmail.com> Date: Fri, 15 Nov 2024 19:54:29 +0300 Subject: [PATCH 34/37] Fix domain issues --- package.json | 1 + .../dashboard/components/server/cards/cards-controller.ts | 2 ++ .../server/latest-invoices/latest-invoices-controller.ts | 2 ++ .../domain/usecase/fetch-customer-invoices-usecase.ts | 5 ++--- .../domain/usecase/fetch-customers-amount-usecase.ts | 1 + .../core/customer/domain/usecase/fetch-customers-usecase.ts | 5 +---- .../domain/usecase/fetch-all-invoices-amount-usecase.ts | 5 ++--- .../invoice/domain/usecase/fetch-invoices-status-summary.ts | 3 ++- .../core/revenue/domain/usecase/fetch-revenues-usecase.ts | 3 ++- .../domain/usecase/fetch-summary-info-usecase.ts | 4 +--- yarn.lock | 5 +++++ 11 files changed, 21 insertions(+), 15 deletions(-) diff --git a/package.json b/package.json index 3223cf1..ad7a6a0 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,7 @@ "react-dom": "19.0.0-rc-69d4b800-20241021", "react-i18next": "^15.1.0", "reflect-metadata": "^0.2.2", + "server-only": "^0.0.1", "tailwind-merge": "^2.5.4", "tailwindcss-animate": "^1.0.7", "tsyringe": "^4.8.0", diff --git a/src/app/[lang]/dashboard/components/server/cards/cards-controller.ts b/src/app/[lang]/dashboard/components/server/cards/cards-controller.ts index 53c601a..9d38e29 100644 --- a/src/app/[lang]/dashboard/components/server/cards/cards-controller.ts +++ b/src/app/[lang]/dashboard/components/server/cards/cards-controller.ts @@ -1,5 +1,7 @@ import fetchSummaryInfoUsecase from "@/feature/core/summary-info/domain/usecase/fetch-summary-info-usecase"; +import { connection } from "next/server"; export default function cardsController() { + connection(); return fetchSummaryInfoUsecase(); } diff --git a/src/app/[lang]/dashboard/components/server/latest-invoices/latest-invoices-controller.ts b/src/app/[lang]/dashboard/components/server/latest-invoices/latest-invoices-controller.ts index 9f34a9a..2b7df56 100644 --- a/src/app/[lang]/dashboard/components/server/latest-invoices/latest-invoices-controller.ts +++ b/src/app/[lang]/dashboard/components/server/latest-invoices/latest-invoices-controller.ts @@ -1,5 +1,7 @@ import fetchCustomerInvoicesUsecase from "@/feature/core/customer-invoice/domain/usecase/fetch-customer-invoices-usecase"; +import { connection } from "next/server"; export default function latestInvoicesController() { + connection(); return fetchCustomerInvoicesUsecase(); } diff --git a/src/feature/core/customer-invoice/domain/usecase/fetch-customer-invoices-usecase.ts b/src/feature/core/customer-invoice/domain/usecase/fetch-customer-invoices-usecase.ts index a2bd48e..7109cef 100644 --- a/src/feature/core/customer-invoice/domain/usecase/fetch-customer-invoices-usecase.ts +++ b/src/feature/core/customer-invoice/domain/usecase/fetch-customer-invoices-usecase.ts @@ -1,3 +1,4 @@ +import "server-only"; import { ApiEither } from "@/feature/common/data/api-task"; import serverDi from "@/feature/common/server-di"; import CustomerInvoice from "@/feature/core/customer-invoice/domain/entity/customer-invoice"; @@ -5,12 +6,10 @@ import CustomerInvoiceRepo, { customerInvoiceRepoKey, } from "@/feature/core/customer-invoice/domain/i-repo/customer-invoice-repo"; import { customerInvoiceModuleKey } from "@/feature/core/customer-invoice/invoice-module-key"; -import { connection } from "next/server"; -export default async function fetchCustomerInvoicesUsecase(): Promise< +export default function fetchCustomerInvoicesUsecase(): Promise< ApiEither<CustomerInvoice[]> > { - connection(); const repo = serverDi(customerInvoiceModuleKey).resolve<CustomerInvoiceRepo>( customerInvoiceRepoKey, ); diff --git a/src/feature/core/customer/domain/usecase/fetch-customers-amount-usecase.ts b/src/feature/core/customer/domain/usecase/fetch-customers-amount-usecase.ts index 2f5f620..e184514 100644 --- a/src/feature/core/customer/domain/usecase/fetch-customers-amount-usecase.ts +++ b/src/feature/core/customer/domain/usecase/fetch-customers-amount-usecase.ts @@ -1,3 +1,4 @@ +import "server-only"; import serverDi from "@/feature/common/server-di"; import { customerKey } from "@/feature/core/customer/customer-key"; import CustomerRepo, { diff --git a/src/feature/core/customer/domain/usecase/fetch-customers-usecase.ts b/src/feature/core/customer/domain/usecase/fetch-customers-usecase.ts index 716b190..0418725 100644 --- a/src/feature/core/customer/domain/usecase/fetch-customers-usecase.ts +++ b/src/feature/core/customer/domain/usecase/fetch-customers-usecase.ts @@ -1,5 +1,4 @@ -"use server"; - +import "server-only"; import { ApiEither } from "@/feature/common/data/api-task"; import serverDi from "@/feature/common/server-di"; import { customerKey } from "@/feature/core/customer/customer-key"; @@ -7,12 +6,10 @@ import Customer from "@/feature/core/customer/domain/entity/customer"; import CustomerRepo, { customerRepoKey, } from "@/feature/core/customer/domain/i-repo/customer-repo"; -import { connection } from "next/server"; export default function fetchCustomersUsecase( query: string, ): Promise<ApiEither<Customer[]>> { - connection(); const repo = serverDi(customerKey).resolve<CustomerRepo>(customerRepoKey); return repo.fetchList(query)(); diff --git a/src/feature/core/invoice/domain/usecase/fetch-all-invoices-amount-usecase.ts b/src/feature/core/invoice/domain/usecase/fetch-all-invoices-amount-usecase.ts index 8b8d04a..77aa180 100644 --- a/src/feature/core/invoice/domain/usecase/fetch-all-invoices-amount-usecase.ts +++ b/src/feature/core/invoice/domain/usecase/fetch-all-invoices-amount-usecase.ts @@ -1,12 +1,11 @@ -"use server"; - +import "server-only"; import serverDi from "@/feature/common/server-di"; import InvoiceRepo, { invoiceRepoKey, } from "@/feature/core/invoice/domain/i-repo/invoice-repo"; import { invoiceModuleKey } from "@/feature/core/invoice/invoice-module-key"; -export default async function fetchAllInvoicesAmountUsecase(): Promise<number> { +export default function fetchAllInvoicesAmountUsecase(): Promise<number> { const repo = serverDi(invoiceModuleKey).resolve<InvoiceRepo>(invoiceRepoKey); return repo.fetchAllInvoicesAmount(); diff --git a/src/feature/core/invoice/domain/usecase/fetch-invoices-status-summary.ts b/src/feature/core/invoice/domain/usecase/fetch-invoices-status-summary.ts index 68c96ad..6ef1a31 100644 --- a/src/feature/core/invoice/domain/usecase/fetch-invoices-status-summary.ts +++ b/src/feature/core/invoice/domain/usecase/fetch-invoices-status-summary.ts @@ -1,3 +1,4 @@ +import "server-only"; import serverDi from "@/feature/common/server-di"; import InvoiceRepo, { invoiceRepoKey, @@ -5,7 +6,7 @@ import InvoiceRepo, { import InvoiceStatusSummary from "@/feature/core/invoice/domain/value-object/invoice-status"; import { invoiceModuleKey } from "@/feature/core/invoice/invoice-module-key"; -export default async function fetchInvoicesStatusSummary(): Promise<InvoiceStatusSummary> { +export default function fetchInvoicesStatusSummary(): Promise<InvoiceStatusSummary> { const repo = serverDi(invoiceModuleKey).resolve<InvoiceRepo>(invoiceRepoKey); return repo.fetchInvoicesStatusSummary(); } diff --git a/src/feature/core/revenue/domain/usecase/fetch-revenues-usecase.ts b/src/feature/core/revenue/domain/usecase/fetch-revenues-usecase.ts index 57b5a5d..ed1812c 100644 --- a/src/feature/core/revenue/domain/usecase/fetch-revenues-usecase.ts +++ b/src/feature/core/revenue/domain/usecase/fetch-revenues-usecase.ts @@ -1,3 +1,4 @@ +import "server-only"; import serverDi from "@/feature/common/server-di"; import Revenue from "@/feature/core/revenue/domain/entity/revenue"; import RevenueRepo, { @@ -5,7 +6,7 @@ import RevenueRepo, { } from "@/feature/core/revenue/domain/i-repo/revenue-repo"; import { revenueModuleKey } from "@/feature/core/revenue/domain/revenue-module-key"; -export default async function fetchRevenuesUsecase(): Promise<Revenue[]> { +export default function fetchRevenuesUsecase(): Promise<Revenue[]> { const repo = serverDi(revenueModuleKey).resolve<RevenueRepo>(revenueRepoKey); return repo.fetchRevenues(); } diff --git a/src/feature/core/summary-info/domain/usecase/fetch-summary-info-usecase.ts b/src/feature/core/summary-info/domain/usecase/fetch-summary-info-usecase.ts index 33bbec4..84af863 100644 --- a/src/feature/core/summary-info/domain/usecase/fetch-summary-info-usecase.ts +++ b/src/feature/core/summary-info/domain/usecase/fetch-summary-info-usecase.ts @@ -1,14 +1,12 @@ +import "server-only"; import serverDi from "@/feature/common/server-di"; 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 fetchInvoicesStatusSummary from "@/feature/core/invoice/domain/usecase/fetch-invoices-status-summary"; 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 { connection } from "next/server"; export default async function fetchSummaryInfoUsecase(): Promise<SummaryInfo> { - connection(); - try { const summaryInfoDi = serverDi(summaryInfoModuleKey); const invoicesAmountPromise = summaryInfoDi.resolve< diff --git a/yarn.lock b/yarn.lock index 32d67a6..827d025 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3663,6 +3663,11 @@ semver@^7.3.5, semver@^7.6.0, semver@^7.6.3: resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.3.tgz#980f7b5550bc175fb4dc09403085627f9eb33143" integrity sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A== +server-only@^0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/server-only/-/server-only-0.0.1.tgz#0f366bb6afb618c37c9255a314535dc412cd1c9e" + integrity sha512-qepMx2JxAa5jjfzxG79yPPq+8BuFToHd1hm7kI+Z4zAq1ftQiP7HcxMhDDItrbtwVeLg/cY2JnKnrcFkmiswNA== + set-blocking@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" -- 2.39.5 From 6b9c2d3925c676dd4f04888da1a4b3fffe1deaff Mon Sep 17 00:00:00 2001 From: behnam <behnamrahimpour74@gmail.com> Date: Fri, 15 Nov 2024 20:25:42 +0300 Subject: [PATCH 35/37] Fix i18n issue for html --- src/app/[lang]/layout.tsx | 27 +++++++++++++++++++++++---- src/app/layout.tsx | 24 ++---------------------- src/bootstrap/i18n/i18n.ts | 4 +++- 3 files changed, 28 insertions(+), 27 deletions(-) diff --git a/src/app/[lang]/layout.tsx b/src/app/[lang]/layout.tsx index 4fbaf40..b142672 100644 --- a/src/app/[lang]/layout.tsx +++ b/src/app/[lang]/layout.tsx @@ -1,15 +1,34 @@ import { initI18next } from "@/bootstrap/i18n/i18n"; import TranslationsProvider from "@/bootstrap/i18n/i18n-provider"; +import localFont from "next/font/local"; import { PropsWithChildren } from "react"; +const geistSans = localFont({ + src: "./../fonts/GeistVF.woff", + variable: "--font-geist-sans", + weight: "100 900", +}); +const geistMono = localFont({ + src: "./../fonts/GeistMonoVF.woff", + variable: "--font-geist-mono", + weight: "100 900", +}); + export default async function layout( props: PropsWithChildren & { params: Promise<{ lang: string }> }, ) { - const { lang } = await props.params; + const { params, children } = props; + const { lang } = await params; const { resources } = await initI18next({ lng: lang }); return ( - <TranslationsProvider lng={lang} resources={resources}> - {props.children} - </TranslationsProvider> + <html lang={lang}> + <body + className={`${geistSans.variable} ${geistMono.variable} antialiased`} + > + <TranslationsProvider lng={lang} resources={resources}> + {children} + </TranslationsProvider> + </body> + </html> ); } diff --git a/src/app/layout.tsx b/src/app/layout.tsx index a36cde0..c277050 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -1,35 +1,15 @@ import type { Metadata } from "next"; -import localFont from "next/font/local"; import "./globals.css"; -const geistSans = localFont({ - src: "./fonts/GeistVF.woff", - variable: "--font-geist-sans", - weight: "100 900", -}); -const geistMono = localFont({ - src: "./fonts/GeistMonoVF.woff", - variable: "--font-geist-mono", - weight: "100 900", -}); - export const metadata: Metadata = { title: "Create Next App", description: "Generated by create next app", }; -export default function RootLayout({ +export default async function RootLayout({ children, }: Readonly<{ children: React.ReactNode; }>) { - return ( - <html lang="en"> - <body - className={`${geistSans.variable} ${geistMono.variable} antialiased`} - > - {children} - </body> - </html> - ); + return children; } diff --git a/src/bootstrap/i18n/i18n.ts b/src/bootstrap/i18n/i18n.ts index 8b348f2..c95d601 100644 --- a/src/bootstrap/i18n/i18n.ts +++ b/src/bootstrap/i18n/i18n.ts @@ -3,6 +3,8 @@ import { createInstance, i18n, Resource } from "i18next"; import resourcesToBackend from "i18next-resources-to-backend"; import { initReactI18next } from "react-i18next/initReactI18next"; +const initI18nextInstance = createInstance(); + export const initI18next = async (params: { lng: string; i18n?: i18n; @@ -10,7 +12,7 @@ export const initI18next = async (params: { ns?: string; }) => { const { lng, i18n, ns, resources } = params; - const i18nInstance = i18n || createInstance(); + const i18nInstance = i18n || initI18nextInstance; await i18nInstance .use(initReactI18next) .use( -- 2.39.5 From 2365a07d76aa28a7913324b82aa96aa755c795c1 Mon Sep 17 00:00:00 2001 From: behnam <behnamrahimpour74@gmail.com> Date: Fri, 15 Nov 2024 20:46:17 +0300 Subject: [PATCH 36/37] Add docker file and docker compose file --- Dockerfile | 70 + docker-compose.yml | 27 + next.config.ts | 1 + package-lock.json | 5724 ----------------- .../common/failures/failure-helpers.ts | 30 +- 5 files changed, 115 insertions(+), 5737 deletions(-) create mode 100644 Dockerfile create mode 100644 docker-compose.yml delete mode 100644 package-lock.json diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..36923cd --- /dev/null +++ b/Dockerfile @@ -0,0 +1,70 @@ +# syntax=docker.io/docker/dockerfile:1 + +FROM node:18-alpine AS base + +# Install dependencies only when needed +FROM base AS deps +# Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed. +RUN apk add --no-cache libc6-compat +WORKDIR /app + +# Install dependencies based on the preferred package manager +COPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml* .npmrc* ./ +RUN \ + if [ -f yarn.lock ]; then yarn --frozen-lockfile; \ + elif [ -f package-lock.json ]; then npm ci; \ + elif [ -f pnpm-lock.yaml ]; then corepack enable pnpm && pnpm i --frozen-lockfile; \ + else echo "Lockfile not found." && exit 1; \ + fi + + +# Rebuild the source code only when needed +FROM base AS builder +WORKDIR /app +COPY --from=deps /app/node_modules ./node_modules +COPY . . + +# Next.js collects completely anonymous telemetry data about general usage. +# Learn more here: https://nextjs.org/telemetry +# Uncomment the following line in case you want to disable telemetry during the build. +# ENV NEXT_TELEMETRY_DISABLED=1 + +RUN \ + if [ -f yarn.lock ]; then yarn run build; \ + elif [ -f package-lock.json ]; then npm run build; \ + elif [ -f pnpm-lock.yaml ]; then corepack enable pnpm && pnpm run build; \ + else echo "Lockfile not found." && exit 1; \ + fi + +# Production image, copy all the files and run next +FROM base AS runner +WORKDIR /app + +ENV NODE_ENV=production +# Uncomment the following line in case you want to disable telemetry during runtime. +# ENV NEXT_TELEMETRY_DISABLED=1 + +RUN addgroup --system --gid 1001 nodejs +RUN adduser --system --uid 1001 nextjs + +COPY --from=builder /app/public ./public + +# Set the correct permission for prerender cache +RUN mkdir .next +RUN chown nextjs:nodejs .next + +# Automatically leverage output traces to reduce image size +# https://nextjs.org/docs/advanced-features/output-file-tracing +COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./ +COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static + +USER nextjs + +EXPOSE 3000 + +ENV PORT=3000 + +# server.js is created by next build from the standalone output +# https://nextjs.org/docs/pages/api-reference/next-config-js/output +ENV HOSTNAME="0.0.0.0" +CMD ["node", "server.js"] \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..9e2981f --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,27 @@ +services: + db: + image: postgres + restart: always + volumes: + - postgres_data:/var/lib/postgresql/data + ports: + - 5432:5432 + environment: + POSTGRES_PASSWORD: example + POSTGRES_USER: admin + POSTGRES_DB: nextbp + + + app: + build: . + ports: + - 3000:3000 + environment: + POSTGRES_HOST: db + POSTGRES_PORT: 5432 + POSTGRES_USER: admin + POSTGRES_PASS: example + POSTGRES_DB: nextbp +volumes: + postgres_data: + \ No newline at end of file diff --git a/next.config.ts b/next.config.ts index e9ffa30..ed23578 100644 --- a/next.config.ts +++ b/next.config.ts @@ -2,6 +2,7 @@ import type { NextConfig } from "next"; const nextConfig: NextConfig = { /* config options here */ + output: "standalone", }; export default nextConfig; diff --git a/package-lock.json b/package-lock.json deleted file mode 100644 index d6c0f4e..0000000 --- a/package-lock.json +++ /dev/null @@ -1,5724 +0,0 @@ -{ - "name": "nextjs-boilerplate", - "version": "0.1.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "nextjs-boilerplate", - "version": "0.1.0", - "dependencies": { - "next": "15.0.1", - "react": "19.0.0-rc-69d4b800-20241021", - "react-dom": "19.0.0-rc-69d4b800-20241021" - }, - "devDependencies": { - "@types/node": "^20", - "@types/react": "^18", - "@types/react-dom": "^18", - "eslint": "^8", - "eslint-config-next": "15.0.1", - "postcss": "^8", - "tailwindcss": "^3.4.1", - "typescript": "^5" - } - }, - "node_modules/@alloc/quick-lru": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", - "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@emnapi/runtime": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.3.1.tgz", - "integrity": "sha512-kEBmG8KyqtxJZv+ygbEim+KCGtIq1fC22Ms3S4ziXmYKm8uyoLX0MHONVKwp+9opg390VaKRNt4a7A9NwmpNhw==", - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", - "dev": true, - "license": "MIT", - "dependencies": { - "eslint-visitor-keys": "^3.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" - } - }, - "node_modules/@eslint-community/regexpp": { - "version": "4.11.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.1.tgz", - "integrity": "sha512-m4DVN9ZqskZoLU5GlWZadwDnYo3vAEydiUayB9widCl9ffWx2IvPnp6n3on5rJmziJSw9Bv+Z3ChDVdMwXCY8Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" - } - }, - "node_modules/@eslint/eslintrc": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", - "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@eslint/js": { - "version": "8.57.1", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", - "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.13.0", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", - "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", - "deprecated": "Use @eslint/config-array instead", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@humanwhocodes/object-schema": "^2.0.3", - "debug": "^4.3.1", - "minimatch": "^3.0.5" - }, - "engines": { - "node": ">=10.10.0" - } - }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=12.22" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, - "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", - "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", - "deprecated": "Use @eslint/object-schema instead", - "dev": true, - "license": "BSD-3-Clause" - }, - "node_modules/@img/sharp-darwin-arm64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.33.5.tgz", - "integrity": "sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ==", - "cpu": [ - "arm64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-darwin-arm64": "1.0.4" - } - }, - "node_modules/@img/sharp-darwin-x64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.33.5.tgz", - "integrity": "sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q==", - "cpu": [ - "x64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-darwin-x64": "1.0.4" - } - }, - "node_modules/@img/sharp-libvips-darwin-arm64": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.0.4.tgz", - "integrity": "sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg==", - "cpu": [ - "arm64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "darwin" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-darwin-x64": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.0.4.tgz", - "integrity": "sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ==", - "cpu": [ - "x64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "darwin" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linux-arm": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.0.5.tgz", - "integrity": "sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g==", - "cpu": [ - "arm" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linux-arm64": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.0.4.tgz", - "integrity": "sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA==", - "cpu": [ - "arm64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linux-s390x": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.0.4.tgz", - "integrity": "sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA==", - "cpu": [ - "s390x" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linux-x64": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.0.4.tgz", - "integrity": "sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw==", - "cpu": [ - "x64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linuxmusl-arm64": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.0.4.tgz", - "integrity": "sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA==", - "cpu": [ - "arm64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linuxmusl-x64": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.0.4.tgz", - "integrity": "sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw==", - "cpu": [ - "x64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-linux-arm": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.33.5.tgz", - "integrity": "sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ==", - "cpu": [ - "arm" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-arm": "1.0.5" - } - }, - "node_modules/@img/sharp-linux-arm64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.33.5.tgz", - "integrity": "sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA==", - "cpu": [ - "arm64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-arm64": "1.0.4" - } - }, - "node_modules/@img/sharp-linux-s390x": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.33.5.tgz", - "integrity": "sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q==", - "cpu": [ - "s390x" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-s390x": "1.0.4" - } - }, - "node_modules/@img/sharp-linux-x64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.33.5.tgz", - "integrity": "sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA==", - "cpu": [ - "x64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-x64": "1.0.4" - } - }, - "node_modules/@img/sharp-linuxmusl-arm64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.33.5.tgz", - "integrity": "sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g==", - "cpu": [ - "arm64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linuxmusl-arm64": "1.0.4" - } - }, - "node_modules/@img/sharp-linuxmusl-x64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.33.5.tgz", - "integrity": "sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw==", - "cpu": [ - "x64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linuxmusl-x64": "1.0.4" - } - }, - "node_modules/@img/sharp-wasm32": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.33.5.tgz", - "integrity": "sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg==", - "cpu": [ - "wasm32" - ], - "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", - "optional": true, - "dependencies": { - "@emnapi/runtime": "^1.2.0" - }, - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-win32-ia32": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.33.5.tgz", - "integrity": "sha512-T36PblLaTwuVJ/zw/LaH0PdZkRz5rd3SmMHX8GSmR7vtNSP5Z6bQkExdSK7xGWyxLw4sUknBuugTelgw2faBbQ==", - "cpu": [ - "ia32" - ], - "license": "Apache-2.0 AND LGPL-3.0-or-later", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-win32-x64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.33.5.tgz", - "integrity": "sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg==", - "cpu": [ - "x64" - ], - "license": "Apache-2.0 AND LGPL-3.0-or-later", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@isaacs/cliui": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", - "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", - "dev": true, - "license": "ISC", - "dependencies": { - "string-width": "^5.1.2", - "string-width-cjs": "npm:string-width@^4.2.0", - "strip-ansi": "^7.0.1", - "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", - "wrap-ansi": "^8.1.0", - "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@isaacs/cliui/node_modules/ansi-regex": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", - "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", - "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/set-array": "^1.2.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/set-array": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", - "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", - "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.25", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "node_modules/@next/env": { - "version": "15.0.1", - "resolved": "https://registry.npmjs.org/@next/env/-/env-15.0.1.tgz", - "integrity": "sha512-lc4HeDUKO9gxxlM5G2knTRifqhsY6yYpwuHspBZdboZe0Gp+rZHBNNSIjmQKDJIdRXiXGyVnSD6gafrbQPvILQ==", - "license": "MIT" - }, - "node_modules/@next/eslint-plugin-next": { - "version": "15.0.1", - "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-15.0.1.tgz", - "integrity": "sha512-bKWsMaGPbiFAaGqrDJvbE8b4Z0uKicGVcgOI77YM2ui3UfjHMr4emFPrZTLeZVchi7fT1mooG2LxREfUUClIKw==", - "dev": true, - "license": "MIT", - "dependencies": { - "fast-glob": "3.3.1" - } - }, - "node_modules/@next/swc-darwin-arm64": { - "version": "15.0.1", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-15.0.1.tgz", - "integrity": "sha512-C9k/Xv4sxkQRTA37Z6MzNq3Yb1BJMmSqjmwowoWEpbXTkAdfOwnoKOpAb71ItSzoA26yUTIo6ZhN8rKGu4ExQw==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-darwin-x64": { - "version": "15.0.1", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-15.0.1.tgz", - "integrity": "sha512-uHl13HXOuq1G7ovWFxCACDJHTSDVbn/sbLv8V1p+7KIvTrYQ5HNoSmKBdYeEKRRCbEmd+OohOgg9YOp8Ux3MBg==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-linux-arm64-gnu": { - "version": "15.0.1", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-15.0.1.tgz", - "integrity": "sha512-LvyhvxHOihFTEIbb35KxOc3q8w8G4xAAAH/AQnsYDEnOvwawjL2eawsB59AX02ki6LJdgDaHoTEnC54Gw+82xw==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-linux-arm64-musl": { - "version": "15.0.1", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-15.0.1.tgz", - "integrity": "sha512-vFmCGUFNyk/A5/BYcQNhAQqPIw01RJaK6dRO+ZEhz0DncoW+hJW1kZ8aH2UvTX27zPq3m85zN5waMSbZEmANcQ==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-linux-x64-gnu": { - "version": "15.0.1", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-15.0.1.tgz", - "integrity": "sha512-5by7IYq0NCF8rouz6Qg9T97jYU68kaClHPfGpQG2lCZpSYHtSPQF1kjnqBTd34RIqPKMbCa4DqCufirgr8HM5w==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-linux-x64-musl": { - "version": "15.0.1", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-15.0.1.tgz", - "integrity": "sha512-lmYr6H3JyDNBJLzklGXLfbehU3ay78a+b6UmBGlHls4xhDXBNZfgb0aI67sflrX+cGBnv1LgmWzFlYrAYxS1Qw==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-win32-arm64-msvc": { - "version": "15.0.1", - "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-15.0.1.tgz", - "integrity": "sha512-DS8wQtl6diAj0eZTdH0sefykm4iXMbHT4MOvLwqZiIkeezKpkgPFcEdFlz3vKvXa2R/2UEgMh48z1nEpNhjeOQ==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-win32-x64-msvc": { - "version": "15.0.1", - "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.0.1.tgz", - "integrity": "sha512-4Ho2ggvDdMKlZ/0e9HNdZ9ngeaBwtc+2VS5oCeqrbXqOgutX6I4U2X/42VBw0o+M5evn4/7v3zKgGHo+9v/VjA==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nolyfill/is-core-module": { - "version": "1.0.39", - "resolved": "https://registry.npmjs.org/@nolyfill/is-core-module/-/is-core-module-1.0.39.tgz", - "integrity": "sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12.4.0" - } - }, - "node_modules/@pkgjs/parseargs": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", - "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=14" - } - }, - "node_modules/@rtsao/scc": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", - "integrity": "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==", - "dev": true, - "license": "MIT" - }, - "node_modules/@rushstack/eslint-patch": { - "version": "1.10.4", - "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.10.4.tgz", - "integrity": "sha512-WJgX9nzTqknM393q1QJDJmoW28kUfEnybeTfVNcNAPnIx210RXm2DiXiHzfNPJNIUUb1tJnz/l4QGtJ30PgWmA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@swc/counter": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", - "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==", - "license": "Apache-2.0" - }, - "node_modules/@swc/helpers": { - "version": "0.5.13", - "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.13.tgz", - "integrity": "sha512-UoKGxQ3r5kYI9dALKJapMmuK+1zWM/H17Z1+iwnNmzcJRnfFuevZs375TA5rW31pu4BS4NoSy1fRsexDXfWn5w==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@types/json5": { - "version": "0.0.29", - "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", - "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/node": { - "version": "20.17.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.17.0.tgz", - "integrity": "sha512-a7zRo0f0eLo9K5X9Wp5cAqTUNGzuFLDG2R7C4HY2BhcMAsxgSPuRvAC1ZB6QkuUQXf0YZAgfOX2ZyrBa2n4nHQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "undici-types": "~6.19.2" - } - }, - "node_modules/@types/prop-types": { - "version": "15.7.13", - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.13.tgz", - "integrity": "sha512-hCZTSvwbzWGvhqxp/RqVqwU999pBf2vp7hzIjiYOsl8wqOmUxkQ6ddw1cV3l8811+kdUFus/q4d1Y3E3SyEifA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/react": { - "version": "18.3.12", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.12.tgz", - "integrity": "sha512-D2wOSq/d6Agt28q7rSI3jhU7G6aiuzljDGZ2hTZHIkrTLUI+AF3WMeKkEZ9nN2fkBAlcktT6vcZjDFiIhMYEQw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/prop-types": "*", - "csstype": "^3.0.2" - } - }, - "node_modules/@types/react-dom": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.1.tgz", - "integrity": "sha512-qW1Mfv8taImTthu4KoXgDfLuk4bydU6Q/TkADnDWWHwi4NX4BR+LWfTp2sVmTqRrsHvyDDTelgelxJ+SsejKKQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/react": "*" - } - }, - "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.11.0.tgz", - "integrity": "sha512-KhGn2LjW1PJT2A/GfDpiyOfS4a8xHQv2myUagTM5+zsormOmBlYsnQ6pobJ8XxJmh6hnHwa2Mbe3fPrDJoDhbA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.11.0", - "@typescript-eslint/type-utils": "8.11.0", - "@typescript-eslint/utils": "8.11.0", - "@typescript-eslint/visitor-keys": "8.11.0", - "graphemer": "^1.4.0", - "ignore": "^5.3.1", - "natural-compare": "^1.4.0", - "ts-api-utils": "^1.3.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", - "eslint": "^8.57.0 || ^9.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/parser": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.11.0.tgz", - "integrity": "sha512-lmt73NeHdy1Q/2ul295Qy3uninSqi6wQI18XwSpm8w0ZbQXUpjCAWP1Vlv/obudoBiIjJVjlztjQ+d/Md98Yxg==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "@typescript-eslint/scope-manager": "8.11.0", - "@typescript-eslint/types": "8.11.0", - "@typescript-eslint/typescript-estree": "8.11.0", - "@typescript-eslint/visitor-keys": "8.11.0", - "debug": "^4.3.4" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.11.0.tgz", - "integrity": "sha512-Uholz7tWhXmA4r6epo+vaeV7yjdKy5QFCERMjs1kMVsLRKIrSdM6o21W2He9ftp5PP6aWOVpD5zvrvuHZC0bMQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "8.11.0", - "@typescript-eslint/visitor-keys": "8.11.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/type-utils": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.11.0.tgz", - "integrity": "sha512-ItiMfJS6pQU0NIKAaybBKkuVzo6IdnAhPFZA/2Mba/uBjuPQPet/8+zh5GtLHwmuFRShZx+8lhIs7/QeDHflOg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/typescript-estree": "8.11.0", - "@typescript-eslint/utils": "8.11.0", - "debug": "^4.3.4", - "ts-api-utils": "^1.3.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/types": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.11.0.tgz", - "integrity": "sha512-tn6sNMHf6EBAYMvmPUaKaVeYvhUsrE6x+bXQTxjQRp360h1giATU0WvgeEys1spbvb5R+VpNOZ+XJmjD8wOUHw==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.11.0.tgz", - "integrity": "sha512-yHC3s1z1RCHoCz5t06gf7jH24rr3vns08XXhfEqzYpd6Hll3z/3g23JRi0jM8A47UFKNc3u/y5KIMx8Ynbjohg==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "@typescript-eslint/types": "8.11.0", - "@typescript-eslint/visitor-keys": "8.11.0", - "debug": "^4.3.4", - "fast-glob": "^3.3.2", - "is-glob": "^4.0.3", - "minimatch": "^9.0.4", - "semver": "^7.6.0", - "ts-api-utils": "^1.3.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/fast-glob": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", - "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@typescript-eslint/utils": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.11.0.tgz", - "integrity": "sha512-CYiX6WZcbXNJV7UNB4PLDIBtSdRmRI/nb0FMyqHPTQD1rMjA0foPLaPUV39C/MxkTd/QKSeX+Gb34PPsDVC35g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.11.0", - "@typescript-eslint/types": "8.11.0", - "@typescript-eslint/typescript-estree": "8.11.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0" - } - }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.11.0.tgz", - "integrity": "sha512-EaewX6lxSjRJnc+99+dqzTeoDZUfyrA52d2/HRrkI830kgovWsmIiTfmr0NZorzqic7ga+1bS60lRBUgR3n/Bw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "8.11.0", - "eslint-visitor-keys": "^3.4.3" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@ungap/structured-clone": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", - "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/acorn": { - "version": "8.13.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.13.0.tgz", - "integrity": "sha512-8zSiw54Oxrdym50NlZ9sUusyO1Z1ZchgRLWRaK6c86XJFClyCgFKetdowBg5bKxyp/u+CDBJG4Mpp0m3HLZl9w==", - "dev": true, - "license": "MIT", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/any-promise": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", - "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", - "dev": true, - "license": "MIT" - }, - "node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dev": true, - "license": "ISC", - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/arg": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", - "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", - "dev": true, - "license": "MIT" - }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true, - "license": "Python-2.0" - }, - "node_modules/aria-query": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz", - "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/array-buffer-byte-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", - "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.5", - "is-array-buffer": "^3.0.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array-includes": { - "version": "3.1.8", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", - "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-object-atoms": "^1.0.0", - "get-intrinsic": "^1.2.4", - "is-string": "^1.0.7" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.findlast": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", - "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "es-shim-unscopables": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.findlastindex": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz", - "integrity": "sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "es-shim-unscopables": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.flat": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", - "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.flatmap": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", - "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.tosorted": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz", - "integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.3", - "es-errors": "^1.3.0", - "es-shim-unscopables": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/arraybuffer.prototype.slice": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", - "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", - "dev": true, - "license": "MIT", - "dependencies": { - "array-buffer-byte-length": "^1.0.1", - "call-bind": "^1.0.5", - "define-properties": "^1.2.1", - "es-abstract": "^1.22.3", - "es-errors": "^1.2.1", - "get-intrinsic": "^1.2.3", - "is-array-buffer": "^3.0.4", - "is-shared-array-buffer": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/ast-types-flow": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz", - "integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/available-typed-arrays": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", - "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "possible-typed-array-names": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/axe-core": { - "version": "4.10.2", - "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.10.2.tgz", - "integrity": "sha512-RE3mdQ7P3FRSe7eqCWoeQ/Z9QXrtniSjp1wUjt5nRC3WIpz5rSCve6o3fsZ2aCpJtrZjSZgjwXAoTO5k4tEI0w==", - "dev": true, - "license": "MPL-2.0", - "engines": { - "node": ">=4" - } - }, - "node_modules/axobject-query": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz", - "integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true, - "license": "MIT" - }, - "node_modules/binary-extensions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", - "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "dev": true, - "license": "MIT", - "dependencies": { - "fill-range": "^7.1.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/busboy": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", - "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", - "dependencies": { - "streamsearch": "^1.1.0" - }, - "engines": { - "node": ">=10.16.0" - } - }, - "node_modules/call-bind": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", - "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", - "dev": true, - "license": "MIT", - "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "set-function-length": "^1.2.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/camelcase-css": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", - "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 6" - } - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001669", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001669.tgz", - "integrity": "sha512-DlWzFDJqstqtIVx1zeSpIMLjunf5SmwOw0N2Ck/QSQdS8PLS4+9HrLaYei4w8BIAL7IB/UEDu889d8vhCTPA0w==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "CC-BY-4.0" - }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/chokidar": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", - "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", - "dev": true, - "license": "MIT", - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/chokidar/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/client-only": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", - "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==", - "license": "MIT" - }, - "node_modules/color": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", - "integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==", - "license": "MIT", - "optional": true, - "dependencies": { - "color-convert": "^2.0.1", - "color-string": "^1.9.0" - }, - "engines": { - "node": ">=12.5.0" - } - }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "devOptional": true, - "license": "MIT" - }, - "node_modules/color-string": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", - "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", - "license": "MIT", - "optional": true, - "dependencies": { - "color-name": "^1.0.0", - "simple-swizzle": "^0.2.2" - } - }, - "node_modules/commander": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", - "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 6" - } - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true, - "license": "MIT" - }, - "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "license": "MIT", - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/cssesc": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", - "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", - "dev": true, - "license": "MIT", - "bin": { - "cssesc": "bin/cssesc" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/csstype": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", - "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", - "dev": true, - "license": "MIT" - }, - "node_modules/damerau-levenshtein": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", - "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==", - "dev": true, - "license": "BSD-2-Clause" - }, - "node_modules/data-view-buffer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", - "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.6", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/data-view-byte-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz", - "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/data-view-byte-offset": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz", - "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.6", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/debug": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/define-data-property": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", - "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", - "dev": true, - "license": "MIT", - "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "gopd": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/define-properties": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", - "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", - "dev": true, - "license": "MIT", - "dependencies": { - "define-data-property": "^1.0.1", - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/detect-libc": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz", - "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==", - "license": "Apache-2.0", - "optional": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/didyoumean": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", - "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", - "dev": true, - "license": "Apache-2.0" - }, - "node_modules/dlv": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", - "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", - "dev": true, - "license": "MIT" - }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/eastasianwidth": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "dev": true, - "license": "MIT" - }, - "node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true, - "license": "MIT" - }, - "node_modules/enhanced-resolve": { - "version": "5.17.1", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz", - "integrity": "sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==", - "dev": true, - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/es-abstract": { - "version": "1.23.3", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz", - "integrity": "sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==", - "dev": true, - "license": "MIT", - "dependencies": { - "array-buffer-byte-length": "^1.0.1", - "arraybuffer.prototype.slice": "^1.0.3", - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.7", - "data-view-buffer": "^1.0.1", - "data-view-byte-length": "^1.0.1", - "data-view-byte-offset": "^1.0.0", - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "es-set-tostringtag": "^2.0.3", - "es-to-primitive": "^1.2.1", - "function.prototype.name": "^1.1.6", - "get-intrinsic": "^1.2.4", - "get-symbol-description": "^1.0.2", - "globalthis": "^1.0.3", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.2", - "has-proto": "^1.0.3", - "has-symbols": "^1.0.3", - "hasown": "^2.0.2", - "internal-slot": "^1.0.7", - "is-array-buffer": "^3.0.4", - "is-callable": "^1.2.7", - "is-data-view": "^1.0.1", - "is-negative-zero": "^2.0.3", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.3", - "is-string": "^1.0.7", - "is-typed-array": "^1.1.13", - "is-weakref": "^1.0.2", - "object-inspect": "^1.13.1", - "object-keys": "^1.1.1", - "object.assign": "^4.1.5", - "regexp.prototype.flags": "^1.5.2", - "safe-array-concat": "^1.1.2", - "safe-regex-test": "^1.0.3", - "string.prototype.trim": "^1.2.9", - "string.prototype.trimend": "^1.0.8", - "string.prototype.trimstart": "^1.0.8", - "typed-array-buffer": "^1.0.2", - "typed-array-byte-length": "^1.0.1", - "typed-array-byte-offset": "^1.0.2", - "typed-array-length": "^1.0.6", - "unbox-primitive": "^1.0.2", - "which-typed-array": "^1.1.15" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es-define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", - "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "get-intrinsic": "^1.2.4" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-errors": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-iterator-helpers": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.1.0.tgz", - "integrity": "sha512-/SurEfycdyssORP/E+bj4sEu1CWw4EmLDsHynHwSXQ7utgbrMRWW195pTrCjFgFCddf/UkYm3oqKPRq5i8bJbw==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.3", - "es-errors": "^1.3.0", - "es-set-tostringtag": "^2.0.3", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "globalthis": "^1.0.4", - "has-property-descriptors": "^1.0.2", - "has-proto": "^1.0.3", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.7", - "iterator.prototype": "^1.1.3", - "safe-array-concat": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-object-atoms": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", - "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", - "dev": true, - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-set-tostringtag": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", - "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "get-intrinsic": "^1.2.4", - "has-tostringtag": "^1.0.2", - "hasown": "^2.0.1" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-shim-unscopables": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz", - "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==", - "dev": true, - "license": "MIT", - "dependencies": { - "hasown": "^2.0.0" - } - }, - "node_modules/es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint": { - "version": "8.57.1", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", - "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", - "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", - "dev": true, - "license": "MIT", - "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.57.1", - "@humanwhocodes/config-array": "^0.13.0", - "@humanwhocodes/module-importer": "^1.0.1", - "@nodelib/fs.walk": "^1.2.8", - "@ungap/structured-clone": "^1.2.0", - "ajv": "^6.12.4", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "doctrine": "^3.0.0", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.2", - "eslint-visitor-keys": "^3.4.3", - "espree": "^9.6.1", - "esquery": "^1.4.2", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "graphemer": "^1.4.0", - "ignore": "^5.2.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.3", - "strip-ansi": "^6.0.1", - "text-table": "^0.2.0" - }, - "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-config-next": { - "version": "15.0.1", - "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-15.0.1.tgz", - "integrity": "sha512-3cYCrgbH6GS/ufApza7XCKz92vtq4dAdYhx++rMFNlH2cAV+/GsAKkrr4+bohYOACmzG2nAOR+uWprKC1Uld6A==", - "dev": true, - "license": "MIT", - "dependencies": { - "@next/eslint-plugin-next": "15.0.1", - "@rushstack/eslint-patch": "^1.10.3", - "@typescript-eslint/eslint-plugin": "^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0", - "@typescript-eslint/parser": "^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0", - "eslint-import-resolver-node": "^0.3.6", - "eslint-import-resolver-typescript": "^3.5.2", - "eslint-plugin-import": "^2.31.0", - "eslint-plugin-jsx-a11y": "^6.10.0", - "eslint-plugin-react": "^7.35.0", - "eslint-plugin-react-hooks": "^5.0.0" - }, - "peerDependencies": { - "eslint": "^7.23.0 || ^8.0.0 || ^9.0.0", - "typescript": ">=3.3.1" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/eslint-import-resolver-node": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", - "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^3.2.7", - "is-core-module": "^2.13.0", - "resolve": "^1.22.4" - } - }, - "node_modules/eslint-import-resolver-node/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-import-resolver-typescript": { - "version": "3.6.3", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.6.3.tgz", - "integrity": "sha512-ud9aw4szY9cCT1EWWdGv1L1XR6hh2PaRWif0j2QjQ0pgTY/69iw+W0Z4qZv5wHahOl8isEr+k/JnyAqNQkLkIA==", - "dev": true, - "license": "ISC", - "dependencies": { - "@nolyfill/is-core-module": "1.0.39", - "debug": "^4.3.5", - "enhanced-resolve": "^5.15.0", - "eslint-module-utils": "^2.8.1", - "fast-glob": "^3.3.2", - "get-tsconfig": "^4.7.5", - "is-bun-module": "^1.0.2", - "is-glob": "^4.0.3" - }, - "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/unts/projects/eslint-import-resolver-ts" - }, - "peerDependencies": { - "eslint": "*", - "eslint-plugin-import": "*", - "eslint-plugin-import-x": "*" - }, - "peerDependenciesMeta": { - "eslint-plugin-import": { - "optional": true - }, - "eslint-plugin-import-x": { - "optional": true - } - } - }, - "node_modules/eslint-import-resolver-typescript/node_modules/fast-glob": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", - "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/eslint-import-resolver-typescript/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/eslint-module-utils": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.0.tgz", - "integrity": "sha512-wALZ0HFoytlyh/1+4wuZ9FJCD/leWHQzzrxJ8+rebyReSLk7LApMyd3WJaLVoN+D5+WIdJyDK1c6JnE65V4Zyg==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^3.2.7" - }, - "engines": { - "node": ">=4" - }, - "peerDependenciesMeta": { - "eslint": { - "optional": true - } - } - }, - "node_modules/eslint-module-utils/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-plugin-import": { - "version": "2.31.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.31.0.tgz", - "integrity": "sha512-ixmkI62Rbc2/w8Vfxyh1jQRTdRTF52VxwRVHl/ykPAmqG+Nb7/kNn+byLP0LxPgI7zWA16Jt82SybJInmMia3A==", - "dev": true, - "license": "MIT", - "dependencies": { - "@rtsao/scc": "^1.1.0", - "array-includes": "^3.1.8", - "array.prototype.findlastindex": "^1.2.5", - "array.prototype.flat": "^1.3.2", - "array.prototype.flatmap": "^1.3.2", - "debug": "^3.2.7", - "doctrine": "^2.1.0", - "eslint-import-resolver-node": "^0.3.9", - "eslint-module-utils": "^2.12.0", - "hasown": "^2.0.2", - "is-core-module": "^2.15.1", - "is-glob": "^4.0.3", - "minimatch": "^3.1.2", - "object.fromentries": "^2.0.8", - "object.groupby": "^1.0.3", - "object.values": "^1.2.0", - "semver": "^6.3.1", - "string.prototype.trimend": "^1.0.8", - "tsconfig-paths": "^3.15.0" - }, - "engines": { - "node": ">=4" - }, - "peerDependencies": { - "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9" - } - }, - "node_modules/eslint-plugin-import/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-plugin-import/node_modules/doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/eslint-plugin-import/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/eslint-plugin-jsx-a11y": { - "version": "6.10.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.10.1.tgz", - "integrity": "sha512-zHByM9WTUMnfsDTafGXRiqxp6lFtNoSOWBY6FonVRn3A+BUwN1L/tdBXT40BcBJi0cZjOGTXZ0eD/rTG9fEJ0g==", - "dev": true, - "license": "MIT", - "dependencies": { - "aria-query": "^5.3.2", - "array-includes": "^3.1.8", - "array.prototype.flatmap": "^1.3.2", - "ast-types-flow": "^0.0.8", - "axe-core": "^4.10.0", - "axobject-query": "^4.1.0", - "damerau-levenshtein": "^1.0.8", - "emoji-regex": "^9.2.2", - "es-iterator-helpers": "^1.1.0", - "hasown": "^2.0.2", - "jsx-ast-utils": "^3.3.5", - "language-tags": "^1.0.9", - "minimatch": "^3.1.2", - "object.fromentries": "^2.0.8", - "safe-regex-test": "^1.0.3", - "string.prototype.includes": "^2.0.1" - }, - "engines": { - "node": ">=4.0" - }, - "peerDependencies": { - "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9" - } - }, - "node_modules/eslint-plugin-react": { - "version": "7.37.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.2.tgz", - "integrity": "sha512-EsTAnj9fLVr/GZleBLFbj/sSuXeWmp1eXIN60ceYnZveqEaUCyW4X+Vh4WTdUhCkW4xutXYqTXCUSyqD4rB75w==", - "dev": true, - "license": "MIT", - "dependencies": { - "array-includes": "^3.1.8", - "array.prototype.findlast": "^1.2.5", - "array.prototype.flatmap": "^1.3.2", - "array.prototype.tosorted": "^1.1.4", - "doctrine": "^2.1.0", - "es-iterator-helpers": "^1.1.0", - "estraverse": "^5.3.0", - "hasown": "^2.0.2", - "jsx-ast-utils": "^2.4.1 || ^3.0.0", - "minimatch": "^3.1.2", - "object.entries": "^1.1.8", - "object.fromentries": "^2.0.8", - "object.values": "^1.2.0", - "prop-types": "^15.8.1", - "resolve": "^2.0.0-next.5", - "semver": "^6.3.1", - "string.prototype.matchall": "^4.0.11", - "string.prototype.repeat": "^1.0.0" - }, - "engines": { - "node": ">=4" - }, - "peerDependencies": { - "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" - } - }, - "node_modules/eslint-plugin-react-hooks": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.0.0.tgz", - "integrity": "sha512-hIOwI+5hYGpJEc4uPRmz2ulCjAGD/N13Lukkh8cLV0i2IRk/bdZDYjgLVHj+U9Z704kLIdIO6iueGvxNur0sgw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0" - } - }, - "node_modules/eslint-plugin-react/node_modules/doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/eslint-plugin-react/node_modules/resolve": { - "version": "2.0.0-next.5", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", - "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-core-module": "^2.13.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/eslint-plugin-react/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/eslint-scope": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", - "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/espree": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "acorn": "^8.9.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/esquery": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", - "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "estraverse": "^5.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "estraverse": "^5.2.0" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true, - "license": "MIT" - }, - "node_modules/fast-glob": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz", - "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/fast-glob/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true, - "license": "MIT" - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true, - "license": "MIT" - }, - "node_modules/fastq": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", - "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", - "dev": true, - "license": "ISC", - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dev": true, - "license": "MIT", - "dependencies": { - "flat-cache": "^3.0.4" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "dev": true, - "license": "MIT", - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "license": "MIT", - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/flat-cache": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", - "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", - "dev": true, - "license": "MIT", - "dependencies": { - "flatted": "^3.2.9", - "keyv": "^4.5.3", - "rimraf": "^3.0.2" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/flatted": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", - "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", - "dev": true, - "license": "ISC" - }, - "node_modules/for-each": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", - "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-callable": "^1.1.3" - } - }, - "node_modules/foreground-child": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", - "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", - "dev": true, - "license": "ISC", - "dependencies": { - "cross-spawn": "^7.0.0", - "signal-exit": "^4.0.1" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true, - "license": "ISC" - }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/function.prototype.name": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", - "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "functions-have-names": "^1.2.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/functions-have-names": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", - "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-intrinsic": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", - "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "hasown": "^2.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-symbol-description": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", - "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.5", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-tsconfig": { - "version": "4.8.1", - "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.8.1.tgz", - "integrity": "sha512-k9PN+cFBmaLWtVz29SkUoqU5O0slLuHJXt/2P+tMVFT+phsSGXGkp9t3rQIqdz0e+06EHNGs3oM6ZX1s2zHxRg==", - "dev": true, - "license": "MIT", - "dependencies": { - "resolve-pkg-maps": "^1.0.0" - }, - "funding": { - "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" - } - }, - "node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "dev": true, - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/globalthis": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", - "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "define-properties": "^1.2.1", - "gopd": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", - "dev": true, - "license": "MIT", - "dependencies": { - "get-intrinsic": "^1.1.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true, - "license": "MIT" - }, - "node_modules/has-bigints": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", - "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/has-property-descriptors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", - "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", - "dev": true, - "license": "MIT", - "dependencies": { - "es-define-property": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-proto": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", - "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-tostringtag": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", - "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-symbols": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/ignore": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", - "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, - "license": "MIT", - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", - "dev": true, - "license": "ISC", - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/internal-slot": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", - "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", - "dev": true, - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "hasown": "^2.0.0", - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/is-array-buffer": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", - "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-arrayish": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", - "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==", - "license": "MIT", - "optional": true - }, - "node_modules/is-async-function": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz", - "integrity": "sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-bigint": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", - "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-bigints": "^1.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "license": "MIT", - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-boolean-object": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", - "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-bun-module": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/is-bun-module/-/is-bun-module-1.2.1.tgz", - "integrity": "sha512-AmidtEM6D6NmUiLOvvU7+IePxjEjOzra2h0pSrsfSAcXwl/83zLLXDByafUJy9k/rKK0pvXMLdwKwGHlX2Ke6Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "semver": "^7.6.3" - } - }, - "node_modules/is-callable": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", - "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-core-module": { - "version": "2.15.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz", - "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-data-view": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz", - "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-typed-array": "^1.1.13" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-date-object": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", - "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-finalizationregistry": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz", - "integrity": "sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/is-generator-function": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", - "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-map": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", - "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-negative-zero": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", - "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-number-object": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", - "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/is-regex": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", - "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-set": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", - "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-shared-array-buffer": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", - "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-string": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", - "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-symbol": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", - "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-symbols": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-typed-array": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", - "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", - "dev": true, - "license": "MIT", - "dependencies": { - "which-typed-array": "^1.1.14" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-weakmap": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", - "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-weakref": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", - "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-weakset": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.3.tgz", - "integrity": "sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "get-intrinsic": "^1.2.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true, - "license": "MIT" - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true, - "license": "ISC" - }, - "node_modules/iterator.prototype": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.3.tgz", - "integrity": "sha512-FW5iMbeQ6rBGm/oKgzq2aW4KvAGpxPzYES8N4g4xNXUKpL1mclMvOe+76AcLDTvD+Ze+sOpVhgdAQEKF4L9iGQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "define-properties": "^1.2.1", - "get-intrinsic": "^1.2.1", - "has-symbols": "^1.0.3", - "reflect.getprototypeof": "^1.0.4", - "set-function-name": "^2.0.1" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/jackspeak": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", - "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", - "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "@isaacs/cliui": "^8.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - }, - "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" - } - }, - "node_modules/jiti": { - "version": "1.21.6", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.6.tgz", - "integrity": "sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==", - "dev": true, - "license": "MIT", - "bin": { - "jiti": "bin/jiti.js" - } - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "license": "MIT", - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/json-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true, - "license": "MIT" - }, - "node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true, - "license": "MIT" - }, - "node_modules/json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", - "dev": true, - "license": "MIT", - "dependencies": { - "minimist": "^1.2.0" - }, - "bin": { - "json5": "lib/cli.js" - } - }, - "node_modules/jsx-ast-utils": { - "version": "3.3.5", - "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", - "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "array-includes": "^3.1.6", - "array.prototype.flat": "^1.3.1", - "object.assign": "^4.1.4", - "object.values": "^1.1.6" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/keyv": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", - "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", - "dev": true, - "license": "MIT", - "dependencies": { - "json-buffer": "3.0.1" - } - }, - "node_modules/language-subtag-registry": { - "version": "0.3.23", - "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.23.tgz", - "integrity": "sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==", - "dev": true, - "license": "CC0-1.0" - }, - "node_modules/language-tags": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.9.tgz", - "integrity": "sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==", - "dev": true, - "license": "MIT", - "dependencies": { - "language-subtag-registry": "^0.3.20" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/lilconfig": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", - "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - } - }, - "node_modules/lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true, - "license": "MIT" - }, - "node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/loose-envify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "js-tokens": "^3.0.0 || ^4.0.0" - }, - "bin": { - "loose-envify": "cli.js" - } - }, - "node_modules/lru-cache": { - "version": "10.4.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", - "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, - "node_modules/micromatch": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", - "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", - "dev": true, - "license": "MIT", - "dependencies": { - "braces": "^3.0.3", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true, - "license": "MIT" - }, - "node_modules/mz": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", - "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "any-promise": "^1.0.0", - "object-assign": "^4.0.1", - "thenify-all": "^1.0.0" - } - }, - "node_modules/nanoid": { - "version": "3.3.7", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", - "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true, - "license": "MIT" - }, - "node_modules/next": { - "version": "15.0.1", - "resolved": "https://registry.npmjs.org/next/-/next-15.0.1.tgz", - "integrity": "sha512-PSkFkr/w7UnFWm+EP8y/QpHrJXMqpZzAXpergB/EqLPOh4SGPJXv1wj4mslr2hUZBAS9pX7/9YLIdxTv6fwytw==", - "license": "MIT", - "dependencies": { - "@next/env": "15.0.1", - "@swc/counter": "0.1.3", - "@swc/helpers": "0.5.13", - "busboy": "1.6.0", - "caniuse-lite": "^1.0.30001579", - "postcss": "8.4.31", - "styled-jsx": "5.1.6" - }, - "bin": { - "next": "dist/bin/next" - }, - "engines": { - "node": ">=18.18.0" - }, - "optionalDependencies": { - "@next/swc-darwin-arm64": "15.0.1", - "@next/swc-darwin-x64": "15.0.1", - "@next/swc-linux-arm64-gnu": "15.0.1", - "@next/swc-linux-arm64-musl": "15.0.1", - "@next/swc-linux-x64-gnu": "15.0.1", - "@next/swc-linux-x64-musl": "15.0.1", - "@next/swc-win32-arm64-msvc": "15.0.1", - "@next/swc-win32-x64-msvc": "15.0.1", - "sharp": "^0.33.5" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.1.0", - "@playwright/test": "^1.41.2", - "babel-plugin-react-compiler": "*", - "react": "^18.2.0 || 19.0.0-rc-69d4b800-20241021", - "react-dom": "^18.2.0 || 19.0.0-rc-69d4b800-20241021", - "sass": "^1.3.0" - }, - "peerDependenciesMeta": { - "@opentelemetry/api": { - "optional": true - }, - "@playwright/test": { - "optional": true - }, - "babel-plugin-react-compiler": { - "optional": true - }, - "sass": { - "optional": true - } - } - }, - "node_modules/next/node_modules/postcss": { - "version": "8.4.31", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", - "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "nanoid": "^3.3.6", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-hash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", - "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 6" - } - }, - "node_modules/object-inspect": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", - "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.assign": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", - "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.5", - "define-properties": "^1.2.1", - "has-symbols": "^1.0.3", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object.entries": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.8.tgz", - "integrity": "sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.fromentries": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", - "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object.groupby": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", - "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.values": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.0.tgz", - "integrity": "sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, - "license": "ISC", - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/optionator": { - "version": "0.9.4", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", - "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", - "dev": true, - "license": "MIT", - "dependencies": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.5" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/package-json-from-dist": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", - "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", - "dev": true, - "license": "BlueOak-1.0.0" - }, - "node_modules/parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "license": "MIT", - "dependencies": { - "callsites": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true, - "license": "MIT" - }, - "node_modules/path-scurry": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", - "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", - "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "lru-cache": "^10.2.0", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" - }, - "engines": { - "node": ">=16 || 14 >=14.18" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "license": "ISC" - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/pirates": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", - "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 6" - } - }, - "node_modules/possible-typed-array-names": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", - "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/postcss": { - "version": "8.4.47", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz", - "integrity": "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "nanoid": "^3.3.7", - "picocolors": "^1.1.0", - "source-map-js": "^1.2.1" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/postcss-import": { - "version": "15.1.0", - "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz", - "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", - "dev": true, - "license": "MIT", - "dependencies": { - "postcss-value-parser": "^4.0.0", - "read-cache": "^1.0.0", - "resolve": "^1.1.7" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "postcss": "^8.0.0" - } - }, - "node_modules/postcss-js": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz", - "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==", - "dev": true, - "license": "MIT", - "dependencies": { - "camelcase-css": "^2.0.1" - }, - "engines": { - "node": "^12 || ^14 || >= 16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - "peerDependencies": { - "postcss": "^8.4.21" - } - }, - "node_modules/postcss-load-config": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz", - "integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "lilconfig": "^3.0.0", - "yaml": "^2.3.4" - }, - "engines": { - "node": ">= 14" - }, - "peerDependencies": { - "postcss": ">=8.0.9", - "ts-node": ">=9.0.0" - }, - "peerDependenciesMeta": { - "postcss": { - "optional": true - }, - "ts-node": { - "optional": true - } - } - }, - "node_modules/postcss-load-config/node_modules/lilconfig": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.2.tgz", - "integrity": "sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/antonk52" - } - }, - "node_modules/postcss-nested": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz", - "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "postcss-selector-parser": "^6.1.1" - }, - "engines": { - "node": ">=12.0" - }, - "peerDependencies": { - "postcss": "^8.2.14" - } - }, - "node_modules/postcss-selector-parser": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", - "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", - "dev": true, - "license": "MIT", - "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/prop-types": { - "version": "15.8.1", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", - "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", - "dev": true, - "license": "MIT", - "dependencies": { - "loose-envify": "^1.4.0", - "object-assign": "^4.1.1", - "react-is": "^16.13.1" - } - }, - "node_modules/punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/react": { - "version": "19.0.0-rc-69d4b800-20241021", - "resolved": "https://registry.npmjs.org/react/-/react-19.0.0-rc-69d4b800-20241021.tgz", - "integrity": "sha512-dXki4tN+rP+4xhsm65q/QI/19VCZdu5vPcy4h6zaJt20XP8/1r/LCwrLFYuj8hElbNz5AmxW6JtRa7ej0BzZdg==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/react-dom": { - "version": "19.0.0-rc-69d4b800-20241021", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.0.0-rc-69d4b800-20241021.tgz", - "integrity": "sha512-ZXBsP/kTDLI9QopUaUgYJhmmAhO8aKz7DCv2Ui2rA9boCfJ/dRRh6BlVidsyb2dPzG01rItdRFQqwbP+x9s5Rg==", - "license": "MIT", - "dependencies": { - "scheduler": "0.25.0-rc-69d4b800-20241021" - }, - "peerDependencies": { - "react": "19.0.0-rc-69d4b800-20241021" - } - }, - "node_modules/react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/read-cache": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", - "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", - "dev": true, - "license": "MIT", - "dependencies": { - "pify": "^2.3.0" - } - }, - "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "license": "MIT", - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/reflect.getprototypeof": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.6.tgz", - "integrity": "sha512-fmfw4XgoDke3kdI6h4xcUz1dG8uaiv5q9gcEwLS4Pnth2kxT+GZ7YehS1JTMGBQmtV7Y4GFGbs2re2NqhdozUg==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.1", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4", - "globalthis": "^1.0.3", - "which-builtin-type": "^1.1.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/regexp.prototype.flags": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.3.tgz", - "integrity": "sha512-vqlC04+RQoFalODCbCumG2xIOvapzVMHwsyIGM/SIE8fRhFFsXeH8/QQ+s0T0kDAhKc4k30s73/0ydkHQz6HlQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-errors": "^1.3.0", - "set-function-name": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/resolve": { - "version": "1.22.8", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", - "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-core-module": "^2.13.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/resolve-pkg-maps": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", - "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" - } - }, - "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true, - "license": "MIT", - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", - "dev": true, - "license": "ISC", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, - "node_modules/safe-array-concat": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz", - "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "get-intrinsic": "^1.2.4", - "has-symbols": "^1.0.3", - "isarray": "^2.0.5" - }, - "engines": { - "node": ">=0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/safe-regex-test": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", - "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.6", - "es-errors": "^1.3.0", - "is-regex": "^1.1.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/scheduler": { - "version": "0.25.0-rc-69d4b800-20241021", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.25.0-rc-69d4b800-20241021.tgz", - "integrity": "sha512-S5AYX/YhMAN6u9AXgKYbZP4U4ZklC6R9Q7HmFSBk7d4DLiHVNxvAvlSvuM4nxFkwOk50MnpfTKQ7UWHXDOc9Eg==", - "license": "MIT" - }, - "node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "devOptional": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/set-function-length": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", - "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", - "dev": true, - "license": "MIT", - "dependencies": { - "define-data-property": "^1.1.4", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/set-function-name": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", - "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "define-data-property": "^1.1.4", - "es-errors": "^1.3.0", - "functions-have-names": "^1.2.3", - "has-property-descriptors": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/sharp": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.33.5.tgz", - "integrity": "sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw==", - "hasInstallScript": true, - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "color": "^4.2.3", - "detect-libc": "^2.0.3", - "semver": "^7.6.3" - }, - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-darwin-arm64": "0.33.5", - "@img/sharp-darwin-x64": "0.33.5", - "@img/sharp-libvips-darwin-arm64": "1.0.4", - "@img/sharp-libvips-darwin-x64": "1.0.4", - "@img/sharp-libvips-linux-arm": "1.0.5", - "@img/sharp-libvips-linux-arm64": "1.0.4", - "@img/sharp-libvips-linux-s390x": "1.0.4", - "@img/sharp-libvips-linux-x64": "1.0.4", - "@img/sharp-libvips-linuxmusl-arm64": "1.0.4", - "@img/sharp-libvips-linuxmusl-x64": "1.0.4", - "@img/sharp-linux-arm": "0.33.5", - "@img/sharp-linux-arm64": "0.33.5", - "@img/sharp-linux-s390x": "0.33.5", - "@img/sharp-linux-x64": "0.33.5", - "@img/sharp-linuxmusl-arm64": "0.33.5", - "@img/sharp-linuxmusl-x64": "0.33.5", - "@img/sharp-wasm32": "0.33.5", - "@img/sharp-win32-ia32": "0.33.5", - "@img/sharp-win32-x64": "0.33.5" - } - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "license": "MIT", - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/side-channel": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", - "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4", - "object-inspect": "^1.13.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/simple-swizzle": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", - "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==", - "license": "MIT", - "optional": true, - "dependencies": { - "is-arrayish": "^0.3.1" - } - }, - "node_modules/source-map-js": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/streamsearch": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", - "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "dev": true, - "license": "MIT", - "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/string-width-cjs": { - "name": "string-width", - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/string-width-cjs/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, - "license": "MIT" - }, - "node_modules/string-width/node_modules/ansi-regex": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", - "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/string-width/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/string.prototype.includes": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/string.prototype.includes/-/string.prototype.includes-2.0.1.tgz", - "integrity": "sha512-o7+c9bW6zpAdJHTtujeePODAhkuicdAryFsfVKwA+wGw89wJ4GTY484WTucM9hLtDEOpOvI+aHnzqnC5lHp4Rg==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.3" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/string.prototype.matchall": { - "version": "4.0.11", - "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.11.tgz", - "integrity": "sha512-NUdh0aDavY2og7IbBPenWqR9exH+E26Sv8e0/eTe1tltDGZL+GtBkDAnnyBtmekfK6/Dq3MkcGtzXFEd1LQrtg==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "get-intrinsic": "^1.2.4", - "gopd": "^1.0.1", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.7", - "regexp.prototype.flags": "^1.5.2", - "set-function-name": "^2.0.2", - "side-channel": "^1.0.6" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.repeat": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz", - "integrity": "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==", - "dev": true, - "license": "MIT", - "dependencies": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.5" - } - }, - "node_modules/string.prototype.trim": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz", - "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.0", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trimend": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz", - "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trimstart": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", - "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi-cjs": { - "name": "strip-ansi", - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/styled-jsx": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.6.tgz", - "integrity": "sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA==", - "license": "MIT", - "dependencies": { - "client-only": "0.0.1" - }, - "engines": { - "node": ">= 12.0.0" - }, - "peerDependencies": { - "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0" - }, - "peerDependenciesMeta": { - "@babel/core": { - "optional": true - }, - "babel-plugin-macros": { - "optional": true - } - } - }, - "node_modules/sucrase": { - "version": "3.35.0", - "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", - "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.2", - "commander": "^4.0.0", - "glob": "^10.3.10", - "lines-and-columns": "^1.1.6", - "mz": "^2.7.0", - "pirates": "^4.0.1", - "ts-interface-checker": "^0.1.9" - }, - "bin": { - "sucrase": "bin/sucrase", - "sucrase-node": "bin/sucrase-node" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/sucrase/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/sucrase/node_modules/glob": { - "version": "10.4.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", - "dev": true, - "license": "ISC", - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^1.11.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/sucrase/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/tailwindcss": { - "version": "3.4.14", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.14.tgz", - "integrity": "sha512-IcSvOcTRcUtQQ7ILQL5quRDg7Xs93PdJEk1ZLbhhvJc7uj/OAhYOnruEiwnGgBvUtaUAJ8/mhSw1o8L2jCiENA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@alloc/quick-lru": "^5.2.0", - "arg": "^5.0.2", - "chokidar": "^3.5.3", - "didyoumean": "^1.2.2", - "dlv": "^1.1.3", - "fast-glob": "^3.3.0", - "glob-parent": "^6.0.2", - "is-glob": "^4.0.3", - "jiti": "^1.21.0", - "lilconfig": "^2.1.0", - "micromatch": "^4.0.5", - "normalize-path": "^3.0.0", - "object-hash": "^3.0.0", - "picocolors": "^1.0.0", - "postcss": "^8.4.23", - "postcss-import": "^15.1.0", - "postcss-js": "^4.0.1", - "postcss-load-config": "^4.0.1", - "postcss-nested": "^6.0.1", - "postcss-selector-parser": "^6.0.11", - "resolve": "^1.22.2", - "sucrase": "^3.32.0" - }, - "bin": { - "tailwind": "lib/cli.js", - "tailwindcss": "lib/cli.js" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true, - "license": "MIT" - }, - "node_modules/thenify": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", - "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", - "dev": true, - "license": "MIT", - "dependencies": { - "any-promise": "^1.0.0" - } - }, - "node_modules/thenify-all": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", - "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", - "dev": true, - "license": "MIT", - "dependencies": { - "thenify": ">= 3.1.0 < 4" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/ts-api-utils": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", - "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=16" - }, - "peerDependencies": { - "typescript": ">=4.2.0" - } - }, - "node_modules/ts-interface-checker": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", - "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", - "dev": true, - "license": "Apache-2.0" - }, - "node_modules/tsconfig-paths": { - "version": "3.15.0", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", - "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/json5": "^0.0.29", - "json5": "^1.0.2", - "minimist": "^1.2.6", - "strip-bom": "^3.0.0" - } - }, - "node_modules/tslib": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.0.tgz", - "integrity": "sha512-jWVzBLplnCmoaTr13V9dYbiQ99wvZRd0vNWaDRg+aVYRcjDF3nDksxFDE/+fkXnKhpnUUkmx5pK/v8mCtLVqZA==", - "license": "0BSD" - }, - "node_modules/type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "license": "MIT", - "dependencies": { - "prelude-ls": "^1.2.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/typed-array-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", - "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "es-errors": "^1.3.0", - "is-typed-array": "^1.1.13" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/typed-array-byte-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", - "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-proto": "^1.0.3", - "is-typed-array": "^1.1.13" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/typed-array-byte-offset": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", - "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", - "dev": true, - "license": "MIT", - "dependencies": { - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.7", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-proto": "^1.0.3", - "is-typed-array": "^1.1.13" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/typed-array-length": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.6.tgz", - "integrity": "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-proto": "^1.0.3", - "is-typed-array": "^1.1.13", - "possible-typed-array-names": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/typescript": { - "version": "5.6.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz", - "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==", - "dev": true, - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, - "node_modules/unbox-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", - "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "has-bigints": "^1.0.2", - "has-symbols": "^1.0.3", - "which-boxed-primitive": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/undici-types": { - "version": "6.19.8", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", - "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", - "dev": true, - "license": "MIT" - }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true, - "license": "MIT" - }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "license": "ISC", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/which-boxed-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", - "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/which-builtin-type": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.1.4.tgz", - "integrity": "sha512-bppkmBSsHFmIMSl8BO9TbsyzsvGjVoppt8xUiGzwiu/bhDCGxnpOKCxgqj6GuyHE0mINMDecBFPlOm2hzY084w==", - "dev": true, - "license": "MIT", - "dependencies": { - "function.prototype.name": "^1.1.6", - "has-tostringtag": "^1.0.2", - "is-async-function": "^2.0.0", - "is-date-object": "^1.0.5", - "is-finalizationregistry": "^1.0.2", - "is-generator-function": "^1.0.10", - "is-regex": "^1.1.4", - "is-weakref": "^1.0.2", - "isarray": "^2.0.5", - "which-boxed-primitive": "^1.0.2", - "which-collection": "^1.0.2", - "which-typed-array": "^1.1.15" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/which-collection": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", - "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-map": "^2.0.3", - "is-set": "^2.0.3", - "is-weakmap": "^2.0.2", - "is-weakset": "^2.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/which-typed-array": { - "version": "1.1.15", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", - "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", - "dev": true, - "license": "MIT", - "dependencies": { - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.7", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/word-wrap": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", - "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/wrap-ansi": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrap-ansi-cjs": { - "name": "wrap-ansi", - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, - "license": "MIT" - }, - "node_modules/wrap-ansi-cjs/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/wrap-ansi/node_modules/ansi-regex": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", - "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/wrap-ansi/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/wrap-ansi/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/yaml": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.0.tgz", - "integrity": "sha512-a6ae//JvKDEra2kdi1qzCyrJW/WZCgFi8ydDV+eXExl95t+5R+ijnqHJbz9tmMh8FUjx3iv2fCQ4dclAQlO2UQ==", - "dev": true, - "license": "ISC", - "bin": { - "yaml": "bin.mjs" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - } - } -} diff --git a/src/feature/common/failures/failure-helpers.ts b/src/feature/common/failures/failure-helpers.ts index a6c8f46..673b8aa 100644 --- a/src/feature/common/failures/failure-helpers.ts +++ b/src/feature/common/failures/failure-helpers.ts @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ import BaseFailure from "@/feature/common/failures/base-failure"; /** @@ -16,16 +17,19 @@ import BaseFailure from "@/feature/common/failures/base-failure"; * ) * ``` * In this example `failureOr` will return already throwed - * instance of `BaseFailure` which is `ValidationFailure`. + * instance of `BaseFailure<any>` which is `ValidationFailure`. * * * @param reason is throwed object. - * Basically it can be default `Error` or instance of `BaseFailure`. - * @param failure instance of `BaseFailure` that will be returned - * if reason is not instance of `BaseFailure`. - * @returns `BaseFailure` + * Basically it can be default `Error` or instance of `BaseFailure<any>`. + * @param failure instance of `BaseFailure<any>` that will be returned + * if reason is not instance of `BaseFailure<any>`. + * @returns `BaseFailure<any>` */ -export function failureOr(reason: unknown, failure: BaseFailure): BaseFailure { +export function failureOr( + reason: unknown, + failure: BaseFailure<any>, +): BaseFailure<any> { if (reason instanceof BaseFailure) { return reason; } @@ -33,16 +37,16 @@ export function failureOr(reason: unknown, failure: BaseFailure): BaseFailure { } /** - * Returns a function that maps a BaseFailure instance to a new BaseFailure instance of type IfType using the provided mapping function. - * @param f A function that maps an instance of IfType to a new instance of BaseFailure. + * Returns a function that maps a BaseFailure<any> instance to a new BaseFailure<any> instance of type IfType using the provided mapping function. + * @param f A function that maps an instance of IfType to a new instance of BaseFailure<any>. * @param ctor A constructor function for IfType. - * @returns A function that maps a BaseFailure instance to a new BaseFailure instance of type IfType. + * @returns A function that maps a BaseFailure<any> instance to a new BaseFailure<any> instance of type IfType. */ -export function mapToFailureFrom<IfType extends BaseFailure>( - f: (t: IfType) => BaseFailure, +export function mapToFailureFrom<IfType extends BaseFailure<any>>( + f: (t: IfType) => BaseFailure<any>, ctor: new (...args: never[]) => IfType, -): (t: BaseFailure) => BaseFailure { - return mapIfInstance<IfType, BaseFailure>(f, ctor); +): (t: BaseFailure<any>) => BaseFailure<any> { + return mapIfInstance<IfType, BaseFailure<any>>(f, ctor); } /** -- 2.39.5 From 1675d84caee45c51460ef63de46a5d902d0deb2e Mon Sep 17 00:00:00 2001 From: behnam <behnamrahimpour74@gmail.com> Date: Tue, 26 Nov 2024 15:42:16 +0000 Subject: [PATCH 37/37] Add storybook with i18n and darkmode Reviewed-on: https://git.dipal.ru/behnam/Nextjs-boilerplate/pulls/2 --- .eslintignore | 1 + .eslintrc.json | 48 +- .gitignore | 2 + .storybook/main.ts | 18 + .storybook/preview.tsx | 134 + docker-compose.yml | 1 - package.json | 16 +- .../client/theme-provider/theme-provider.tsx | 11 + src/app/[lang]/dashboard/page.tsx | 4 +- src/app/[lang]/layout.tsx | 20 +- src/app/components/button/button.tsx | 1 - .../button/stories/Button.stories.tsx | 65 + src/app/globals.css | 2 +- src/bootstrap/di/mocked-module-di.ts | 33 + src/bootstrap/helpers/global-helpers.ts | 7 + src/bootstrap/helpers/hooks/use-throttle.ts | 4 +- .../view/storybook-base-template-type.ts | 5 + .../helpers/view/storybook-with-arg-vm.ts | 14 + src/bootstrap/i18n/i18n-provider.tsx | 13 +- src/bootstrap/i18n/i18n.ts | 26 +- tailwind.config.ts | 102 +- yarn.lock | 3643 ++++++++++++++++- 22 files changed, 4015 insertions(+), 155 deletions(-) create mode 100644 .eslintignore create mode 100644 .storybook/main.ts create mode 100644 .storybook/preview.tsx create mode 100644 src/app/[lang]/dashboard/components/client/theme-provider/theme-provider.tsx create mode 100644 src/app/components/button/stories/Button.stories.tsx create mode 100644 src/bootstrap/di/mocked-module-di.ts create mode 100644 src/bootstrap/helpers/view/storybook-base-template-type.ts create mode 100644 src/bootstrap/helpers/view/storybook-with-arg-vm.ts diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000..9e6de2f --- /dev/null +++ b/.eslintignore @@ -0,0 +1 @@ +tailwind.config.ts \ No newline at end of file diff --git a/.eslintrc.json b/.eslintrc.json index 6307415..1c88a7d 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -5,14 +5,19 @@ "src/**/*-vm.ts" ], "rules": { - "react-hooks/rules-of-hooks": "off" + "react-hooks/rules-of-hooks": "off" } + }, + { + "files": [ + "src/app/**/*.stories.tsx" + ], + "rules": { + "react/jsx-props-no-spreading": "off" + } } ], - "plugins": [ - "prettier" - ], - "settings": { + "settings": { "react": { "version": "detect" }, @@ -35,6 +40,16 @@ } } }, + "plugins": [ + "prettier" + ], + "extends": [ + "airbnb", + "next/core-web-vitals", + "next/typescript", + "prettier", + "plugin:storybook/recommended" + ], "rules": { "no-use-before-define": "off", "class-methods-use-this": "off", @@ -43,13 +58,24 @@ "no-promise-executor-return": "off", "@typescript-eslint/no-shadow": "off", "react/require-default-props": "off", + "import/order": [ + "error", + { + "pathGroups": [ + { + "pattern": "@/**", + "group": "external" + } + ] + } + ], "no-shadow": "off", "prettier/prettier": [ "warn", { "printWidth": 80, "tabWidth": 2, - "endOfLine":"auto", + "endOfLine": "auto", "useTabs": false, "semi": true, "singleQuote": false, @@ -85,11 +111,5 @@ "devDependencies": true } ] - }, - "extends": [ - "airbnb", - "next/core-web-vitals", - "next/typescript", - "prettier" - ] -} + } +} \ No newline at end of file diff --git a/.gitignore b/.gitignore index 39c19d2..a39f2a5 100644 --- a/.gitignore +++ b/.gitignore @@ -38,3 +38,5 @@ yarn-error.log* # typescript *.tsbuildinfo next-env.d.ts + +*storybook.log diff --git a/.storybook/main.ts b/.storybook/main.ts new file mode 100644 index 0000000..6efa0cd --- /dev/null +++ b/.storybook/main.ts @@ -0,0 +1,18 @@ +import type { StorybookConfig } from "@storybook/nextjs"; + +const config: StorybookConfig = { + stories: ["../src/**/*.mdx", "../src/**/*.stories.@(js|jsx|mjs|ts|tsx)"], + addons: [ + "@storybook/addon-onboarding", + "@storybook/addon-essentials", + "@chromatic-com/storybook", + "@storybook/addon-interactions", + "storybook-dark-mode" + ], + framework: { + name: "@storybook/nextjs", + options: {}, + }, + staticDirs: ["../public"], +}; +export default config; diff --git a/.storybook/preview.tsx b/.storybook/preview.tsx new file mode 100644 index 0000000..dc1dbaa --- /dev/null +++ b/.storybook/preview.tsx @@ -0,0 +1,134 @@ +import React, { useRef } from "react"; +import { themes } from '@storybook/theming'; +import { ThemeProvider } from "../src/app/[lang]/dashboard/components/client/theme-provider/theme-provider"; +import { DARK_MODE_EVENT_NAME, UPDATE_DARK_MODE_EVENT_NAME } from 'storybook-dark-mode'; +import { initI18next, LANGS } from "../src/bootstrap/i18n/i18n" +import { addons } from '@storybook/preview-api'; +import { i18n } from "i18next"; +import { I18nextProvider } from "react-i18next"; +const channel = addons.getChannel(); +import "../src/app/globals.css" +/** + * + * This function will expand the object with nested properties + * @param obj refrence Object to that + * @param leftKeys keys to be nested object keys + * @param value value to be nested + * + */ +export const recursiveNestedProps = ( + obj: Record<string, unknown>, + leftKeys: string[], + value: unknown, +): Record<string, unknown> => { + if (leftKeys.length <= 0) return obj; + if (leftKeys.length === 1) { + // eslint-disable-next-line no-param-reassign + obj[leftKeys[0]] = value; + return obj; + } + const key = leftKeys.shift(); + if (!key) return obj; + + if (!obj[key]) { + // eslint-disable-next-line no-param-reassign + obj[key] = {}; + } + + return recursiveNestedProps( + obj[key] as Record<string, unknown>, + leftKeys, + value, + ); +}; + +const preview = { + decorators: [ + (Story, data) => { + const [isDark, setDark] = React.useState(true); + const [i18n, setI18n] = React.useState<i18n>() + const parsedProps = {} as Record<string, unknown>; + const { locale } = data.globals + const props = data.allArgs; + Object.entries(props).forEach((prop) => { + const [key, value] = prop; + if (!key.includes("vm")) { + parsedProps[key] = value; + return; + } + const splitedKey = key.split("."); + + recursiveNestedProps(parsedProps, splitedKey, value); + }); + + + React.useEffect(() => { + channel.on(DARK_MODE_EVENT_NAME, setDark); + return () => channel.removeListener(DARK_MODE_EVENT_NAME, setDark); + }, [channel, setDark]); + + React.useEffect(() => { + (async () => { + setI18n((await initI18next({ lng: locale })).i18n); + })() + }, []) + + React.useEffect(() => { + i18n?.changeLanguage(locale); + }, [locale]); + + return ( + <ThemeProvider + attribute="class" + forcedTheme={isDark ? "dark" : "light"} + enableSystem + disableTransitionOnChange + > + { + i18n && ( + <I18nextProvider + i18n={i18n} + > + <Story parsedProps={parsedProps} /> + </I18nextProvider> + ) + } + </ThemeProvider> + ); + }, + ], + darkMode: { + // Override the default dark theme + dark: { ...themes.dark, appBg: 'black' }, + // Override the default light theme + classTarget: 'html', + light: { ...themes.normal, appBg: 'red' }, + }, + parameters: { + nextjs: { + appDirectory: true, + }, + controls: { + matchers: { + color: /(background|color)$/i, + date: /Date$/i, + }, + }, + }, + globalTypes: { + locale: { + name: 'Locale', + description: 'Internationalization locale', + toolbar: { + icon: 'globe', + items: [ + { value: LANGS.EN, title: 'English' }, + { value: LANGS.RU, title: 'Russian' }, + ], + showName: true, + }, + }, + } +}; + +export default preview; diff --git a/docker-compose.yml b/docker-compose.yml index 9e2981f..189a656 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -11,7 +11,6 @@ services: POSTGRES_USER: admin POSTGRES_DB: nextbp - app: build: . ports: diff --git a/package.json b/package.json index ad7a6a0..59fef4e 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,9 @@ "start": "next start --port 4000", "lint": "next lint --fix", "test": "vitest", - "seed": "node -r dotenv/config ./src/bootstrap/boundaries/db/seed.js" + "seed": "node -r dotenv/config ./src/bootstrap/boundaries/db/seed.js", + "storybook": "storybook dev -p 6006 --no-open", + "build-storybook": "storybook build" }, "dependencies": { "@heroicons/react": "^2.1.5", @@ -24,6 +26,7 @@ "lucide-react": "^0.454.0", "next": "15.0.2", "next-i18n-router": "^5.5.1", + "next-themes": "^0.4.3", "postgres": "^3.4.5", "react": "19.0.0-rc-69d4b800-20241021", "react-cookie": "^7.2.2", @@ -37,7 +40,15 @@ "zod": "^3.23.8" }, "devDependencies": { + "@chromatic-com/storybook": "^3.2.2", "@faker-js/faker": "^9.1.0", + "@storybook/addon-essentials": "^8.4.5", + "@storybook/addon-interactions": "^8.4.5", + "@storybook/addon-onboarding": "^8.4.5", + "@storybook/blocks": "^8.4.5", + "@storybook/nextjs": "^8.4.5", + "@storybook/react": "^8.4.5", + "@storybook/test": "^8.4.5", "@testing-library/dom": "^10.4.0", "@testing-library/react": "^16.0.1", "@types/node": "^20", @@ -53,10 +64,13 @@ "eslint-import-resolver-alias": "^1.1.2", "eslint-import-resolver-typescript": "^3.6.3", "eslint-plugin-prettier": "^5.2.1", + "eslint-plugin-storybook": "^0.11.1", "jsdom": "^25.0.1", "moq.ts": "^10.0.8", "postcss": "^8", "prettier": "^3.3.3", + "storybook": "^8.4.5", + "storybook-dark-mode": "^4.0.2", "tailwindcss": "^3.4.1", "typescript": "^5", "vitest": "^2.1.4" diff --git a/src/app/[lang]/dashboard/components/client/theme-provider/theme-provider.tsx b/src/app/[lang]/dashboard/components/client/theme-provider/theme-provider.tsx new file mode 100644 index 0000000..6a1ffe4 --- /dev/null +++ b/src/app/[lang]/dashboard/components/client/theme-provider/theme-provider.tsx @@ -0,0 +1,11 @@ +"use client" + +import * as React from "react" +import { ThemeProvider as NextThemesProvider } from "next-themes" + +export function ThemeProvider({ + children, + ...props +}: React.ComponentProps<typeof NextThemesProvider>) { + return <NextThemesProvider {...props}>{children}</NextThemesProvider> +} diff --git a/src/app/[lang]/dashboard/page.tsx b/src/app/[lang]/dashboard/page.tsx index f9f980f..ea09ada 100644 --- a/src/app/[lang]/dashboard/page.tsx +++ b/src/app/[lang]/dashboard/page.tsx @@ -6,11 +6,11 @@ import CardWrapper from "@/app/[lang]/dashboard/components/server/cards/cards"; import LatestInvoices from "@/app/[lang]/dashboard/components/server/latest-invoices/latest-invoices"; import RevenueChart from "@/app/[lang]/dashboard/components/server/revenue-chart/revenue-chart"; import { Suspense } from "react"; -import { getServerTranslation } from "@/bootstrap/i18n/i18n"; +import { getServerTranslation, LANGS } from "@/bootstrap/i18n/i18n"; import langKey from "@/bootstrap/i18n/dictionaries/lang-key"; export default async function Dashboard(props: { - params: Promise<{ lang: string }>; + params: Promise<{ lang: LANGS }>; }) { const { params } = props; const { lang } = await params; diff --git a/src/app/[lang]/layout.tsx b/src/app/[lang]/layout.tsx index b142672..89037c1 100644 --- a/src/app/[lang]/layout.tsx +++ b/src/app/[lang]/layout.tsx @@ -1,4 +1,5 @@ -import { initI18next } from "@/bootstrap/i18n/i18n"; +import { ThemeProvider } from "@/app/[lang]/dashboard/components/client/theme-provider/theme-provider"; +import { initI18next, LANGS } from "@/bootstrap/i18n/i18n"; import TranslationsProvider from "@/bootstrap/i18n/i18n-provider"; import localFont from "next/font/local"; import { PropsWithChildren } from "react"; @@ -15,19 +16,26 @@ const geistMono = localFont({ }); export default async function layout( - props: PropsWithChildren & { params: Promise<{ lang: string }> }, + props: PropsWithChildren & { params: Promise<{ lang: LANGS }> }, ) { const { params, children } = props; const { lang } = await params; const { resources } = await initI18next({ lng: lang }); return ( - <html lang={lang}> + <html lang={lang} suppressHydrationWarning> <body className={`${geistSans.variable} ${geistMono.variable} antialiased`} > - <TranslationsProvider lng={lang} resources={resources}> - {children} - </TranslationsProvider> + <ThemeProvider + attribute="class" + defaultTheme="light" + enableSystem + disableTransitionOnChange + > + <TranslationsProvider lng={lang} resources={resources}> + {children} + </TranslationsProvider> + </ThemeProvider> </body> </html> ); diff --git a/src/app/components/button/button.tsx b/src/app/components/button/button.tsx index 5520728..2c72f27 100644 --- a/src/app/components/button/button.tsx +++ b/src/app/components/button/button.tsx @@ -11,7 +11,6 @@ import { cn } from "@/bootstrap/helpers/lib/ui-utils"; export default class Button extends BaseView<ButtonVm> { protected Build(props: BuildProps<ButtonVm>): ReactNode { const { vm } = props; - return ( <ButtonUi disabled={vm.props.isDisable} onClick={vm.onClick}> {vm.props.title} diff --git a/src/app/components/button/stories/Button.stories.tsx b/src/app/components/button/stories/Button.stories.tsx new file mode 100644 index 0000000..d7739ae --- /dev/null +++ b/src/app/components/button/stories/Button.stories.tsx @@ -0,0 +1,65 @@ +import CreateRandomInvoiceButtonVM from "@/app/[lang]/dashboard/vm/create-random-invoice-button-vm"; +import Button from "@/app/components/button/button"; +import { DiContext, useDI } from "@/bootstrap/di/di-context"; +import mockedModuleDi from "@/bootstrap/di/mocked-module-di"; +import Story from "@/bootstrap/helpers/view/storybook-base-template-type"; +import getArgVM from "@/bootstrap/helpers/view/storybook-with-arg-vm"; +import createInvoiceUsecase from "@/feature/core/invoice/domain/usecase/create-invoice-usecase"; +import type { Meta } from "@storybook/react"; +import { useRef } from "react"; + +const meta: Meta = { + title: "general/Button", +}; + +export default meta; + +export const Primary: Story = { + argTypes: { + "vm.props.isDisable": { + control: "boolean", + }, + "vm.props.title": { + control: "text", + }, + }, + args: { + "vm.props.title": "Button", + "vm.props.isDisable": false, + }, + render: (_props, globalData) => { + const vm = getArgVM(globalData.parsedProps.vm); // You can use parsed props to access your vm properties. + return <Button vm={vm} memoizedByVM={false} />; + }, +}; + +export const WithVM: Story = { + decorators: [ + (Story) => { + const di = mockedModuleDi([ + { + token: CreateRandomInvoiceButtonVM, + provider: CreateRandomInvoiceButtonVM, + }, + { + token: createInvoiceUsecase.name, + // eslint-disable-next-line @typescript-eslint/no-explicit-any, no-console + provider: (args: any) => console.log("clicked", args), + }, + ]); + return <Story di={di} />; + }, + ], + render: (_, globalProps) => { + function Child() { + const di = useDI(); + const vm = useRef(di.resolve(CreateRandomInvoiceButtonVM)); + return <Button vm={vm.current} memoizedByVM={false} />; + } + return ( + <DiContext.Provider value={globalProps.di}> + <Child /> + </DiContext.Provider> + ); + }, +}; diff --git a/src/app/globals.css b/src/app/globals.css index 942f871..be56f49 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -34,7 +34,7 @@ body { --chart-5: 27 87% 67%; --radius: 0.5rem; } - .dark { + :root[class~="dark"] { --background: 240 10% 3.9%; --foreground: 0 0% 98%; --card: 240 10% 3.9%; diff --git a/src/bootstrap/di/mocked-module-di.ts b/src/bootstrap/di/mocked-module-di.ts new file mode 100644 index 0000000..5fc1d93 --- /dev/null +++ b/src/bootstrap/di/mocked-module-di.ts @@ -0,0 +1,33 @@ +import { container, DependencyContainer } from "tsyringe"; +import { InjectionToken } from "tsyringe/dist/typings/providers"; +import constructor from "tsyringe/dist/typings/types/constructor"; +import { isClass } from "../helpers/global-helpers"; + +/** + * Provides mocked di for test cases and using instead of real di + * @param providers List of providers + * @returns Mocked di with registered providers + */ +const mockedModuleDi = ( + providers: { + token: InjectionToken<unknown>; + provider: unknown | constructor<unknown>; + }[], +): DependencyContainer => { + const di = container.createChildContainer(); + + providers.forEach((provider) => { + if (isClass(provider.provider)) { + di.register(provider.token, provider.provider); + return; + } + + di.register(provider.token, { + useValue: provider.provider, + }); + }); + + return di; +}; + +export default mockedModuleDi; diff --git a/src/bootstrap/helpers/global-helpers.ts b/src/bootstrap/helpers/global-helpers.ts index ca617a8..ca009a2 100644 --- a/src/bootstrap/helpers/global-helpers.ts +++ b/src/bootstrap/helpers/global-helpers.ts @@ -1 +1,8 @@ +import { constructor } from "tsyringe/dist/typings/types"; + export const isServer = typeof window === "undefined"; + +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export function isClass(fn: any): fn is constructor<unknown> { + return typeof fn === "function" && /^(class|function [A-Z])/.test(fn); +} diff --git a/src/bootstrap/helpers/hooks/use-throttle.ts b/src/bootstrap/helpers/hooks/use-throttle.ts index 6f8213b..b791f67 100644 --- a/src/bootstrap/helpers/hooks/use-throttle.ts +++ b/src/bootstrap/helpers/hooks/use-throttle.ts @@ -11,11 +11,11 @@ export default function useThrottle<T extends () => unknown>( callback: T, time: number = 2000, ) { - const lastRun = useRef(Date.now()); + const lastRun = useRef<number>(); // eslint-disable-next-line func-names return function () { - if (Date.now() - lastRun.current <= time) return; + if (lastRun.current && Date.now() - lastRun.current <= time) return; lastRun.current = Date.now(); callback(); }; diff --git a/src/bootstrap/helpers/view/storybook-base-template-type.ts b/src/bootstrap/helpers/view/storybook-base-template-type.ts new file mode 100644 index 0000000..763c5fe --- /dev/null +++ b/src/bootstrap/helpers/view/storybook-base-template-type.ts @@ -0,0 +1,5 @@ +import { Meta, StoryObj } from "@storybook/react"; + +type Story = StoryObj<Meta>; + +export default Story; diff --git a/src/bootstrap/helpers/view/storybook-with-arg-vm.ts b/src/bootstrap/helpers/view/storybook-with-arg-vm.ts new file mode 100644 index 0000000..210e173 --- /dev/null +++ b/src/bootstrap/helpers/view/storybook-with-arg-vm.ts @@ -0,0 +1,14 @@ +import IBaseVM from "@/bootstrap/helpers/vm/i-base-vm"; + +const getArgVM = <IVM>(vmObj: IVM) => { + class VM implements IBaseVM<IVM> { + useVM(): IVM { + return { + ...vmObj, + }; + } + } + return new VM(); +}; + +export default getArgVM; diff --git a/src/bootstrap/i18n/i18n-provider.tsx b/src/bootstrap/i18n/i18n-provider.tsx index c3272d8..ed50a29 100644 --- a/src/bootstrap/i18n/i18n-provider.tsx +++ b/src/bootstrap/i18n/i18n-provider.tsx @@ -1,18 +1,17 @@ "use client"; import { I18nextProvider } from "react-i18next"; -import { initI18next } from "@/bootstrap/i18n/i18n"; -import { createInstance, Resource } from "i18next"; +import { i18nInstance, initI18next, LANGS } from "@/bootstrap/i18n/i18n"; +import { Resource } from "i18next"; import { PropsWithChildren } from "react"; export default function TranslationsProvider({ children, lng, resources, -}: PropsWithChildren & { lng: string; resources: Resource }) { - const i18n = createInstance(); +}: PropsWithChildren & { lng: LANGS; resources: Resource }) { + if (!resources) return children; + initI18next({ lng, resources }); - initI18next({ lng, i18n, resources }); - - return <I18nextProvider i18n={i18n}>{children}</I18nextProvider>; + return <I18nextProvider i18n={i18nInstance}>{children}</I18nextProvider>; } diff --git a/src/bootstrap/i18n/i18n.ts b/src/bootstrap/i18n/i18n.ts index c95d601..9e376a9 100644 --- a/src/bootstrap/i18n/i18n.ts +++ b/src/bootstrap/i18n/i18n.ts @@ -1,23 +1,26 @@ import { getOptions, languages } from "@/bootstrap/i18n/settings"; -import { createInstance, i18n, Resource } from "i18next"; +import { createInstance, Resource } from "i18next"; import resourcesToBackend from "i18next-resources-to-backend"; import { initReactI18next } from "react-i18next/initReactI18next"; -const initI18nextInstance = createInstance(); +export const i18nInstance = createInstance(); + +export enum LANGS { + EN = "en", + RU = "ru", +} export const initI18next = async (params: { - lng: string; - i18n?: i18n; + lng: LANGS; resources?: Resource; ns?: string; }) => { - const { lng, i18n, ns, resources } = params; - const i18nInstance = i18n || initI18nextInstance; + const { lng, ns, resources } = params; await i18nInstance .use(initReactI18next) .use( resourcesToBackend( - (language: string) => import(`./dictionaries/${language}.ts`), + (language: LANGS) => import(`./dictionaries/${language}.ts`), ), ) .init({ @@ -36,18 +39,17 @@ export const initI18next = async (params: { }; export async function getServerTranslation( - lng: string, + lng: LANGS, ns?: string, options: { keyPrefix?: string } = {}, ) { - const i18nextInstance = (await initI18next({ lng, ns })).i18n; - + await initI18next({ lng }); return { - t: i18nextInstance.getFixedT( + t: i18nInstance.getFixedT( lng, Array.isArray(ns) ? ns[0] : ns, options?.keyPrefix, ), - i18n: i18nextInstance, + i18n: i18nInstance, }; } diff --git a/tailwind.config.ts b/tailwind.config.ts index 1f7474c..c3fef07 100644 --- a/tailwind.config.ts +++ b/tailwind.config.ts @@ -2,62 +2,62 @@ import type { Config } from "tailwindcss"; const config: Config = { - darkMode: ["class"], - content: [ + darkMode: ["class"], + content: [ "./src/pages/**/*.{js,ts,jsx,tsx,mdx}", "./src/components/**/*.{js,ts,jsx,tsx,mdx}", "./src/app/**/*.{js,ts,jsx,tsx,mdx}", ], theme: { - extend: { - colors: { - background: 'hsl(var(--background))', - foreground: 'hsl(var(--foreground))', - card: { - DEFAULT: 'hsl(var(--card))', - foreground: 'hsl(var(--card-foreground))' - }, - popover: { - DEFAULT: 'hsl(var(--popover))', - foreground: 'hsl(var(--popover-foreground))' - }, - primary: { - DEFAULT: 'hsl(var(--primary))', - foreground: 'hsl(var(--primary-foreground))' - }, - secondary: { - DEFAULT: 'hsl(var(--secondary))', - foreground: 'hsl(var(--secondary-foreground))' - }, - muted: { - DEFAULT: 'hsl(var(--muted))', - foreground: 'hsl(var(--muted-foreground))' - }, - accent: { - DEFAULT: 'hsl(var(--accent))', - foreground: 'hsl(var(--accent-foreground))' - }, - destructive: { - DEFAULT: 'hsl(var(--destructive))', - foreground: 'hsl(var(--destructive-foreground))' - }, - border: 'hsl(var(--border))', - input: 'hsl(var(--input))', - ring: 'hsl(var(--ring))', - chart: { - '1': 'hsl(var(--chart-1))', - '2': 'hsl(var(--chart-2))', - '3': 'hsl(var(--chart-3))', - '4': 'hsl(var(--chart-4))', - '5': 'hsl(var(--chart-5))' - } - }, - borderRadius: { - lg: 'var(--radius)', - md: 'calc(var(--radius) - 2px)', - sm: 'calc(var(--radius) - 4px)' - } - } + extend: { + colors: { + background: "hsl(var(--background))", + foreground: "hsl(var(--foreground))", + card: { + DEFAULT: "hsl(var(--card))", + foreground: "hsl(var(--card-foreground))", + }, + popover: { + DEFAULT: "hsl(var(--popover))", + foreground: "hsl(var(--popover-foreground))", + }, + primary: { + DEFAULT: "hsl(var(--primary))", + foreground: "hsl(var(--primary-foreground))", + }, + secondary: { + DEFAULT: "hsl(var(--secondary))", + foreground: "hsl(var(--secondary-foreground))", + }, + muted: { + DEFAULT: "hsl(var(--muted))", + foreground: "hsl(var(--muted-foreground))", + }, + accent: { + DEFAULT: "hsl(var(--accent))", + foreground: "hsl(var(--accent-foreground))", + }, + destructive: { + DEFAULT: "hsl(var(--destructive))", + foreground: "hsl(var(--destructive-foreground))", + }, + border: "hsl(var(--border))", + input: "hsl(var(--input))", + ring: "hsl(var(--ring))", + chart: { + "1": "hsl(var(--chart-1))", + "2": "hsl(var(--chart-2))", + "3": "hsl(var(--chart-3))", + "4": "hsl(var(--chart-4))", + "5": "hsl(var(--chart-5))", + }, + }, + borderRadius: { + lg: "var(--radius)", + md: "calc(var(--radius) - 2px)", + sm: "calc(var(--radius) - 4px)", + }, + }, }, plugins: [require("tailwindcss-animate")], }; diff --git a/yarn.lock b/yarn.lock index 827d025..413bcc0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,6 +2,11 @@ # yarn lockfile v1 +"@adobe/css-tools@^4.4.0": + version "4.4.1" + resolved "https://registry.yarnpkg.com/@adobe/css-tools/-/css-tools-4.4.1.tgz#2447a230bfe072c1659e6815129c03cf170710e3" + integrity sha512-12WGKBQzjUAI4ayyF4IAtfw2QR/IDoqk6jTddXDhtYTJF9ASmoE1zst7cVtP0aL/F1jUJL5r+JxKXKEgHNbEUQ== + "@alloc/quick-lru@^5.2.0": version "5.2.0" resolved "https://registry.yarnpkg.com/@alloc/quick-lru/-/quick-lru-5.2.0.tgz#7bf68b20c0a350f936915fcae06f58e32007ce30" @@ -15,7 +20,7 @@ "@jridgewell/gen-mapping" "^0.3.5" "@jridgewell/trace-mapping" "^0.3.24" -"@babel/code-frame@^7.10.4", "@babel/code-frame@^7.25.9", "@babel/code-frame@^7.26.0": +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.16.7", "@babel/code-frame@^7.25.9", "@babel/code-frame@^7.26.0": version "7.26.2" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.26.2.tgz#4b5fab97d33338eff916235055f0ebc21e573a85" integrity sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ== @@ -24,12 +29,12 @@ js-tokens "^4.0.0" picocolors "^1.0.0" -"@babel/compat-data@^7.25.9": +"@babel/compat-data@^7.22.6", "@babel/compat-data@^7.25.9", "@babel/compat-data@^7.26.0": version "7.26.2" resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.26.2.tgz#278b6b13664557de95b8f35b90d96785850bb56e" integrity sha512-Z0WgzSEa+aUcdiJuCIqgujCshpMWgUpgOxXotrYPSA53hA3qopNaqcJpyr0hVb1FeWdnqFA35/fUtXgBK8srQg== -"@babel/core@^7.25.2": +"@babel/core@^7.18.9", "@babel/core@^7.24.4", "@babel/core@^7.25.2": version "7.26.0" resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.26.0.tgz#d78b6023cc8f3114ccf049eb219613f74a747b40" integrity sha512-i1SLeK+DzNnQ3LL/CswPCa/E5u4lh1k6IAEphON8F+cXt0t9euTshDru0q7/IqMa1PMPz5RnHuHscF8/ZJsStg== @@ -61,7 +66,22 @@ "@jridgewell/trace-mapping" "^0.3.25" jsesc "^3.0.2" -"@babel/helper-compilation-targets@^7.25.9": +"@babel/helper-annotate-as-pure@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.9.tgz#d8eac4d2dc0d7b6e11fa6e535332e0d3184f06b4" + integrity sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g== + dependencies: + "@babel/types" "^7.25.9" + +"@babel/helper-builder-binary-assignment-operator-visitor@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.25.9.tgz#f41752fe772a578e67286e6779a68a5a92de1ee9" + integrity sha512-C47lC7LIDCnz0h4vai/tpNOI95tCd5ZT3iBt/DBH5lXKHZsyNQv18yf1wIIg2ntiQNgmAvA+DgZ82iW8Qdym8g== + dependencies: + "@babel/traverse" "^7.25.9" + "@babel/types" "^7.25.9" + +"@babel/helper-compilation-targets@^7.22.6", "@babel/helper-compilation-targets@^7.25.9": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.9.tgz#55af025ce365be3cdc0c1c1e56c6af617ce88875" integrity sha512-j9Db8Suy6yV/VHa4qzrj9yZfZxhLWQdVnRlXxmKLYlhWUVB1sB2G5sxuWYXk/whHD9iW76PmNzxZ4UCnTQTVEQ== @@ -72,6 +92,47 @@ lru-cache "^5.1.1" semver "^6.3.1" +"@babel/helper-create-class-features-plugin@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.25.9.tgz#7644147706bb90ff613297d49ed5266bde729f83" + integrity sha512-UTZQMvt0d/rSz6KI+qdu7GQze5TIajwTS++GUozlw8VBJDEOAqSXwm1WvmYEZwqdqSGQshRocPDqrt4HBZB3fQ== + dependencies: + "@babel/helper-annotate-as-pure" "^7.25.9" + "@babel/helper-member-expression-to-functions" "^7.25.9" + "@babel/helper-optimise-call-expression" "^7.25.9" + "@babel/helper-replace-supers" "^7.25.9" + "@babel/helper-skip-transparent-expression-wrappers" "^7.25.9" + "@babel/traverse" "^7.25.9" + semver "^6.3.1" + +"@babel/helper-create-regexp-features-plugin@^7.18.6", "@babel/helper-create-regexp-features-plugin@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.25.9.tgz#3e8999db94728ad2b2458d7a470e7770b7764e26" + integrity sha512-ORPNZ3h6ZRkOyAa/SaHU+XsLZr0UQzRwuDQ0cczIA17nAzZ+85G5cVkOJIj7QavLZGSe8QXUmNFxSZzjcZF9bw== + dependencies: + "@babel/helper-annotate-as-pure" "^7.25.9" + regexpu-core "^6.1.1" + semver "^6.3.1" + +"@babel/helper-define-polyfill-provider@^0.6.2", "@babel/helper-define-polyfill-provider@^0.6.3": + version "0.6.3" + resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.3.tgz#f4f2792fae2ef382074bc2d713522cf24e6ddb21" + integrity sha512-HK7Bi+Hj6H+VTHA3ZvBis7V/6hu9QuTrnMXNybfUf2iiuU/N97I8VjB+KbhFF8Rld/Lx5MzoCwPCpPjfK+n8Cg== + dependencies: + "@babel/helper-compilation-targets" "^7.22.6" + "@babel/helper-plugin-utils" "^7.22.5" + debug "^4.1.1" + lodash.debounce "^4.0.8" + resolve "^1.14.2" + +"@babel/helper-member-expression-to-functions@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.25.9.tgz#9dfffe46f727005a5ea29051ac835fb735e4c1a3" + integrity sha512-wbfdZ9w5vk0C0oyHqAJbc62+vet5prjj01jjJ8sKn3j9h3MQQlflEdXYvuqRWjHnM12coDEqiC1IRCi0U/EKwQ== + dependencies: + "@babel/traverse" "^7.25.9" + "@babel/types" "^7.25.9" + "@babel/helper-module-imports@^7.25.9": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz#e7f8d20602ebdbf9ebbea0a0751fb0f2a4141715" @@ -80,7 +141,7 @@ "@babel/traverse" "^7.25.9" "@babel/types" "^7.25.9" -"@babel/helper-module-transforms@^7.26.0": +"@babel/helper-module-transforms@^7.25.9", "@babel/helper-module-transforms@^7.26.0": version "7.26.0" resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz#8ce54ec9d592695e58d84cd884b7b5c6a2fdeeae" integrity sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw== @@ -89,11 +150,52 @@ "@babel/helper-validator-identifier" "^7.25.9" "@babel/traverse" "^7.25.9" -"@babel/helper-plugin-utils@^7.25.9": +"@babel/helper-optimise-call-expression@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.25.9.tgz#3324ae50bae7e2ab3c33f60c9a877b6a0146b54e" + integrity sha512-FIpuNaz5ow8VyrYcnXQTDRGvV6tTjkNtCK/RYNDXGSLlUD6cBuQTSw43CShGxjvfBTfcUA/r6UhUCbtYqkhcuQ== + dependencies: + "@babel/types" "^7.25.9" + +"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.22.5", "@babel/helper-plugin-utils@^7.25.9", "@babel/helper-plugin-utils@^7.8.0": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.25.9.tgz#9cbdd63a9443a2c92a725cca7ebca12cc8dd9f46" integrity sha512-kSMlyUVdWe25rEsRGviIgOWnoT/nfABVWlqt9N19/dIPWViAOW2s9wznP5tURbs/IDuNk4gPy3YdYRgH3uxhBw== +"@babel/helper-remap-async-to-generator@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.25.9.tgz#e53956ab3d5b9fb88be04b3e2f31b523afd34b92" + integrity sha512-IZtukuUeBbhgOcaW2s06OXTzVNJR0ybm4W5xC1opWFFJMZbwRj5LCk+ByYH7WdZPZTt8KnFwA8pvjN2yqcPlgw== + dependencies: + "@babel/helper-annotate-as-pure" "^7.25.9" + "@babel/helper-wrap-function" "^7.25.9" + "@babel/traverse" "^7.25.9" + +"@babel/helper-replace-supers@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.25.9.tgz#ba447224798c3da3f8713fc272b145e33da6a5c5" + integrity sha512-IiDqTOTBQy0sWyeXyGSC5TBJpGFXBkRynjBeXsvbhQFKj2viwJC76Epz35YLU1fpe/Am6Vppb7W7zM4fPQzLsQ== + dependencies: + "@babel/helper-member-expression-to-functions" "^7.25.9" + "@babel/helper-optimise-call-expression" "^7.25.9" + "@babel/traverse" "^7.25.9" + +"@babel/helper-simple-access@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.25.9.tgz#6d51783299884a2c74618d6ef0f86820ec2e7739" + integrity sha512-c6WHXuiaRsJTyHYLJV75t9IqsmTbItYfdj99PnzYGQZkYKvan5/2jKJ7gu31J3/BJ/A18grImSPModuyG/Eo0Q== + dependencies: + "@babel/traverse" "^7.25.9" + "@babel/types" "^7.25.9" + +"@babel/helper-skip-transparent-expression-wrappers@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.25.9.tgz#0b2e1b62d560d6b1954893fd2b705dc17c91f0c9" + integrity sha512-K4Du3BFa3gvyhzgPcntrkDgZzQaq6uozzcpGbOO1OEJaI+EJdqWIMTLgFgQf6lrfiDFo5FU+BxKepI9RmZqahA== + dependencies: + "@babel/traverse" "^7.25.9" + "@babel/types" "^7.25.9" + "@babel/helper-string-parser@^7.25.9": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz#1aabb72ee72ed35789b4bbcad3ca2862ce614e8c" @@ -109,6 +211,15 @@ resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz#86e45bd8a49ab7e03f276577f96179653d41da72" integrity sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw== +"@babel/helper-wrap-function@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.25.9.tgz#d99dfd595312e6c894bd7d237470025c85eea9d0" + integrity sha512-ETzz9UTjQSTmw39GboatdymDq4XIQbR8ySgVrylRhPOFpsd+JrKHIuF0de7GCWmem+T4uC5z7EZguod7Wj4A4g== + dependencies: + "@babel/template" "^7.25.9" + "@babel/traverse" "^7.25.9" + "@babel/types" "^7.25.9" + "@babel/helpers@^7.26.0": version "7.26.0" resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.26.0.tgz#30e621f1eba5aa45fe6f4868d2e9154d884119a4" @@ -124,6 +235,413 @@ dependencies: "@babel/types" "^7.26.0" +"@babel/plugin-bugfix-firefox-class-in-computed-class-key@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.25.9.tgz#cc2e53ebf0a0340777fff5ed521943e253b4d8fe" + integrity sha512-ZkRyVkThtxQ/J6nv3JFYv1RYY+JT5BvU0y3k5bWrmuG4woXypRa4PXmm9RhOwodRkYFWqC0C0cqcJ4OqR7kW+g== + dependencies: + "@babel/helper-plugin-utils" "^7.25.9" + "@babel/traverse" "^7.25.9" + +"@babel/plugin-bugfix-safari-class-field-initializer-scope@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.25.9.tgz#af9e4fb63ccb8abcb92375b2fcfe36b60c774d30" + integrity sha512-MrGRLZxLD/Zjj0gdU15dfs+HH/OXvnw/U4jJD8vpcP2CJQapPEv1IWwjc/qMg7ItBlPwSv1hRBbb7LeuANdcnw== + dependencies: + "@babel/helper-plugin-utils" "^7.25.9" + +"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.25.9.tgz#e8dc26fcd616e6c5bf2bd0d5a2c151d4f92a9137" + integrity sha512-2qUwwfAFpJLZqxd02YW9btUCZHl+RFvdDkNfZwaIJrvB8Tesjsk8pEQkTvGwZXLqXUx/2oyY3ySRhm6HOXuCug== + dependencies: + "@babel/helper-plugin-utils" "^7.25.9" + +"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.25.9.tgz#807a667f9158acac6f6164b4beb85ad9ebc9e1d1" + integrity sha512-6xWgLZTJXwilVjlnV7ospI3xi+sl8lN8rXXbBD6vYn3UYDlGsag8wrZkKcSI8G6KgqKP7vNFaDgeDnfAABq61g== + dependencies: + "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-skip-transparent-expression-wrappers" "^7.25.9" + "@babel/plugin-transform-optional-chaining" "^7.25.9" + +"@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.25.9.tgz#de7093f1e7deaf68eadd7cc6b07f2ab82543269e" + integrity sha512-aLnMXYPnzwwqhYSCyXfKkIkYgJ8zv9RK+roo9DkTXz38ynIhd9XCbN08s3MGvqL2MYGVUGdRQLL/JqBIeJhJBg== + dependencies: + "@babel/helper-plugin-utils" "^7.25.9" + "@babel/traverse" "^7.25.9" + +"@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2": + version "7.21.0-placeholder-for-preset-env.2" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz#7844f9289546efa9febac2de4cfe358a050bd703" + integrity sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w== + +"@babel/plugin-syntax-bigint@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz#4c9a6f669f5d0cdf1b90a1671e9a146be5300cea" + integrity sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-dynamic-import@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz#62bf98b2da3cd21d626154fc96ee5b3cb68eacb3" + integrity sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-import-assertions@^7.24.1", "@babel/plugin-syntax-import-assertions@^7.26.0": + version "7.26.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.26.0.tgz#620412405058efa56e4a564903b79355020f445f" + integrity sha512-QCWT5Hh830hK5EQa7XzuqIkQU9tT/whqbDz7kuaZMHFl1inRRg7JnuAEOQ0Ur0QUl0NufCk1msK2BeY79Aj/eg== + dependencies: + "@babel/helper-plugin-utils" "^7.25.9" + +"@babel/plugin-syntax-import-attributes@^7.26.0": + version "7.26.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.26.0.tgz#3b1412847699eea739b4f2602c74ce36f6b0b0f7" + integrity sha512-e2dttdsJ1ZTpi3B9UYGLw41hifAubg19AtCu/2I/F1QNVclOBr1dYpTdmdyZ84Xiz43BS/tCUkMAZNLv12Pi+A== + dependencies: + "@babel/helper-plugin-utils" "^7.25.9" + +"@babel/plugin-syntax-jsx@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.25.9.tgz#a34313a178ea56f1951599b929c1ceacee719290" + integrity sha512-ld6oezHQMZsZfp6pWtbjaNDF2tiiCYYDqQszHt5VV437lewP9aSi2Of99CK0D0XB21k7FLgnLcmQKyKzynfeAA== + dependencies: + "@babel/helper-plugin-utils" "^7.25.9" + +"@babel/plugin-syntax-typescript@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.25.9.tgz#67dda2b74da43727cf21d46cf9afef23f4365399" + integrity sha512-hjMgRy5hb8uJJjUcdWunWVcoi9bGpJp8p5Ol1229PoN6aytsLwNMgmdftO23wnCLMfVmTwZDWMPNq/D1SY60JQ== + dependencies: + "@babel/helper-plugin-utils" "^7.25.9" + +"@babel/plugin-syntax-unicode-sets-regex@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz#d49a3b3e6b52e5be6740022317580234a6a47357" + integrity sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-arrow-functions@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.25.9.tgz#7821d4410bee5daaadbb4cdd9a6649704e176845" + integrity sha512-6jmooXYIwn9ca5/RylZADJ+EnSxVUS5sjeJ9UPk6RWRzXCmOJCy6dqItPJFpw2cuCangPK4OYr5uhGKcmrm5Qg== + dependencies: + "@babel/helper-plugin-utils" "^7.25.9" + +"@babel/plugin-transform-async-generator-functions@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.25.9.tgz#1b18530b077d18a407c494eb3d1d72da505283a2" + integrity sha512-RXV6QAzTBbhDMO9fWwOmwwTuYaiPbggWQ9INdZqAYeSHyG7FzQ+nOZaUUjNwKv9pV3aE4WFqFm1Hnbci5tBCAw== + dependencies: + "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-remap-async-to-generator" "^7.25.9" + "@babel/traverse" "^7.25.9" + +"@babel/plugin-transform-async-to-generator@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.25.9.tgz#c80008dacae51482793e5a9c08b39a5be7e12d71" + integrity sha512-NT7Ejn7Z/LjUH0Gv5KsBCxh7BH3fbLTV0ptHvpeMvrt3cPThHfJfst9Wrb7S8EvJ7vRTFI7z+VAvFVEQn/m5zQ== + dependencies: + "@babel/helper-module-imports" "^7.25.9" + "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-remap-async-to-generator" "^7.25.9" + +"@babel/plugin-transform-block-scoped-functions@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.25.9.tgz#5700691dbd7abb93de300ca7be94203764fce458" + integrity sha512-toHc9fzab0ZfenFpsyYinOX0J/5dgJVA2fm64xPewu7CoYHWEivIWKxkK2rMi4r3yQqLnVmheMXRdG+k239CgA== + dependencies: + "@babel/helper-plugin-utils" "^7.25.9" + +"@babel/plugin-transform-block-scoping@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.25.9.tgz#c33665e46b06759c93687ca0f84395b80c0473a1" + integrity sha512-1F05O7AYjymAtqbsFETboN1NvBdcnzMerO+zlMyJBEz6WkMdejvGWw9p05iTSjC85RLlBseHHQpYaM4gzJkBGg== + dependencies: + "@babel/helper-plugin-utils" "^7.25.9" + +"@babel/plugin-transform-class-properties@^7.24.1", "@babel/plugin-transform-class-properties@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.25.9.tgz#a8ce84fedb9ad512549984101fa84080a9f5f51f" + integrity sha512-bbMAII8GRSkcd0h0b4X+36GksxuheLFjP65ul9w6C3KgAamI3JqErNgSrosX6ZPj+Mpim5VvEbawXxJCyEUV3Q== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.25.9" + "@babel/helper-plugin-utils" "^7.25.9" + +"@babel/plugin-transform-class-static-block@^7.26.0": + version "7.26.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.26.0.tgz#6c8da219f4eb15cae9834ec4348ff8e9e09664a0" + integrity sha512-6J2APTs7BDDm+UMqP1useWqhcRAXo0WIoVj26N7kPFB6S73Lgvyka4KTZYIxtgYXiN5HTyRObA72N2iu628iTQ== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.25.9" + "@babel/helper-plugin-utils" "^7.25.9" + +"@babel/plugin-transform-classes@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.25.9.tgz#7152457f7880b593a63ade8a861e6e26a4469f52" + integrity sha512-mD8APIXmseE7oZvZgGABDyM34GUmK45Um2TXiBUt7PnuAxrgoSVf123qUzPxEr/+/BHrRn5NMZCdE2m/1F8DGg== + dependencies: + "@babel/helper-annotate-as-pure" "^7.25.9" + "@babel/helper-compilation-targets" "^7.25.9" + "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-replace-supers" "^7.25.9" + "@babel/traverse" "^7.25.9" + globals "^11.1.0" + +"@babel/plugin-transform-computed-properties@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.25.9.tgz#db36492c78460e534b8852b1d5befe3c923ef10b" + integrity sha512-HnBegGqXZR12xbcTHlJ9HGxw1OniltT26J5YpfruGqtUHlz/xKf/G2ak9e+t0rVqrjXa9WOhvYPz1ERfMj23AA== + dependencies: + "@babel/helper-plugin-utils" "^7.25.9" + "@babel/template" "^7.25.9" + +"@babel/plugin-transform-destructuring@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.25.9.tgz#966ea2595c498224340883602d3cfd7a0c79cea1" + integrity sha512-WkCGb/3ZxXepmMiX101nnGiU+1CAdut8oHyEOHxkKuS1qKpU2SMXE2uSvfz8PBuLd49V6LEsbtyPhWC7fnkgvQ== + dependencies: + "@babel/helper-plugin-utils" "^7.25.9" + +"@babel/plugin-transform-dotall-regex@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.25.9.tgz#bad7945dd07734ca52fe3ad4e872b40ed09bb09a" + integrity sha512-t7ZQ7g5trIgSRYhI9pIJtRl64KHotutUJsh4Eze5l7olJv+mRSg4/MmbZ0tv1eeqRbdvo/+trvJD/Oc5DmW2cA== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.25.9" + "@babel/helper-plugin-utils" "^7.25.9" + +"@babel/plugin-transform-duplicate-keys@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.25.9.tgz#8850ddf57dce2aebb4394bb434a7598031059e6d" + integrity sha512-LZxhJ6dvBb/f3x8xwWIuyiAHy56nrRG3PeYTpBkkzkYRRQ6tJLu68lEF5VIqMUZiAV7a8+Tb78nEoMCMcqjXBw== + dependencies: + "@babel/helper-plugin-utils" "^7.25.9" + +"@babel/plugin-transform-duplicate-named-capturing-groups-regex@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.25.9.tgz#6f7259b4de127721a08f1e5165b852fcaa696d31" + integrity sha512-0UfuJS0EsXbRvKnwcLjFtJy/Sxc5J5jhLHnFhy7u4zih97Hz6tJkLU+O+FMMrNZrosUPxDi6sYxJ/EA8jDiAog== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.25.9" + "@babel/helper-plugin-utils" "^7.25.9" + +"@babel/plugin-transform-dynamic-import@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.25.9.tgz#23e917de63ed23c6600c5dd06d94669dce79f7b8" + integrity sha512-GCggjexbmSLaFhqsojeugBpeaRIgWNTcgKVq/0qIteFEqY2A+b9QidYadrWlnbWQUrW5fn+mCvf3tr7OeBFTyg== + dependencies: + "@babel/helper-plugin-utils" "^7.25.9" + +"@babel/plugin-transform-exponentiation-operator@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.25.9.tgz#ece47b70d236c1d99c263a1e22b62dc20a4c8b0f" + integrity sha512-KRhdhlVk2nObA5AYa7QMgTMTVJdfHprfpAk4DjZVtllqRg9qarilstTKEhpVjyt+Npi8ThRyiV8176Am3CodPA== + dependencies: + "@babel/helper-builder-binary-assignment-operator-visitor" "^7.25.9" + "@babel/helper-plugin-utils" "^7.25.9" + +"@babel/plugin-transform-export-namespace-from@^7.24.1", "@babel/plugin-transform-export-namespace-from@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.25.9.tgz#90745fe55053394f554e40584cda81f2c8a402a2" + integrity sha512-2NsEz+CxzJIVOPx2o9UsW1rXLqtChtLoVnwYHHiB04wS5sgn7mrV45fWMBX0Kk+ub9uXytVYfNP2HjbVbCB3Ww== + dependencies: + "@babel/helper-plugin-utils" "^7.25.9" + +"@babel/plugin-transform-for-of@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.25.9.tgz#4bdc7d42a213397905d89f02350c5267866d5755" + integrity sha512-LqHxduHoaGELJl2uhImHwRQudhCM50pT46rIBNvtT/Oql3nqiS3wOwP+5ten7NpYSXrrVLgtZU3DZmPtWZo16A== + dependencies: + "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-skip-transparent-expression-wrappers" "^7.25.9" + +"@babel/plugin-transform-function-name@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.25.9.tgz#939d956e68a606661005bfd550c4fc2ef95f7b97" + integrity sha512-8lP+Yxjv14Vc5MuWBpJsoUCd3hD6V9DgBon2FVYL4jJgbnVQ9fTgYmonchzZJOVNgzEgbxp4OwAf6xz6M/14XA== + dependencies: + "@babel/helper-compilation-targets" "^7.25.9" + "@babel/helper-plugin-utils" "^7.25.9" + "@babel/traverse" "^7.25.9" + +"@babel/plugin-transform-json-strings@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.25.9.tgz#c86db407cb827cded902a90c707d2781aaa89660" + integrity sha512-xoTMk0WXceiiIvsaquQQUaLLXSW1KJ159KP87VilruQm0LNNGxWzahxSS6T6i4Zg3ezp4vA4zuwiNUR53qmQAw== + dependencies: + "@babel/helper-plugin-utils" "^7.25.9" + +"@babel/plugin-transform-literals@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.25.9.tgz#1a1c6b4d4aa59bc4cad5b6b3a223a0abd685c9de" + integrity sha512-9N7+2lFziW8W9pBl2TzaNht3+pgMIRP74zizeCSrtnSKVdUl8mAjjOP2OOVQAfZ881P2cNjDj1uAMEdeD50nuQ== + dependencies: + "@babel/helper-plugin-utils" "^7.25.9" + +"@babel/plugin-transform-logical-assignment-operators@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.25.9.tgz#b19441a8c39a2fda0902900b306ea05ae1055db7" + integrity sha512-wI4wRAzGko551Y8eVf6iOY9EouIDTtPb0ByZx+ktDGHwv6bHFimrgJM/2T021txPZ2s4c7bqvHbd+vXG6K948Q== + dependencies: + "@babel/helper-plugin-utils" "^7.25.9" + +"@babel/plugin-transform-member-expression-literals@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.25.9.tgz#63dff19763ea64a31f5e6c20957e6a25e41ed5de" + integrity sha512-PYazBVfofCQkkMzh2P6IdIUaCEWni3iYEerAsRWuVd8+jlM1S9S9cz1dF9hIzyoZ8IA3+OwVYIp9v9e+GbgZhA== + dependencies: + "@babel/helper-plugin-utils" "^7.25.9" + +"@babel/plugin-transform-modules-amd@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.25.9.tgz#49ba478f2295101544abd794486cd3088dddb6c5" + integrity sha512-g5T11tnI36jVClQlMlt4qKDLlWnG5pP9CSM4GhdRciTNMRgkfpo5cR6b4rGIOYPgRRuFAvwjPQ/Yk+ql4dyhbw== + dependencies: + "@babel/helper-module-transforms" "^7.25.9" + "@babel/helper-plugin-utils" "^7.25.9" + +"@babel/plugin-transform-modules-commonjs@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.25.9.tgz#d165c8c569a080baf5467bda88df6425fc060686" + integrity sha512-dwh2Ol1jWwL2MgkCzUSOvfmKElqQcuswAZypBSUsScMXvgdT8Ekq5YA6TtqpTVWH+4903NmboMuH1o9i8Rxlyg== + dependencies: + "@babel/helper-module-transforms" "^7.25.9" + "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-simple-access" "^7.25.9" + +"@babel/plugin-transform-modules-systemjs@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.25.9.tgz#8bd1b43836269e3d33307151a114bcf3ba6793f8" + integrity sha512-hyss7iIlH/zLHaehT+xwiymtPOpsiwIIRlCAOwBB04ta5Tt+lNItADdlXw3jAWZ96VJ2jlhl/c+PNIQPKNfvcA== + dependencies: + "@babel/helper-module-transforms" "^7.25.9" + "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-validator-identifier" "^7.25.9" + "@babel/traverse" "^7.25.9" + +"@babel/plugin-transform-modules-umd@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.25.9.tgz#6710079cdd7c694db36529a1e8411e49fcbf14c9" + integrity sha512-bS9MVObUgE7ww36HEfwe6g9WakQ0KF07mQF74uuXdkoziUPfKyu/nIm663kz//e5O1nPInPFx36z7WJmJ4yNEw== + dependencies: + "@babel/helper-module-transforms" "^7.25.9" + "@babel/helper-plugin-utils" "^7.25.9" + +"@babel/plugin-transform-named-capturing-groups-regex@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.25.9.tgz#454990ae6cc22fd2a0fa60b3a2c6f63a38064e6a" + integrity sha512-oqB6WHdKTGl3q/ItQhpLSnWWOpjUJLsOCLVyeFgeTktkBSCiurvPOsyt93gibI9CmuKvTUEtWmG5VhZD+5T/KA== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.25.9" + "@babel/helper-plugin-utils" "^7.25.9" + +"@babel/plugin-transform-new-target@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.25.9.tgz#42e61711294b105c248336dcb04b77054ea8becd" + integrity sha512-U/3p8X1yCSoKyUj2eOBIx3FOn6pElFOKvAAGf8HTtItuPyB+ZeOqfn+mvTtg9ZlOAjsPdK3ayQEjqHjU/yLeVQ== + dependencies: + "@babel/helper-plugin-utils" "^7.25.9" + +"@babel/plugin-transform-nullish-coalescing-operator@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.25.9.tgz#bcb1b0d9e948168102d5f7104375ca21c3266949" + integrity sha512-ENfftpLZw5EItALAD4WsY/KUWvhUlZndm5GC7G3evUsVeSJB6p0pBeLQUnRnBCBx7zV0RKQjR9kCuwrsIrjWog== + dependencies: + "@babel/helper-plugin-utils" "^7.25.9" + +"@babel/plugin-transform-numeric-separator@^7.24.1", "@babel/plugin-transform-numeric-separator@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.25.9.tgz#bfed75866261a8b643468b0ccfd275f2033214a1" + integrity sha512-TlprrJ1GBZ3r6s96Yq8gEQv82s8/5HnCVHtEJScUj90thHQbwe+E5MLhi2bbNHBEJuzrvltXSru+BUxHDoog7Q== + dependencies: + "@babel/helper-plugin-utils" "^7.25.9" + +"@babel/plugin-transform-object-rest-spread@^7.24.1", "@babel/plugin-transform-object-rest-spread@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.25.9.tgz#0203725025074164808bcf1a2cfa90c652c99f18" + integrity sha512-fSaXafEE9CVHPweLYw4J0emp1t8zYTXyzN3UuG+lylqkvYd7RMrsOQ8TYx5RF231be0vqtFC6jnx3UmpJmKBYg== + dependencies: + "@babel/helper-compilation-targets" "^7.25.9" + "@babel/helper-plugin-utils" "^7.25.9" + "@babel/plugin-transform-parameters" "^7.25.9" + +"@babel/plugin-transform-object-super@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.25.9.tgz#385d5de135162933beb4a3d227a2b7e52bb4cf03" + integrity sha512-Kj/Gh+Rw2RNLbCK1VAWj2U48yxxqL2x0k10nPtSdRa0O2xnHXalD0s+o1A6a0W43gJ00ANo38jxkQreckOzv5A== + dependencies: + "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-replace-supers" "^7.25.9" + +"@babel/plugin-transform-optional-catch-binding@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.25.9.tgz#10e70d96d52bb1f10c5caaac59ac545ea2ba7ff3" + integrity sha512-qM/6m6hQZzDcZF3onzIhZeDHDO43bkNNlOX0i8n3lR6zLbu0GN2d8qfM/IERJZYauhAHSLHy39NF0Ctdvcid7g== + dependencies: + "@babel/helper-plugin-utils" "^7.25.9" + +"@babel/plugin-transform-optional-chaining@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.25.9.tgz#e142eb899d26ef715435f201ab6e139541eee7dd" + integrity sha512-6AvV0FsLULbpnXeBjrY4dmWF8F7gf8QnvTEoO/wX/5xm/xE1Xo8oPuD3MPS+KS9f9XBEAWN7X1aWr4z9HdOr7A== + dependencies: + "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-skip-transparent-expression-wrappers" "^7.25.9" + +"@babel/plugin-transform-parameters@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.25.9.tgz#b856842205b3e77e18b7a7a1b94958069c7ba257" + integrity sha512-wzz6MKwpnshBAiRmn4jR8LYz/g8Ksg0o80XmwZDlordjwEk9SxBzTWC7F5ef1jhbrbOW2DJ5J6ayRukrJmnr0g== + dependencies: + "@babel/helper-plugin-utils" "^7.25.9" + +"@babel/plugin-transform-private-methods@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.25.9.tgz#847f4139263577526455d7d3223cd8bda51e3b57" + integrity sha512-D/JUozNpQLAPUVusvqMxyvjzllRaF8/nSrP1s2YGQT/W4LHK4xxsMcHjhOGTS01mp9Hda8nswb+FblLdJornQw== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.25.9" + "@babel/helper-plugin-utils" "^7.25.9" + +"@babel/plugin-transform-private-property-in-object@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.25.9.tgz#9c8b73e64e6cc3cbb2743633885a7dd2c385fe33" + integrity sha512-Evf3kcMqzXA3xfYJmZ9Pg1OvKdtqsDMSWBDzZOPLvHiTt36E75jLDQo5w1gtRU95Q4E5PDttrTf25Fw8d/uWLw== + dependencies: + "@babel/helper-annotate-as-pure" "^7.25.9" + "@babel/helper-create-class-features-plugin" "^7.25.9" + "@babel/helper-plugin-utils" "^7.25.9" + +"@babel/plugin-transform-property-literals@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.25.9.tgz#d72d588bd88b0dec8b62e36f6fda91cedfe28e3f" + integrity sha512-IvIUeV5KrS/VPavfSM/Iu+RE6llrHrYIKY1yfCzyO/lMXHQ+p7uGhonmGVisv6tSBSVgWzMBohTcvkC9vQcQFA== + dependencies: + "@babel/helper-plugin-utils" "^7.25.9" + +"@babel/plugin-transform-react-display-name@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.25.9.tgz#4b79746b59efa1f38c8695065a92a9f5afb24f7d" + integrity sha512-KJfMlYIUxQB1CJfO3e0+h0ZHWOTLCPP115Awhaz8U0Zpq36Gl/cXlpoyMRnUWlhNUBAzldnCiAZNvCDj7CrKxQ== + dependencies: + "@babel/helper-plugin-utils" "^7.25.9" + +"@babel/plugin-transform-react-jsx-development@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.25.9.tgz#8fd220a77dd139c07e25225a903b8be8c829e0d7" + integrity sha512-9mj6rm7XVYs4mdLIpbZnHOYdpW42uoiBCTVowg7sP1thUOiANgMb4UtpRivR0pp5iL+ocvUv7X4mZgFRpJEzGw== + dependencies: + "@babel/plugin-transform-react-jsx" "^7.25.9" + "@babel/plugin-transform-react-jsx-self@^7.24.7": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.25.9.tgz#c0b6cae9c1b73967f7f9eb2fca9536ba2fad2858" @@ -138,7 +656,246 @@ dependencies: "@babel/helper-plugin-utils" "^7.25.9" -"@babel/runtime@^7.12.5", "@babel/runtime@^7.23.2", "@babel/runtime@^7.25.0": +"@babel/plugin-transform-react-jsx@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.25.9.tgz#06367940d8325b36edff5e2b9cbe782947ca4166" + integrity sha512-s5XwpQYCqGerXl+Pu6VDL3x0j2d82eiV77UJ8a2mDHAW7j9SWRqQ2y1fNo1Z74CdcYipl5Z41zvjj4Nfzq36rw== + dependencies: + "@babel/helper-annotate-as-pure" "^7.25.9" + "@babel/helper-module-imports" "^7.25.9" + "@babel/helper-plugin-utils" "^7.25.9" + "@babel/plugin-syntax-jsx" "^7.25.9" + "@babel/types" "^7.25.9" + +"@babel/plugin-transform-react-pure-annotations@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.25.9.tgz#ea1c11b2f9dbb8e2d97025f43a3b5bc47e18ae62" + integrity sha512-KQ/Takk3T8Qzj5TppkS1be588lkbTp5uj7w6a0LeQaTMSckU/wK0oJ/pih+T690tkgI5jfmg2TqDJvd41Sj1Cg== + dependencies: + "@babel/helper-annotate-as-pure" "^7.25.9" + "@babel/helper-plugin-utils" "^7.25.9" + +"@babel/plugin-transform-regenerator@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.25.9.tgz#03a8a4670d6cebae95305ac6defac81ece77740b" + integrity sha512-vwDcDNsgMPDGP0nMqzahDWE5/MLcX8sv96+wfX7as7LoF/kr97Bo/7fI00lXY4wUXYfVmwIIyG80fGZ1uvt2qg== + dependencies: + "@babel/helper-plugin-utils" "^7.25.9" + regenerator-transform "^0.15.2" + +"@babel/plugin-transform-regexp-modifiers@^7.26.0": + version "7.26.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regexp-modifiers/-/plugin-transform-regexp-modifiers-7.26.0.tgz#2f5837a5b5cd3842a919d8147e9903cc7455b850" + integrity sha512-vN6saax7lrA2yA/Pak3sCxuD6F5InBjn9IcrIKQPjpsLvuHYLVroTxjdlVRHjjBWxKOqIwpTXDkOssYT4BFdRw== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.25.9" + "@babel/helper-plugin-utils" "^7.25.9" + +"@babel/plugin-transform-reserved-words@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.25.9.tgz#0398aed2f1f10ba3f78a93db219b27ef417fb9ce" + integrity sha512-7DL7DKYjn5Su++4RXu8puKZm2XBPHyjWLUidaPEkCUBbE7IPcsrkRHggAOOKydH1dASWdcUBxrkOGNxUv5P3Jg== + dependencies: + "@babel/helper-plugin-utils" "^7.25.9" + +"@babel/plugin-transform-runtime@^7.24.3": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.25.9.tgz#62723ea3f5b31ffbe676da9d6dae17138ae580ea" + integrity sha512-nZp7GlEl+yULJrClz0SwHPqir3lc0zsPrDHQUcxGspSL7AKrexNSEfTbfqnDNJUO13bgKyfuOLMF8Xqtu8j3YQ== + dependencies: + "@babel/helper-module-imports" "^7.25.9" + "@babel/helper-plugin-utils" "^7.25.9" + babel-plugin-polyfill-corejs2 "^0.4.10" + babel-plugin-polyfill-corejs3 "^0.10.6" + babel-plugin-polyfill-regenerator "^0.6.1" + semver "^6.3.1" + +"@babel/plugin-transform-shorthand-properties@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.25.9.tgz#bb785e6091f99f826a95f9894fc16fde61c163f2" + integrity sha512-MUv6t0FhO5qHnS/W8XCbHmiRWOphNufpE1IVxhK5kuN3Td9FT1x4rx4K42s3RYdMXCXpfWkGSbCSd0Z64xA7Ng== + dependencies: + "@babel/helper-plugin-utils" "^7.25.9" + +"@babel/plugin-transform-spread@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.25.9.tgz#24a35153931b4ba3d13cec4a7748c21ab5514ef9" + integrity sha512-oNknIB0TbURU5pqJFVbOOFspVlrpVwo2H1+HUIsVDvp5VauGGDP1ZEvO8Nn5xyMEs3dakajOxlmkNW7kNgSm6A== + dependencies: + "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-skip-transparent-expression-wrappers" "^7.25.9" + +"@babel/plugin-transform-sticky-regex@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.25.9.tgz#c7f02b944e986a417817b20ba2c504dfc1453d32" + integrity sha512-WqBUSgeVwucYDP9U/xNRQam7xV8W5Zf+6Eo7T2SRVUFlhRiMNFdFz58u0KZmCVVqs2i7SHgpRnAhzRNmKfi2uA== + dependencies: + "@babel/helper-plugin-utils" "^7.25.9" + +"@babel/plugin-transform-template-literals@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.25.9.tgz#6dbd4a24e8fad024df76d1fac6a03cf413f60fe1" + integrity sha512-o97AE4syN71M/lxrCtQByzphAdlYluKPDBzDVzMmfCobUjjhAryZV0AIpRPrxN0eAkxXO6ZLEScmt+PNhj2OTw== + dependencies: + "@babel/helper-plugin-utils" "^7.25.9" + +"@babel/plugin-transform-typeof-symbol@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.25.9.tgz#224ba48a92869ddbf81f9b4a5f1204bbf5a2bc4b" + integrity sha512-v61XqUMiueJROUv66BVIOi0Fv/CUuZuZMl5NkRoCVxLAnMexZ0A3kMe7vvZ0nulxMuMp0Mk6S5hNh48yki08ZA== + dependencies: + "@babel/helper-plugin-utils" "^7.25.9" + +"@babel/plugin-transform-typescript@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.25.9.tgz#69267905c2b33c2ac6d8fe765e9dc2ddc9df3849" + integrity sha512-7PbZQZP50tzv2KGGnhh82GSyMB01yKY9scIjf1a+GfZCtInOWqUH5+1EBU4t9fyR5Oykkkc9vFTs4OHrhHXljQ== + dependencies: + "@babel/helper-annotate-as-pure" "^7.25.9" + "@babel/helper-create-class-features-plugin" "^7.25.9" + "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-skip-transparent-expression-wrappers" "^7.25.9" + "@babel/plugin-syntax-typescript" "^7.25.9" + +"@babel/plugin-transform-unicode-escapes@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.25.9.tgz#a75ef3947ce15363fccaa38e2dd9bc70b2788b82" + integrity sha512-s5EDrE6bW97LtxOcGj1Khcx5AaXwiMmi4toFWRDP9/y0Woo6pXC+iyPu/KuhKtfSrNFd7jJB+/fkOtZy6aIC6Q== + dependencies: + "@babel/helper-plugin-utils" "^7.25.9" + +"@babel/plugin-transform-unicode-property-regex@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.25.9.tgz#a901e96f2c1d071b0d1bb5dc0d3c880ce8f53dd3" + integrity sha512-Jt2d8Ga+QwRluxRQ307Vlxa6dMrYEMZCgGxoPR8V52rxPyldHu3hdlHspxaqYmE7oID5+kB+UKUB/eWS+DkkWg== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.25.9" + "@babel/helper-plugin-utils" "^7.25.9" + +"@babel/plugin-transform-unicode-regex@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.25.9.tgz#5eae747fe39eacf13a8bd006a4fb0b5d1fa5e9b1" + integrity sha512-yoxstj7Rg9dlNn9UQxzk4fcNivwv4nUYz7fYXBaKxvw/lnmPuOm/ikoELygbYq68Bls3D/D+NBPHiLwZdZZ4HA== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.25.9" + "@babel/helper-plugin-utils" "^7.25.9" + +"@babel/plugin-transform-unicode-sets-regex@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.25.9.tgz#65114c17b4ffc20fa5b163c63c70c0d25621fabe" + integrity sha512-8BYqO3GeVNHtx69fdPshN3fnzUNLrWdHhk/icSwigksJGczKSizZ+Z6SBCxTs723Fr5VSNorTIK7a+R2tISvwQ== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.25.9" + "@babel/helper-plugin-utils" "^7.25.9" + +"@babel/preset-env@^7.24.4": + version "7.26.0" + resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.26.0.tgz#30e5c6bc1bcc54865bff0c5a30f6d4ccdc7fa8b1" + integrity sha512-H84Fxq0CQJNdPFT2DrfnylZ3cf5K43rGfWK4LJGPpjKHiZlk0/RzwEus3PDDZZg+/Er7lCA03MVacueUuXdzfw== + dependencies: + "@babel/compat-data" "^7.26.0" + "@babel/helper-compilation-targets" "^7.25.9" + "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-validator-option" "^7.25.9" + "@babel/plugin-bugfix-firefox-class-in-computed-class-key" "^7.25.9" + "@babel/plugin-bugfix-safari-class-field-initializer-scope" "^7.25.9" + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression" "^7.25.9" + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining" "^7.25.9" + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly" "^7.25.9" + "@babel/plugin-proposal-private-property-in-object" "7.21.0-placeholder-for-preset-env.2" + "@babel/plugin-syntax-import-assertions" "^7.26.0" + "@babel/plugin-syntax-import-attributes" "^7.26.0" + "@babel/plugin-syntax-unicode-sets-regex" "^7.18.6" + "@babel/plugin-transform-arrow-functions" "^7.25.9" + "@babel/plugin-transform-async-generator-functions" "^7.25.9" + "@babel/plugin-transform-async-to-generator" "^7.25.9" + "@babel/plugin-transform-block-scoped-functions" "^7.25.9" + "@babel/plugin-transform-block-scoping" "^7.25.9" + "@babel/plugin-transform-class-properties" "^7.25.9" + "@babel/plugin-transform-class-static-block" "^7.26.0" + "@babel/plugin-transform-classes" "^7.25.9" + "@babel/plugin-transform-computed-properties" "^7.25.9" + "@babel/plugin-transform-destructuring" "^7.25.9" + "@babel/plugin-transform-dotall-regex" "^7.25.9" + "@babel/plugin-transform-duplicate-keys" "^7.25.9" + "@babel/plugin-transform-duplicate-named-capturing-groups-regex" "^7.25.9" + "@babel/plugin-transform-dynamic-import" "^7.25.9" + "@babel/plugin-transform-exponentiation-operator" "^7.25.9" + "@babel/plugin-transform-export-namespace-from" "^7.25.9" + "@babel/plugin-transform-for-of" "^7.25.9" + "@babel/plugin-transform-function-name" "^7.25.9" + "@babel/plugin-transform-json-strings" "^7.25.9" + "@babel/plugin-transform-literals" "^7.25.9" + "@babel/plugin-transform-logical-assignment-operators" "^7.25.9" + "@babel/plugin-transform-member-expression-literals" "^7.25.9" + "@babel/plugin-transform-modules-amd" "^7.25.9" + "@babel/plugin-transform-modules-commonjs" "^7.25.9" + "@babel/plugin-transform-modules-systemjs" "^7.25.9" + "@babel/plugin-transform-modules-umd" "^7.25.9" + "@babel/plugin-transform-named-capturing-groups-regex" "^7.25.9" + "@babel/plugin-transform-new-target" "^7.25.9" + "@babel/plugin-transform-nullish-coalescing-operator" "^7.25.9" + "@babel/plugin-transform-numeric-separator" "^7.25.9" + "@babel/plugin-transform-object-rest-spread" "^7.25.9" + "@babel/plugin-transform-object-super" "^7.25.9" + "@babel/plugin-transform-optional-catch-binding" "^7.25.9" + "@babel/plugin-transform-optional-chaining" "^7.25.9" + "@babel/plugin-transform-parameters" "^7.25.9" + "@babel/plugin-transform-private-methods" "^7.25.9" + "@babel/plugin-transform-private-property-in-object" "^7.25.9" + "@babel/plugin-transform-property-literals" "^7.25.9" + "@babel/plugin-transform-regenerator" "^7.25.9" + "@babel/plugin-transform-regexp-modifiers" "^7.26.0" + "@babel/plugin-transform-reserved-words" "^7.25.9" + "@babel/plugin-transform-shorthand-properties" "^7.25.9" + "@babel/plugin-transform-spread" "^7.25.9" + "@babel/plugin-transform-sticky-regex" "^7.25.9" + "@babel/plugin-transform-template-literals" "^7.25.9" + "@babel/plugin-transform-typeof-symbol" "^7.25.9" + "@babel/plugin-transform-unicode-escapes" "^7.25.9" + "@babel/plugin-transform-unicode-property-regex" "^7.25.9" + "@babel/plugin-transform-unicode-regex" "^7.25.9" + "@babel/plugin-transform-unicode-sets-regex" "^7.25.9" + "@babel/preset-modules" "0.1.6-no-external-plugins" + babel-plugin-polyfill-corejs2 "^0.4.10" + babel-plugin-polyfill-corejs3 "^0.10.6" + babel-plugin-polyfill-regenerator "^0.6.1" + core-js-compat "^3.38.1" + semver "^6.3.1" + +"@babel/preset-modules@0.1.6-no-external-plugins": + version "0.1.6-no-external-plugins" + resolved "https://registry.yarnpkg.com/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz#ccb88a2c49c817236861fee7826080573b8a923a" + integrity sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/types" "^7.4.4" + esutils "^2.0.2" + +"@babel/preset-react@^7.24.1": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.25.9.tgz#5f473035dc2094bcfdbc7392d0766bd42dce173e" + integrity sha512-D3to0uSPiWE7rBrdIICCd0tJSIGpLaaGptna2+w7Pft5xMqLpA1sz99DK5TZ1TjGbdQ/VI1eCSZ06dv3lT4JOw== + dependencies: + "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-validator-option" "^7.25.9" + "@babel/plugin-transform-react-display-name" "^7.25.9" + "@babel/plugin-transform-react-jsx" "^7.25.9" + "@babel/plugin-transform-react-jsx-development" "^7.25.9" + "@babel/plugin-transform-react-pure-annotations" "^7.25.9" + +"@babel/preset-typescript@^7.24.1": + version "7.26.0" + resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.26.0.tgz#4a570f1b8d104a242d923957ffa1eaff142a106d" + integrity sha512-NMk1IGZ5I/oHhoXEElcm+xUnL/szL6xflkFZmoEU9xj1qSJXpiS7rsspYo92B4DRCDvZn2erT5LdsCeXAKNCkg== + dependencies: + "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-validator-option" "^7.25.9" + "@babel/plugin-syntax-jsx" "^7.25.9" + "@babel/plugin-transform-modules-commonjs" "^7.25.9" + "@babel/plugin-transform-typescript" "^7.25.9" + +"@babel/runtime@^7.12.5", "@babel/runtime@^7.17.8", "@babel/runtime@^7.23.2", "@babel/runtime@^7.24.4", "@babel/runtime@^7.25.0", "@babel/runtime@^7.8.4": version "7.26.0" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.26.0.tgz#8600c2f595f277c60815256418b85356a65173c1" integrity sha512-FDSOghenHTiToteC/QRlv2q3DhPZ/oOXTBoirfWNx1Cx3TMVcGWQtMMmQcSvb/JjpNeGzx8Pq/b4fKEJuWm1sw== @@ -154,7 +911,7 @@ "@babel/parser" "^7.25.9" "@babel/types" "^7.25.9" -"@babel/traverse@^7.25.9": +"@babel/traverse@^7.18.9", "@babel/traverse@^7.25.9": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.25.9.tgz#a50f8fe49e7f69f53de5bea7e413cd35c5e13c84" integrity sha512-ZCuvfwOwlz/bawvAuvcj8rrithP2/N55Tzz342AkTvq4qaWbGfmCk/tKhNaV2cthijKrPAA8SRJV5WWe7IBMJw== @@ -167,7 +924,7 @@ debug "^4.3.1" globals "^11.1.0" -"@babel/types@^7.0.0", "@babel/types@^7.20.7", "@babel/types@^7.25.9", "@babel/types@^7.26.0": +"@babel/types@^7.0.0", "@babel/types@^7.18.9", "@babel/types@^7.20.7", "@babel/types@^7.25.9", "@babel/types@^7.26.0", "@babel/types@^7.4.4": version "7.26.0" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.26.0.tgz#deabd08d6b753bc8e0f198f8709fb575e31774ff" integrity sha512-Z/yiTPj+lDVnF7lWeKCIJzaIkI0vYO87dMpZ4bg4TDrFe4XXLFWL1TbXU27gBP3QccxV9mZICCrnjnYlJjXHOA== @@ -175,6 +932,17 @@ "@babel/helper-string-parser" "^7.25.9" "@babel/helper-validator-identifier" "^7.25.9" +"@chromatic-com/storybook@^3.2.2": + version "3.2.2" + resolved "https://registry.yarnpkg.com/@chromatic-com/storybook/-/storybook-3.2.2.tgz#08754443de55618f802f88450c35266fd6d25db5" + integrity sha512-xmXt/GW0hAPbzNTrxYuVo43Adrtjue4DeVrsoIIEeJdGaPNNeNf+DHMlJKOBdlHmCnFUoe9R/0mLM9zUp5bKWw== + dependencies: + chromatic "^11.15.0" + filesize "^10.0.12" + jsonfile "^6.1.0" + react-confetti "^6.1.0" + strip-ansi "^7.1.0" + "@emnapi/runtime@^1.2.0": version "1.3.1" resolved "https://registry.yarnpkg.com/@emnapi/runtime/-/runtime-1.3.1.tgz#0fcaa575afc31f455fd33534c19381cfce6c6f60" @@ -187,116 +955,236 @@ resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz#c7184a326533fcdf1b8ee0733e21c713b975575f" integrity sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ== +"@esbuild/aix-ppc64@0.24.0": + version "0.24.0" + resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.24.0.tgz#b57697945b50e99007b4c2521507dc613d4a648c" + integrity sha512-WtKdFM7ls47zkKHFVzMz8opM7LkcsIp9amDUBIAWirg70RM71WRSjdILPsY5Uv1D42ZpUfaPILDlfactHgsRkw== + "@esbuild/android-arm64@0.21.5": version "0.21.5" resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz#09d9b4357780da9ea3a7dfb833a1f1ff439b4052" integrity sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A== +"@esbuild/android-arm64@0.24.0": + version "0.24.0" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.24.0.tgz#1add7e0af67acefd556e407f8497e81fddad79c0" + integrity sha512-Vsm497xFM7tTIPYK9bNTYJyF/lsP590Qc1WxJdlB6ljCbdZKU9SY8i7+Iin4kyhV/KV5J2rOKsBQbB77Ab7L/w== + "@esbuild/android-arm@0.21.5": version "0.21.5" resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.21.5.tgz#9b04384fb771926dfa6d7ad04324ecb2ab9b2e28" integrity sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg== +"@esbuild/android-arm@0.24.0": + version "0.24.0" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.24.0.tgz#ab7263045fa8e090833a8e3c393b60d59a789810" + integrity sha512-arAtTPo76fJ/ICkXWetLCc9EwEHKaeya4vMrReVlEIUCAUncH7M4bhMQ+M9Vf+FFOZJdTNMXNBrWwW+OXWpSew== + "@esbuild/android-x64@0.21.5": version "0.21.5" resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.21.5.tgz#29918ec2db754cedcb6c1b04de8cd6547af6461e" integrity sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA== +"@esbuild/android-x64@0.24.0": + version "0.24.0" + resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.24.0.tgz#e8f8b196cfdfdd5aeaebbdb0110983460440e705" + integrity sha512-t8GrvnFkiIY7pa7mMgJd7p8p8qqYIz1NYiAoKc75Zyv73L3DZW++oYMSHPRarcotTKuSs6m3hTOa5CKHaS02TQ== + "@esbuild/darwin-arm64@0.21.5": version "0.21.5" resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz#e495b539660e51690f3928af50a76fb0a6ccff2a" integrity sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ== +"@esbuild/darwin-arm64@0.24.0": + version "0.24.0" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.24.0.tgz#2d0d9414f2acbffd2d86e98253914fca603a53dd" + integrity sha512-CKyDpRbK1hXwv79soeTJNHb5EiG6ct3efd/FTPdzOWdbZZfGhpbcqIpiD0+vwmpu0wTIL97ZRPZu8vUt46nBSw== + "@esbuild/darwin-x64@0.21.5": version "0.21.5" resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz#c13838fa57372839abdddc91d71542ceea2e1e22" integrity sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw== +"@esbuild/darwin-x64@0.24.0": + version "0.24.0" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.24.0.tgz#33087aab31a1eb64c89daf3d2cf8ce1775656107" + integrity sha512-rgtz6flkVkh58od4PwTRqxbKH9cOjaXCMZgWD905JOzjFKW+7EiUObfd/Kav+A6Gyud6WZk9w+xu6QLytdi2OA== + "@esbuild/freebsd-arm64@0.21.5": version "0.21.5" resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz#646b989aa20bf89fd071dd5dbfad69a3542e550e" integrity sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g== +"@esbuild/freebsd-arm64@0.24.0": + version "0.24.0" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.24.0.tgz#bb76e5ea9e97fa3c753472f19421075d3a33e8a7" + integrity sha512-6Mtdq5nHggwfDNLAHkPlyLBpE5L6hwsuXZX8XNmHno9JuL2+bg2BX5tRkwjyfn6sKbxZTq68suOjgWqCicvPXA== + "@esbuild/freebsd-x64@0.21.5": version "0.21.5" resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz#aa615cfc80af954d3458906e38ca22c18cf5c261" integrity sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ== +"@esbuild/freebsd-x64@0.24.0": + version "0.24.0" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.24.0.tgz#e0e2ce9249fdf6ee29e5dc3d420c7007fa579b93" + integrity sha512-D3H+xh3/zphoX8ck4S2RxKR6gHlHDXXzOf6f/9dbFt/NRBDIE33+cVa49Kil4WUjxMGW0ZIYBYtaGCa2+OsQwQ== + "@esbuild/linux-arm64@0.21.5": version "0.21.5" resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz#70ac6fa14f5cb7e1f7f887bcffb680ad09922b5b" integrity sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q== +"@esbuild/linux-arm64@0.24.0": + version "0.24.0" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.24.0.tgz#d1b2aa58085f73ecf45533c07c82d81235388e75" + integrity sha512-TDijPXTOeE3eaMkRYpcy3LarIg13dS9wWHRdwYRnzlwlA370rNdZqbcp0WTyyV/k2zSxfko52+C7jU5F9Tfj1g== + "@esbuild/linux-arm@0.21.5": version "0.21.5" resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz#fc6fd11a8aca56c1f6f3894f2bea0479f8f626b9" integrity sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA== +"@esbuild/linux-arm@0.24.0": + version "0.24.0" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.24.0.tgz#8e4915df8ea3e12b690a057e77a47b1d5935ef6d" + integrity sha512-gJKIi2IjRo5G6Glxb8d3DzYXlxdEj2NlkixPsqePSZMhLudqPhtZ4BUrpIuTjJYXxvF9njql+vRjB2oaC9XpBw== + "@esbuild/linux-ia32@0.21.5": version "0.21.5" resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz#3271f53b3f93e3d093d518d1649d6d68d346ede2" integrity sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg== +"@esbuild/linux-ia32@0.24.0": + version "0.24.0" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.24.0.tgz#8200b1110666c39ab316572324b7af63d82013fb" + integrity sha512-K40ip1LAcA0byL05TbCQ4yJ4swvnbzHscRmUilrmP9Am7//0UjPreh4lpYzvThT2Quw66MhjG//20mrufm40mA== + "@esbuild/linux-loong64@0.21.5": version "0.21.5" resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz#ed62e04238c57026aea831c5a130b73c0f9f26df" integrity sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg== +"@esbuild/linux-loong64@0.24.0": + version "0.24.0" + resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.24.0.tgz#6ff0c99cf647504df321d0640f0d32e557da745c" + integrity sha512-0mswrYP/9ai+CU0BzBfPMZ8RVm3RGAN/lmOMgW4aFUSOQBjA31UP8Mr6DDhWSuMwj7jaWOT0p0WoZ6jeHhrD7g== + "@esbuild/linux-mips64el@0.21.5": version "0.21.5" resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz#e79b8eb48bf3b106fadec1ac8240fb97b4e64cbe" integrity sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg== +"@esbuild/linux-mips64el@0.24.0": + version "0.24.0" + resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.24.0.tgz#3f720ccd4d59bfeb4c2ce276a46b77ad380fa1f3" + integrity sha512-hIKvXm0/3w/5+RDtCJeXqMZGkI2s4oMUGj3/jM0QzhgIASWrGO5/RlzAzm5nNh/awHE0A19h/CvHQe6FaBNrRA== + "@esbuild/linux-ppc64@0.21.5": version "0.21.5" resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz#5f2203860a143b9919d383ef7573521fb154c3e4" integrity sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w== +"@esbuild/linux-ppc64@0.24.0": + version "0.24.0" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.24.0.tgz#9d6b188b15c25afd2e213474bf5f31e42e3aa09e" + integrity sha512-HcZh5BNq0aC52UoocJxaKORfFODWXZxtBaaZNuN3PUX3MoDsChsZqopzi5UupRhPHSEHotoiptqikjN/B77mYQ== + "@esbuild/linux-riscv64@0.21.5": version "0.21.5" resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz#07bcafd99322d5af62f618cb9e6a9b7f4bb825dc" integrity sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA== +"@esbuild/linux-riscv64@0.24.0": + version "0.24.0" + resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.24.0.tgz#f989fdc9752dfda286c9cd87c46248e4dfecbc25" + integrity sha512-bEh7dMn/h3QxeR2KTy1DUszQjUrIHPZKyO6aN1X4BCnhfYhuQqedHaa5MxSQA/06j3GpiIlFGSsy1c7Gf9padw== + "@esbuild/linux-s390x@0.21.5": version "0.21.5" resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz#b7ccf686751d6a3e44b8627ababc8be3ef62d8de" integrity sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A== +"@esbuild/linux-s390x@0.24.0": + version "0.24.0" + resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.24.0.tgz#29ebf87e4132ea659c1489fce63cd8509d1c7319" + integrity sha512-ZcQ6+qRkw1UcZGPyrCiHHkmBaj9SiCD8Oqd556HldP+QlpUIe2Wgn3ehQGVoPOvZvtHm8HPx+bH20c9pvbkX3g== + "@esbuild/linux-x64@0.21.5": version "0.21.5" resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz#6d8f0c768e070e64309af8004bb94e68ab2bb3b0" integrity sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ== +"@esbuild/linux-x64@0.24.0": + version "0.24.0" + resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.24.0.tgz#4af48c5c0479569b1f359ffbce22d15f261c0cef" + integrity sha512-vbutsFqQ+foy3wSSbmjBXXIJ6PL3scghJoM8zCL142cGaZKAdCZHyf+Bpu/MmX9zT9Q0zFBVKb36Ma5Fzfa8xA== + "@esbuild/netbsd-x64@0.21.5": version "0.21.5" resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz#bbe430f60d378ecb88decb219c602667387a6047" integrity sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg== +"@esbuild/netbsd-x64@0.24.0": + version "0.24.0" + resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.24.0.tgz#1ae73d23cc044a0ebd4f198334416fb26c31366c" + integrity sha512-hjQ0R/ulkO8fCYFsG0FZoH+pWgTTDreqpqY7UnQntnaKv95uP5iW3+dChxnx7C3trQQU40S+OgWhUVwCjVFLvg== + +"@esbuild/openbsd-arm64@0.24.0": + version "0.24.0" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.24.0.tgz#5d904a4f5158c89859fd902c427f96d6a9e632e2" + integrity sha512-MD9uzzkPQbYehwcN583yx3Tu5M8EIoTD+tUgKF982WYL9Pf5rKy9ltgD0eUgs8pvKnmizxjXZyLt0z6DC3rRXg== + "@esbuild/openbsd-x64@0.21.5": version "0.21.5" resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz#99d1cf2937279560d2104821f5ccce220cb2af70" integrity sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow== +"@esbuild/openbsd-x64@0.24.0": + version "0.24.0" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.24.0.tgz#4c8aa88c49187c601bae2971e71c6dc5e0ad1cdf" + integrity sha512-4ir0aY1NGUhIC1hdoCzr1+5b43mw99uNwVzhIq1OY3QcEwPDO3B7WNXBzaKY5Nsf1+N11i1eOfFcq+D/gOS15Q== + "@esbuild/sunos-x64@0.21.5": version "0.21.5" resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz#08741512c10d529566baba837b4fe052c8f3487b" integrity sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg== +"@esbuild/sunos-x64@0.24.0": + version "0.24.0" + resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.24.0.tgz#8ddc35a0ea38575fa44eda30a5ee01ae2fa54dd4" + integrity sha512-jVzdzsbM5xrotH+W5f1s+JtUy1UWgjU0Cf4wMvffTB8m6wP5/kx0KiaLHlbJO+dMgtxKV8RQ/JvtlFcdZ1zCPA== + "@esbuild/win32-arm64@0.21.5": version "0.21.5" resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz#675b7385398411240735016144ab2e99a60fc75d" integrity sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A== +"@esbuild/win32-arm64@0.24.0": + version "0.24.0" + resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.24.0.tgz#6e79c8543f282c4539db684a207ae0e174a9007b" + integrity sha512-iKc8GAslzRpBytO2/aN3d2yb2z8XTVfNV0PjGlCxKo5SgWmNXx82I/Q3aG1tFfS+A2igVCY97TJ8tnYwpUWLCA== + "@esbuild/win32-ia32@0.21.5": version "0.21.5" resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz#1bfc3ce98aa6ca9a0969e4d2af72144c59c1193b" integrity sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA== +"@esbuild/win32-ia32@0.24.0": + version "0.24.0" + resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.24.0.tgz#057af345da256b7192d18b676a02e95d0fa39103" + integrity sha512-vQW36KZolfIudCcTnaTpmLQ24Ha1RjygBo39/aLkM2kmjkWmZGEJ5Gn9l5/7tzXA42QGIoWbICfg6KLLkIw6yw== + "@esbuild/win32-x64@0.21.5": version "0.21.5" resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz#acad351d582d157bb145535db2a6ff53dd514b5c" integrity sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw== +"@esbuild/win32-x64@0.24.0": + version "0.24.0" + resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.24.0.tgz#168ab1c7e1c318b922637fad8f339d48b01e1244" + integrity sha512-7IAFPrjSQIJrGsK6flwg7NFmwBoSTyF3rl7If0hNUFQU4ilTsEPL6GuMuU9BfIWVVGuRnuIidkSMC+c0Otu8IA== + "@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0": version "4.4.1" resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz#d1145bf2c20132d6400495d6df4bf59362fd9d56" @@ -509,12 +1397,20 @@ resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.2.1.tgz#558fb6472ed16a4c850b889530e6b36438c49280" integrity sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A== +"@jridgewell/source-map@^0.3.3": + version "0.3.6" + resolved "https://registry.yarnpkg.com/@jridgewell/source-map/-/source-map-0.3.6.tgz#9d71ca886e32502eb9362c9a74a46787c36df81a" + integrity sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ== + dependencies: + "@jridgewell/gen-mapping" "^0.3.5" + "@jridgewell/trace-mapping" "^0.3.25" + "@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14", "@jridgewell/sourcemap-codec@^1.5.0": version "1.5.0" resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz#3188bcb273a414b0d215fd22a58540b989b9409a" integrity sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ== -"@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.25": +"@jridgewell/trace-mapping@^0.3.20", "@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.25": version "0.3.25" resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz#15f190e98895f3fc23276ee14bc76b675c2e50f0" integrity sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ== @@ -537,6 +1433,13 @@ semver "^7.3.5" tar "^6.1.11" +"@mdx-js/react@^3.0.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@mdx-js/react/-/react-3.1.0.tgz#c4522e335b3897b9a845db1dbdd2f966ae8fb0ed" + integrity sha512-QjHtSaoameoalGnKDT3FoIl4+9RwyTmo9ZJGBdLOks/YOiWHoRDI3PUwEzOE7kEmGcV3AFcp9K6dYu9rEuKLAQ== + dependencies: + "@types/mdx" "^2.0.0" + "@next/env@15.0.2": version "15.0.2" resolved "https://registry.yarnpkg.com/@next/env/-/env-15.0.2.tgz#4e921af3faf8a16c6be98ec6a81a32a40050a8b7" @@ -625,6 +1528,19 @@ resolved "https://registry.yarnpkg.com/@pkgr/core/-/core-0.1.1.tgz#1ec17e2edbec25c8306d424ecfbf13c7de1aaa31" integrity sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA== +"@pmmmwh/react-refresh-webpack-plugin@^0.5.11": + version "0.5.15" + resolved "https://registry.yarnpkg.com/@pmmmwh/react-refresh-webpack-plugin/-/react-refresh-webpack-plugin-0.5.15.tgz#f126be97c30b83ed777e2aeabd518bc592e6e7c4" + integrity sha512-LFWllMA55pzB9D34w/wXUCf8+c+IYKuJDgxiZ3qMhl64KRMBHYM1I3VdGaD2BV5FNPV2/S2596bppxHbv2ZydQ== + dependencies: + ansi-html "^0.0.9" + core-js-pure "^3.23.3" + error-stack-parser "^2.0.6" + html-entities "^2.1.0" + loader-utils "^2.0.4" + schema-utils "^4.2.0" + source-map "^0.7.3" + "@radix-ui/react-compose-refs@1.1.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.0.tgz#656432461fc8283d7b591dcf0d79152fae9ecc74" @@ -742,6 +1658,347 @@ resolved "https://registry.yarnpkg.com/@rushstack/eslint-patch/-/eslint-patch-1.10.4.tgz#427d5549943a9c6fce808e39ea64dbe60d4047f1" integrity sha512-WJgX9nzTqknM393q1QJDJmoW28kUfEnybeTfVNcNAPnIx210RXm2DiXiHzfNPJNIUUb1tJnz/l4QGtJ30PgWmA== +"@storybook/addon-actions@8.4.5": + version "8.4.5" + resolved "https://registry.yarnpkg.com/@storybook/addon-actions/-/addon-actions-8.4.5.tgz#9224f635c78240f611eb340ba9b4248986b4763c" + integrity sha512-rbB19uiGJ61XHbKIbS1a9bUS6re5L8rT5NMNeEJhCxXRpFUPrlTXMSoD/Pgcn3ENeEMVZsm8/eCzxAVgAP3Mgg== + dependencies: + "@storybook/global" "^5.0.0" + "@types/uuid" "^9.0.1" + dequal "^2.0.2" + polished "^4.2.2" + uuid "^9.0.0" + +"@storybook/addon-backgrounds@8.4.5": + version "8.4.5" + resolved "https://registry.yarnpkg.com/@storybook/addon-backgrounds/-/addon-backgrounds-8.4.5.tgz#3d93d24d0b8e77d6d5bad78bae4c8621ee27c5d1" + integrity sha512-FeMt4qHCMYDQiLGGDKiRuSPXFup2WXOaZSdL137v1W36wEL/vGkK1A5iQt1qJ8MZzL5WZQuedox8rSybFy7eow== + dependencies: + "@storybook/global" "^5.0.0" + memoizerific "^1.11.3" + ts-dedent "^2.0.0" + +"@storybook/addon-controls@8.4.5": + version "8.4.5" + resolved "https://registry.yarnpkg.com/@storybook/addon-controls/-/addon-controls-8.4.5.tgz#1f6ce4044ab093aabb79fcd6537a996f2d12597f" + integrity sha512-RVTtDDuESLYc1+SJQv2kI7wzBddzAS9uoEe8P75quN6S4pC0GxAB6xirWZ2+WOcba4eHosY+PxMwuBXQfH78Ew== + dependencies: + "@storybook/global" "^5.0.0" + dequal "^2.0.2" + ts-dedent "^2.0.0" + +"@storybook/addon-docs@8.4.5": + version "8.4.5" + resolved "https://registry.yarnpkg.com/@storybook/addon-docs/-/addon-docs-8.4.5.tgz#fa38b6c6c0ef1c8fc588b6913ddb55b67be55666" + integrity sha512-zPELIl7wXormOylVaaSpkUIuuCCxrO+OFPMKZnlENt6zSReyy0dJu4V0tzfV8FCw+V4D6Y4wrLRk/TIG951Ojw== + dependencies: + "@mdx-js/react" "^3.0.0" + "@storybook/blocks" "8.4.5" + "@storybook/csf-plugin" "8.4.5" + "@storybook/react-dom-shim" "8.4.5" + react "^16.8.0 || ^17.0.0 || ^18.0.0" + react-dom "^16.8.0 || ^17.0.0 || ^18.0.0" + ts-dedent "^2.0.0" + +"@storybook/addon-essentials@^8.4.5": + version "8.4.5" + resolved "https://registry.yarnpkg.com/@storybook/addon-essentials/-/addon-essentials-8.4.5.tgz#7ff4f71b4435f734936272a691a830a34eaaef49" + integrity sha512-AxetQo/zSPIu3RZqWG2opwAz22Bb+jpf1nWbHp0kEpCrBemcWd8X2gonVmXNOC1PDKNl3jcWyc3lmg/+3mxjYg== + dependencies: + "@storybook/addon-actions" "8.4.5" + "@storybook/addon-backgrounds" "8.4.5" + "@storybook/addon-controls" "8.4.5" + "@storybook/addon-docs" "8.4.5" + "@storybook/addon-highlight" "8.4.5" + "@storybook/addon-measure" "8.4.5" + "@storybook/addon-outline" "8.4.5" + "@storybook/addon-toolbars" "8.4.5" + "@storybook/addon-viewport" "8.4.5" + ts-dedent "^2.0.0" + +"@storybook/addon-highlight@8.4.5": + version "8.4.5" + resolved "https://registry.yarnpkg.com/@storybook/addon-highlight/-/addon-highlight-8.4.5.tgz#44c194f88395a6e221744867a11f39ea8910d290" + integrity sha512-sMA7v+4unaKY+5RDhow6lLncJqNX9ZLUnBIt3vzY1ntUsOYVwykAY1Hq4Ysj0luCBXjJJdJ6223ylrycnb7Ilw== + dependencies: + "@storybook/global" "^5.0.0" + +"@storybook/addon-interactions@^8.4.5": + version "8.4.5" + resolved "https://registry.yarnpkg.com/@storybook/addon-interactions/-/addon-interactions-8.4.5.tgz#0053207da50a4cefc9dce46b7980cd54a828c2ff" + integrity sha512-s6R8XVD8LTp+LQTDbhtDjDLE6S44I7FtMLxPdMNwN9VEJjBk01NONLDuGDpNq5o/0bnybA3rMHk9+3afsgzidQ== + dependencies: + "@storybook/global" "^5.0.0" + "@storybook/instrumenter" "8.4.5" + "@storybook/test" "8.4.5" + polished "^4.2.2" + ts-dedent "^2.2.0" + +"@storybook/addon-measure@8.4.5": + version "8.4.5" + resolved "https://registry.yarnpkg.com/@storybook/addon-measure/-/addon-measure-8.4.5.tgz#9b22ea0f28740f0c9c1edee2642de2b75415abdd" + integrity sha512-+sNjew991YaoXQyWWloFybjEGrDO40Jk6w8BgZs2X7oc3D5t/6oFzvyC862U++LGqKFA3quXDeBjEb92CI9cRA== + dependencies: + "@storybook/global" "^5.0.0" + tiny-invariant "^1.3.1" + +"@storybook/addon-onboarding@^8.4.5": + version "8.4.5" + resolved "https://registry.yarnpkg.com/@storybook/addon-onboarding/-/addon-onboarding-8.4.5.tgz#731ac4a27711dff565dec9b4090fb49ab752d7b9" + integrity sha512-+FW50yVw2NMxYvk3uMpIberfkG4Sn0qRpiMse7MGHgTimtaJ0Mo1AUIrSfyIJCVTuxiWZud1a5DAnH0ybbWjjA== + dependencies: + react-confetti "^6.1.0" + +"@storybook/addon-outline@8.4.5": + version "8.4.5" + resolved "https://registry.yarnpkg.com/@storybook/addon-outline/-/addon-outline-8.4.5.tgz#32d0a798b7c5abacbe2576125f589c8d4bcd5bcc" + integrity sha512-XlpN98AUDnWQWNFSFVm+HkRUzm3xIUMjBGTkv6HsL6zt6XoJ+LsQMca+PPtYqlBJA+5CU41xMDaG8HC/p+sd3A== + dependencies: + "@storybook/global" "^5.0.0" + ts-dedent "^2.0.0" + +"@storybook/addon-toolbars@8.4.5": + version "8.4.5" + resolved "https://registry.yarnpkg.com/@storybook/addon-toolbars/-/addon-toolbars-8.4.5.tgz#ebe20f0577a3e399858ba591066dbc8ac9636a5c" + integrity sha512-hOq5560ONOU/qrslrwosWzxnC4nrF8HZWD43ciKwtethm8HuptU2M+Jrui1CRsMScEZLopWWVE9o0vJMdKpIFQ== + +"@storybook/addon-viewport@8.4.5": + version "8.4.5" + resolved "https://registry.yarnpkg.com/@storybook/addon-viewport/-/addon-viewport-8.4.5.tgz#21a8b6d49f31cdca72018e9cd3adffbc435fa61a" + integrity sha512-l7Y41gIbJAsIN/QCg1QJ9sr61FLz1C/imUotcDej41tOHxUTSQOlXpNtVnfhUM1vGQc0yNpP3pVxj8BpXi0cAw== + dependencies: + memoizerific "^1.11.3" + +"@storybook/blocks@8.4.5", "@storybook/blocks@^8.4.5": + version "8.4.5" + resolved "https://registry.yarnpkg.com/@storybook/blocks/-/blocks-8.4.5.tgz#9494d9ccddc04bacd6a7a6c67cf870b72bf4ce9d" + integrity sha512-Z+LHauSqm3A4HBR9pUEf9KQhD3/3xYMt0FXgA+GHCAyDa6lFeD1C6r9Y2nlT+9dt8gv9B9oygTZvV6GqFVyRSQ== + dependencies: + "@storybook/csf" "^0.1.11" + "@storybook/icons" "^1.2.12" + ts-dedent "^2.0.0" + +"@storybook/builder-webpack5@8.4.5": + version "8.4.5" + resolved "https://registry.yarnpkg.com/@storybook/builder-webpack5/-/builder-webpack5-8.4.5.tgz#f2c15eb2219dc21bc6b0f4a5f83afd8c80561bff" + integrity sha512-5TSpirK2LIL4Wultpowlkrv3iAje57HTw92Hy6c4Zn64tAs30123mkdE6MoJcXMBfD4JwX9I2K2Q+ofZXblJPg== + dependencies: + "@storybook/core-webpack" "8.4.5" + "@types/node" "^22.0.0" + "@types/semver" "^7.3.4" + browser-assert "^1.2.1" + case-sensitive-paths-webpack-plugin "^2.4.0" + cjs-module-lexer "^1.2.3" + constants-browserify "^1.0.0" + css-loader "^6.7.1" + es-module-lexer "^1.5.0" + fork-ts-checker-webpack-plugin "^8.0.0" + html-webpack-plugin "^5.5.0" + magic-string "^0.30.5" + path-browserify "^1.0.1" + process "^0.11.10" + semver "^7.3.7" + style-loader "^3.3.1" + terser-webpack-plugin "^5.3.1" + ts-dedent "^2.0.0" + url "^0.11.0" + util "^0.12.4" + util-deprecate "^1.0.2" + webpack "5" + webpack-dev-middleware "^6.1.2" + webpack-hot-middleware "^2.25.1" + webpack-virtual-modules "^0.6.0" + +"@storybook/components@8.4.5", "@storybook/components@^8.0.0": + version "8.4.5" + resolved "https://registry.yarnpkg.com/@storybook/components/-/components-8.4.5.tgz#039e4cb5090c56c47fc10f0c5ecda77f4b015c7f" + integrity sha512-2PdnKfqNNv3sO7qILgWXiNvmLOi503oN9OMemNCQjTIvdvySc5JpS9/eClwcl/JfmE4qHdSHZr8dLLkBM9S7+Q== + +"@storybook/core-events@^8.0.0": + version "8.4.5" + resolved "https://registry.yarnpkg.com/@storybook/core-events/-/core-events-8.4.5.tgz#b2847bdbeb964019a9d134a311511b7d227e1682" + integrity sha512-+DeYpAuav9E/Q5x5BVrMpf+XBFbVQJuJbVXNiglZcJNH13D/G2WDToOYAbGviZ6CBvbUdjlqC7y9+/emwP78bA== + +"@storybook/core-webpack@8.4.5": + version "8.4.5" + resolved "https://registry.yarnpkg.com/@storybook/core-webpack/-/core-webpack-8.4.5.tgz#b17422cff80c638e3478406193acedb9be2d50cb" + integrity sha512-IpK/3fM+l2WjRNplTtP+MtnRf/394GcBwyemZknUCzFFDJWNYAN1+meEZmOaZKzJ3tQyRYiErrJLHzd1+UH6Dw== + dependencies: + "@types/node" "^22.0.0" + ts-dedent "^2.0.0" + +"@storybook/core@8.4.5": + version "8.4.5" + resolved "https://registry.yarnpkg.com/@storybook/core/-/core-8.4.5.tgz#4133927a43834664777f0918caf32542630cbdd5" + integrity sha512-aB1sQNX5nRoUAqg5u1py0MuR/VPd6c6PhECa4rW6pmr7kZcfyP4PP6UFpXuN71ypTQlkRE3Vc5PQZ3gLhE9o3g== + dependencies: + "@storybook/csf" "^0.1.11" + better-opn "^3.0.2" + browser-assert "^1.2.1" + esbuild "^0.18.0 || ^0.19.0 || ^0.20.0 || ^0.21.0 || ^0.22.0 || ^0.23.0 || ^0.24.0" + esbuild-register "^3.5.0" + jsdoc-type-pratt-parser "^4.0.0" + process "^0.11.10" + recast "^0.23.5" + semver "^7.6.2" + util "^0.12.5" + ws "^8.2.3" + +"@storybook/csf-plugin@8.4.5": + version "8.4.5" + resolved "https://registry.yarnpkg.com/@storybook/csf-plugin/-/csf-plugin-8.4.5.tgz#7f9ae0176e36cb74b1f638aac04dfec4aa04222f" + integrity sha512-qd2rQTglOTS+phQmTbNTXNjNyxdGvolaqHqDNMw3Vf6h9o3U+mLkwnDWNVnQ9oqvOoUEAqpBthgwzU9FhkIk+A== + dependencies: + unplugin "^1.3.1" + +"@storybook/csf@^0.1.11": + version "0.1.11" + resolved "https://registry.yarnpkg.com/@storybook/csf/-/csf-0.1.11.tgz#ad685a4fe564a47a6b73571c2e7c07b526f4f71b" + integrity sha512-dHYFQH3mA+EtnCkHXzicbLgsvzYjcDJ1JWsogbItZogkPHgSJM/Wr71uMkcvw8v9mmCyP4NpXJuu6bPoVsOnzg== + dependencies: + type-fest "^2.19.0" + +"@storybook/global@^5.0.0": + version "5.0.0" + resolved "https://registry.yarnpkg.com/@storybook/global/-/global-5.0.0.tgz#b793d34b94f572c1d7d9e0f44fac4e0dbc9572ed" + integrity sha512-FcOqPAXACP0I3oJ/ws6/rrPT9WGhu915Cg8D02a9YxLo0DE9zI+a9A5gRGvmQ09fiWPukqI8ZAEoQEdWUKMQdQ== + +"@storybook/icons@^1.2.12", "@storybook/icons@^1.2.5": + version "1.2.12" + resolved "https://registry.yarnpkg.com/@storybook/icons/-/icons-1.2.12.tgz#3e4c939113b67df7ab17b78f805dbb57f4acf0db" + integrity sha512-UxgyK5W3/UV4VrI3dl6ajGfHM4aOqMAkFLWe2KibeQudLf6NJpDrDMSHwZj+3iKC4jFU7dkKbbtH2h/al4sW3Q== + +"@storybook/instrumenter@8.4.5": + version "8.4.5" + resolved "https://registry.yarnpkg.com/@storybook/instrumenter/-/instrumenter-8.4.5.tgz#14983198b27dfbeedfef28992eef0d304b9f562b" + integrity sha512-8qM35FkueuRpJr0zA6ENvhQICbo+iKL1ln450DwV1kKJtc41KdbA3CuCvtZ/FnoPsFnwdtPjhhICFtRt8LRTSg== + dependencies: + "@storybook/global" "^5.0.0" + "@vitest/utils" "^2.1.1" + +"@storybook/manager-api@8.4.5", "@storybook/manager-api@^8.0.0": + version "8.4.5" + resolved "https://registry.yarnpkg.com/@storybook/manager-api/-/manager-api-8.4.5.tgz#ce586cc5961297272f7228446161015464c65067" + integrity sha512-t39JaMy3UX4StbUH/tIDcaflBDxTcyIq853wQtBMhVL3e1+Dw3MIiiG/5bw79HU4R7kSmPVLXIIbV3FmXkq7KQ== + +"@storybook/nextjs@^8.4.5": + version "8.4.5" + resolved "https://registry.yarnpkg.com/@storybook/nextjs/-/nextjs-8.4.5.tgz#f930db51ae06fb10ecd8b6d6af8177de5565b2e3" + integrity sha512-KhP9XVI20iwAvMFHqvlV0x5UqzvMbD42QjSW5/2KYy52CStnczfa/3Xyb2VBgAMQx3Ony0qnqlTVHi6qhJQtOA== + dependencies: + "@babel/core" "^7.24.4" + "@babel/plugin-syntax-bigint" "^7.8.3" + "@babel/plugin-syntax-dynamic-import" "^7.8.3" + "@babel/plugin-syntax-import-assertions" "^7.24.1" + "@babel/plugin-transform-class-properties" "^7.24.1" + "@babel/plugin-transform-export-namespace-from" "^7.24.1" + "@babel/plugin-transform-numeric-separator" "^7.24.1" + "@babel/plugin-transform-object-rest-spread" "^7.24.1" + "@babel/plugin-transform-runtime" "^7.24.3" + "@babel/preset-env" "^7.24.4" + "@babel/preset-react" "^7.24.1" + "@babel/preset-typescript" "^7.24.1" + "@babel/runtime" "^7.24.4" + "@pmmmwh/react-refresh-webpack-plugin" "^0.5.11" + "@storybook/builder-webpack5" "8.4.5" + "@storybook/preset-react-webpack" "8.4.5" + "@storybook/react" "8.4.5" + "@storybook/test" "8.4.5" + "@types/node" "^22.0.0" + "@types/semver" "^7.3.4" + babel-loader "^9.1.3" + css-loader "^6.7.3" + find-up "^5.0.0" + image-size "^1.0.0" + loader-utils "^3.2.1" + node-polyfill-webpack-plugin "^2.0.1" + pnp-webpack-plugin "^1.7.0" + postcss "^8.4.38" + postcss-loader "^8.1.1" + react-refresh "^0.14.0" + resolve-url-loader "^5.0.0" + sass-loader "^13.2.0" + semver "^7.3.5" + style-loader "^3.3.1" + styled-jsx "^5.1.6" + ts-dedent "^2.0.0" + tsconfig-paths "^4.0.0" + tsconfig-paths-webpack-plugin "^4.0.1" + optionalDependencies: + sharp "^0.33.3" + +"@storybook/preset-react-webpack@8.4.5": + version "8.4.5" + resolved "https://registry.yarnpkg.com/@storybook/preset-react-webpack/-/preset-react-webpack-8.4.5.tgz#da27afe7eaacaa17816608b1ccf225eb986965d8" + integrity sha512-BKPAN7G0yFXfojQdF8tvgwVJ0ldcl6+p1JtAPAieH69BMGni3TEPnvPhkefRWcM8oM8pl+Hch/J2PLHiZ6QKNQ== + dependencies: + "@storybook/core-webpack" "8.4.5" + "@storybook/react" "8.4.5" + "@storybook/react-docgen-typescript-plugin" "1.0.6--canary.9.0c3f3b7.0" + "@types/node" "^22.0.0" + "@types/semver" "^7.3.4" + find-up "^5.0.0" + magic-string "^0.30.5" + react-docgen "^7.0.0" + resolve "^1.22.8" + semver "^7.3.7" + tsconfig-paths "^4.2.0" + webpack "5" + +"@storybook/preview-api@8.4.5": + version "8.4.5" + resolved "https://registry.yarnpkg.com/@storybook/preview-api/-/preview-api-8.4.5.tgz#f8c046575c68062eda1de9494e7118571d20c72a" + integrity sha512-MKIZ2jQO/3cUdsT57eq8jRgB6inALo9BxrQ88f7mqzltOkMvADvTAY6y8JZqTUoDzWTH/ny/8SGGdtpqlxRuiQ== + +"@storybook/react-docgen-typescript-plugin@1.0.6--canary.9.0c3f3b7.0": + version "1.0.6--canary.9.0c3f3b7.0" + resolved "https://registry.yarnpkg.com/@storybook/react-docgen-typescript-plugin/-/react-docgen-typescript-plugin-1.0.6--canary.9.0c3f3b7.0.tgz#7f10f3c641f32e4513a8b6ffb5036933e7059534" + integrity sha512-KUqXC3oa9JuQ0kZJLBhVdS4lOneKTOopnNBK4tUAgoxWQ3u/IjzdueZjFr7gyBrXMoU6duutk3RQR9u8ZpYJ4Q== + dependencies: + debug "^4.1.1" + endent "^2.0.1" + find-cache-dir "^3.3.1" + flat-cache "^3.0.4" + micromatch "^4.0.2" + react-docgen-typescript "^2.2.2" + tslib "^2.0.0" + +"@storybook/react-dom-shim@8.4.5": + version "8.4.5" + resolved "https://registry.yarnpkg.com/@storybook/react-dom-shim/-/react-dom-shim-8.4.5.tgz#cc874d008a1def4410c32a95bcf9aac8defdb6f5" + integrity sha512-YTWTfPagptEYXJsnxAl3zP97Ev0zebtaEV0WgjGaEeumr+zsfgKKwzzHxgrtumBmDzwkuKlzFwlQB5A8keOIGA== + +"@storybook/react@8.4.5", "@storybook/react@^8.4.5": + version "8.4.5" + resolved "https://registry.yarnpkg.com/@storybook/react/-/react-8.4.5.tgz#9395ce8ffd4e27765459703c0634b306af882137" + integrity sha512-2+p4aGEdGOnu2XNhnMi1B8GPeszm34P905HgqGD1cuz9gMt7x/bgZQaVxs6kpHZ3Hb6V9qp62La2dbAYatHdSw== + dependencies: + "@storybook/components" "8.4.5" + "@storybook/global" "^5.0.0" + "@storybook/manager-api" "8.4.5" + "@storybook/preview-api" "8.4.5" + "@storybook/react-dom-shim" "8.4.5" + "@storybook/theming" "8.4.5" + +"@storybook/test@8.4.5", "@storybook/test@^8.4.5": + version "8.4.5" + resolved "https://registry.yarnpkg.com/@storybook/test/-/test-8.4.5.tgz#a22e8a4671c379f8ffc83a3997feb524bf5d9421" + integrity sha512-mHsRc6m60nfcEBsjvUkKz+Jnz0or4WH5jmJ1VL2pGKO4VzESCPqAwDnwDqP2YyeSQ0b/MAKUT5kdoLE2RE2eVw== + dependencies: + "@storybook/csf" "^0.1.11" + "@storybook/global" "^5.0.0" + "@storybook/instrumenter" "8.4.5" + "@testing-library/dom" "10.4.0" + "@testing-library/jest-dom" "6.5.0" + "@testing-library/user-event" "14.5.2" + "@vitest/expect" "2.0.5" + "@vitest/spy" "2.0.5" + +"@storybook/theming@8.4.5", "@storybook/theming@^8.0.0": + version "8.4.5" + resolved "https://registry.yarnpkg.com/@storybook/theming/-/theming-8.4.5.tgz#d7c77215f09906c9bb124d530d4307fd1841fbb8" + integrity sha512-45e/jeG4iuqdZcHg3PbB6dwXQTwlnnEB7r/QcVExyC7ibrkTnjUfvxzyUw4mmU3CXETFGD5EcUobFkgK+/aPxQ== + "@swc/counter@0.1.3": version "0.1.3" resolved "https://registry.yarnpkg.com/@swc/counter/-/counter-0.1.3.tgz#cc7463bd02949611c6329596fccd2b0ec782b0e9" @@ -754,7 +2011,7 @@ dependencies: tslib "^2.4.0" -"@testing-library/dom@^10.4.0": +"@testing-library/dom@10.4.0", "@testing-library/dom@^10.4.0": version "10.4.0" resolved "https://registry.yarnpkg.com/@testing-library/dom/-/dom-10.4.0.tgz#82a9d9462f11d240ecadbf406607c6ceeeff43a8" integrity sha512-pemlzrSESWbdAloYml3bAJMEfNh1Z7EduzqPKprCH5S341frlpYnUEW0H72dLxa6IsYr+mPno20GiSm+h9dEdQ== @@ -768,6 +2025,19 @@ lz-string "^1.5.0" pretty-format "^27.0.2" +"@testing-library/jest-dom@6.5.0": + version "6.5.0" + resolved "https://registry.yarnpkg.com/@testing-library/jest-dom/-/jest-dom-6.5.0.tgz#50484da3f80fb222a853479f618a9ce5c47bfe54" + integrity sha512-xGGHpBXYSHUUr6XsKBfs85TWlYKpTc37cSBBVrXcib2MkHLboWlkClhWF37JKlDb9KEq3dHs+f2xR7XJEWGBxA== + dependencies: + "@adobe/css-tools" "^4.4.0" + aria-query "^5.0.0" + chalk "^3.0.0" + css.escape "^1.5.1" + dom-accessibility-api "^0.6.3" + lodash "^4.17.21" + redent "^3.0.0" + "@testing-library/react@^16.0.1": version "16.0.1" resolved "https://registry.yarnpkg.com/@testing-library/react/-/react-16.0.1.tgz#29c0ee878d672703f5e7579f239005e4e0faa875" @@ -775,12 +2045,17 @@ dependencies: "@babel/runtime" "^7.12.5" +"@testing-library/user-event@14.5.2": + version "14.5.2" + resolved "https://registry.yarnpkg.com/@testing-library/user-event/-/user-event-14.5.2.tgz#db7257d727c891905947bd1c1a99da20e03c2ebd" + integrity sha512-YAh82Wh4TIrxYLmfGcixwD18oIjyC1pFQC2Y01F2lzV2HTMiYrI0nze0FD0ocB//CKS/7jIUgae+adPqxK5yCQ== + "@types/aria-query@^5.0.1": version "5.0.4" resolved "https://registry.yarnpkg.com/@types/aria-query/-/aria-query-5.0.4.tgz#1a31c3d378850d2778dabb6374d036dcba4ba708" integrity sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw== -"@types/babel__core@^7.20.5": +"@types/babel__core@^7.18.0", "@types/babel__core@^7.20.5": version "7.20.5" resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.20.5.tgz#3df15f27ba85319caa07ba08d0721889bb39c017" integrity sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA== @@ -806,7 +2081,7 @@ "@babel/parser" "^7.1.0" "@babel/types" "^7.0.0" -"@types/babel__traverse@*": +"@types/babel__traverse@*", "@types/babel__traverse@^7.18.0": version "7.20.6" resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.20.6.tgz#8dc9f0ae0f202c08d8d4dab648912c8d6038e3f7" integrity sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg== @@ -818,7 +2093,28 @@ resolved "https://registry.yarnpkg.com/@types/cookie/-/cookie-0.6.0.tgz#eac397f28bf1d6ae0ae081363eca2f425bedf0d5" integrity sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA== -"@types/estree@1.0.6", "@types/estree@^1.0.0": +"@types/doctrine@^0.0.9": + version "0.0.9" + resolved "https://registry.yarnpkg.com/@types/doctrine/-/doctrine-0.0.9.tgz#d86a5f452a15e3e3113b99e39616a9baa0f9863f" + integrity sha512-eOIHzCUSH7SMfonMG1LsC2f8vxBFtho6NGBznK41R84YzPuvSBzrhEps33IsQiOW9+VL6NQ9DbjQJznk/S4uRA== + +"@types/eslint-scope@^3.7.7": + version "3.7.7" + resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.7.tgz#3108bd5f18b0cdb277c867b3dd449c9ed7079ac5" + integrity sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg== + dependencies: + "@types/eslint" "*" + "@types/estree" "*" + +"@types/eslint@*": + version "9.6.1" + resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-9.6.1.tgz#d5795ad732ce81715f27f75da913004a56751584" + integrity sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag== + dependencies: + "@types/estree" "*" + "@types/json-schema" "*" + +"@types/estree@*", "@types/estree@1.0.6", "@types/estree@^1.0.0", "@types/estree@^1.0.6": version "1.0.6" resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.6.tgz#628effeeae2064a1b4e79f78e81d87b7e5fc7b50" integrity sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw== @@ -831,11 +2127,33 @@ "@types/react" "*" hoist-non-react-statics "^3.3.0" +"@types/html-minifier-terser@^6.0.0": + version "6.1.0" + resolved "https://registry.yarnpkg.com/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz#4fc33a00c1d0c16987b1a20cf92d20614c55ac35" + integrity sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg== + +"@types/json-schema@*", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9": + version "7.0.15" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" + integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== + "@types/json5@^0.0.29": version "0.0.29" resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ== +"@types/mdx@^2.0.0": + version "2.0.13" + resolved "https://registry.yarnpkg.com/@types/mdx/-/mdx-2.0.13.tgz#68f6877043d377092890ff5b298152b0a21671bd" + integrity sha512-+OWZQfAYyio6YkJb3HLxDrvnx6SWWDbC0zVPfBRzUk0/nqoDyf6dNxQi3eArPe8rJ473nobTMQ/8Zk+LxJ+Yuw== + +"@types/node@*", "@types/node@^22.0.0": + version "22.9.1" + resolved "https://registry.yarnpkg.com/@types/node/-/node-22.9.1.tgz#bdf91c36e0e7ecfb7257b2d75bf1b206b308ca71" + integrity sha512-p8Yy/8sw1caA8CdRIQBG5tiLHmxtQKObCijiAa9Ez+d4+PRffM4054xbju0msf+cvhJpnFEeNjxmVT/0ipktrg== + dependencies: + undici-types "~6.19.8" + "@types/node@^20": version "20.17.2" resolved "https://registry.yarnpkg.com/@types/node/-/node-20.17.2.tgz#3ca40ef7d776c85a1db3df23cbb5bfb3c384a92e" @@ -843,6 +2161,11 @@ dependencies: undici-types "~6.19.2" +"@types/parse-json@^4.0.0": + version "4.0.2" + resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.2.tgz#5950e50960793055845e956c427fc2b0d70c5239" + integrity sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw== + "@types/prop-types@*": version "15.7.13" resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.13.tgz#2af91918ee12d9d32914feb13f5326658461b451" @@ -863,6 +2186,21 @@ "@types/prop-types" "*" csstype "^3.0.2" +"@types/resolve@^1.20.2": + version "1.20.6" + resolved "https://registry.yarnpkg.com/@types/resolve/-/resolve-1.20.6.tgz#e6e60dad29c2c8c206c026e6dd8d6d1bdda850b8" + integrity sha512-A4STmOXPhMUtHH+S6ymgE2GiBSMqf4oTvcQZMcHzokuTLVYzXTB8ttjcgxOVaAp2lGwEdzZ0J+cRbbeevQj1UQ== + +"@types/semver@^7.3.4": + version "7.5.8" + resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.8.tgz#8268a8c57a3e4abd25c165ecd36237db7948a55e" + integrity sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ== + +"@types/uuid@^9.0.1": + version "9.0.8" + resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-9.0.8.tgz#7545ba4fc3c003d6c756f651f3bf163d8f0f29ba" + integrity sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA== + "@typescript-eslint/eslint-plugin@^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0": version "8.12.2" resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.12.2.tgz#c2ef660bb83fd1432368319312a2581fc92ccac1" @@ -897,6 +2235,14 @@ "@typescript-eslint/types" "8.12.2" "@typescript-eslint/visitor-keys" "8.12.2" +"@typescript-eslint/scope-manager@8.15.0": + version "8.15.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-8.15.0.tgz#28a1a0f13038f382424f45a988961acaca38f7c6" + integrity sha512-QRGy8ADi4J7ii95xz4UoiymmmMd/zuy9azCaamnZ3FM8T5fZcex8UfJcjkiEZjJSztKfEBe3dZ5T/5RHAmw2mA== + dependencies: + "@typescript-eslint/types" "8.15.0" + "@typescript-eslint/visitor-keys" "8.15.0" + "@typescript-eslint/type-utils@8.12.2": version "8.12.2" resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-8.12.2.tgz#132b0c52d45f6814e6f2e32416c7951ed480b016" @@ -912,6 +2258,11 @@ resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.12.2.tgz#8d70098c0e90442495b53d0296acdca6d0f3f73c" integrity sha512-VwDwMF1SZ7wPBUZwmMdnDJ6sIFk4K4s+ALKLP6aIQsISkPv8jhiw65sAK6SuWODN/ix+m+HgbYDkH+zLjrzvOA== +"@typescript-eslint/types@8.15.0": + version "8.15.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.15.0.tgz#4958edf3d83e97f77005f794452e595aaf6430fc" + integrity sha512-n3Gt8Y/KyJNe0S3yDCD2RVKrHBC4gTUcLTebVBXacPy091E6tNspFLKRXlk3hwT4G55nfr1n2AdFqi/XMxzmPQ== + "@typescript-eslint/typescript-estree@8.12.2": version "8.12.2" resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.12.2.tgz#206df9b1cbff212aaa9401985ef99f04daa84da5" @@ -926,6 +2277,20 @@ semver "^7.6.0" ts-api-utils "^1.3.0" +"@typescript-eslint/typescript-estree@8.15.0": + version "8.15.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.15.0.tgz#915c94e387892b114a2a2cc0df2d7f19412c8ba7" + integrity sha512-1eMp2JgNec/niZsR7ioFBlsh/Fk0oJbhaqO0jRyQBMgkz7RrFfkqF9lYYmBoGBaSiLnu8TAPQTwoTUiSTUW9dg== + dependencies: + "@typescript-eslint/types" "8.15.0" + "@typescript-eslint/visitor-keys" "8.15.0" + debug "^4.3.4" + fast-glob "^3.3.2" + is-glob "^4.0.3" + minimatch "^9.0.4" + semver "^7.6.0" + ts-api-utils "^1.3.0" + "@typescript-eslint/utils@8.12.2": version "8.12.2" resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-8.12.2.tgz#726cc9f49f5866605bd15bbc1768ffc15637930e" @@ -936,6 +2301,16 @@ "@typescript-eslint/types" "8.12.2" "@typescript-eslint/typescript-estree" "8.12.2" +"@typescript-eslint/utils@^8.8.1": + version "8.15.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-8.15.0.tgz#ac04679ad19252776b38b81954b8e5a65567cef6" + integrity sha512-k82RI9yGhr0QM3Dnq+egEpz9qB6Un+WLYhmoNcvl8ltMEededhh7otBVVIDDsEEttauwdY/hQoSsOv13lxrFzQ== + dependencies: + "@eslint-community/eslint-utils" "^4.4.0" + "@typescript-eslint/scope-manager" "8.15.0" + "@typescript-eslint/types" "8.15.0" + "@typescript-eslint/typescript-estree" "8.15.0" + "@typescript-eslint/visitor-keys@8.12.2": version "8.12.2" resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.12.2.tgz#94d7410f78eb6d134b9fcabaf1eeedb910ba8c38" @@ -944,6 +2319,14 @@ "@typescript-eslint/types" "8.12.2" eslint-visitor-keys "^3.4.3" +"@typescript-eslint/visitor-keys@8.15.0": + version "8.15.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.15.0.tgz#9ea5a85eb25401d2aa74ec8a478af4e97899ea12" + integrity sha512-h8vYOulWec9LhpwfAdZf2bjr8xIp0KNKnpgqSz0qqYYKAW/QZKw3ktRndbiAtUz4acH4QLQavwZBYCc0wulA/Q== + dependencies: + "@typescript-eslint/types" "8.15.0" + eslint-visitor-keys "^4.2.0" + "@ungap/structured-clone@^1.2.0": version "1.2.0" resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.2.0.tgz#756641adb587851b5ccb3e095daf27ae581c8406" @@ -960,6 +2343,16 @@ "@types/babel__core" "^7.20.5" react-refresh "^0.14.2" +"@vitest/expect@2.0.5": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@vitest/expect/-/expect-2.0.5.tgz#f3745a6a2c18acbea4d39f5935e913f40d26fa86" + integrity sha512-yHZtwuP7JZivj65Gxoi8upUN2OzHTi3zVfjwdpu2WrvCZPLwsJ2Ey5ILIPccoW23dd/zQBlJ4/dhi7DWNyXCpA== + dependencies: + "@vitest/spy" "2.0.5" + "@vitest/utils" "2.0.5" + chai "^5.1.1" + tinyrainbow "^1.2.0" + "@vitest/expect@2.1.4": version "2.1.4" resolved "https://registry.yarnpkg.com/@vitest/expect/-/expect-2.1.4.tgz#48f4f53a01092a3bdc118cff245f79ef388bdd8e" @@ -979,6 +2372,13 @@ estree-walker "^3.0.3" magic-string "^0.30.12" +"@vitest/pretty-format@2.0.5": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@vitest/pretty-format/-/pretty-format-2.0.5.tgz#91d2e6d3a7235c742e1a6cc50e7786e2f2979b1e" + integrity sha512-h8k+1oWHfwTkyTkb9egzwNMfJAEx4veaPSnMeKbVSjp4euqGSbQlm5+6VHwTr7u4FJslVVsUG5nopCaAYdOmSQ== + dependencies: + tinyrainbow "^1.2.0" + "@vitest/pretty-format@2.1.4", "@vitest/pretty-format@^2.1.4": version "2.1.4" resolved "https://registry.yarnpkg.com/@vitest/pretty-format/-/pretty-format-2.1.4.tgz#fc31993bdc1ef5a6c1a4aa6844e7ba55658a4f9f" @@ -986,6 +2386,13 @@ dependencies: tinyrainbow "^1.2.0" +"@vitest/pretty-format@2.1.5": + version "2.1.5" + resolved "https://registry.yarnpkg.com/@vitest/pretty-format/-/pretty-format-2.1.5.tgz#bc79b8826d4a63dc04f2a75d2944694039fa50aa" + integrity sha512-4ZOwtk2bqG5Y6xRGHcveZVr+6txkH7M2e+nPFd6guSoN638v/1XQ0K06eOpi0ptVU/2tW/pIU4IoPotY/GZ9fw== + dependencies: + tinyrainbow "^1.2.0" + "@vitest/runner@2.1.4": version "2.1.4" resolved "https://registry.yarnpkg.com/@vitest/runner/-/runner-2.1.4.tgz#f9346500bdd0be1c926daaac5d683bae87ceda2c" @@ -1003,6 +2410,13 @@ magic-string "^0.30.12" pathe "^1.1.2" +"@vitest/spy@2.0.5": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@vitest/spy/-/spy-2.0.5.tgz#590fc07df84a78b8e9dd976ec2090920084a2b9f" + integrity sha512-c/jdthAhvJdpfVuaexSrnawxZz6pywlTPe84LUB2m/4t3rl2fTo9NFGBG4oWgaD+FTgDDV8hJ/nibT7IfH3JfA== + dependencies: + tinyspy "^3.0.0" + "@vitest/spy@2.1.4": version "2.1.4" resolved "https://registry.yarnpkg.com/@vitest/spy/-/spy-2.1.4.tgz#4e90f9783437c5841a27c80f8fd84d7289a6100a" @@ -1010,6 +2424,16 @@ dependencies: tinyspy "^3.0.2" +"@vitest/utils@2.0.5": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@vitest/utils/-/utils-2.0.5.tgz#6f8307a4b6bc6ceb9270007f73c67c915944e926" + integrity sha512-d8HKbqIcya+GR67mkZbrzhS5kKhtp8dQLcmRZLGTscGVg7yImT82cIrhtn2L8+VujWcy6KZweApgNmPsTAO/UQ== + dependencies: + "@vitest/pretty-format" "2.0.5" + estree-walker "^3.0.3" + loupe "^3.1.1" + tinyrainbow "^1.2.0" + "@vitest/utils@2.1.4": version "2.1.4" resolved "https://registry.yarnpkg.com/@vitest/utils/-/utils-2.1.4.tgz#6d67ac966647a21ce8bc497472ce230de3b64537" @@ -1019,11 +2443,158 @@ loupe "^3.1.2" tinyrainbow "^1.2.0" +"@vitest/utils@^2.1.1": + version "2.1.5" + resolved "https://registry.yarnpkg.com/@vitest/utils/-/utils-2.1.5.tgz#0e19ce677c870830a1573d33ee86b0d6109e9546" + integrity sha512-yfj6Yrp0Vesw2cwJbP+cl04OC+IHFsuQsrsJBL9pyGeQXE56v1UAOQco+SR55Vf1nQzfV0QJg1Qum7AaWUwwYg== + dependencies: + "@vitest/pretty-format" "2.1.5" + loupe "^3.1.2" + tinyrainbow "^1.2.0" + +"@webassemblyjs/ast@1.14.1", "@webassemblyjs/ast@^1.12.1": + version "1.14.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.14.1.tgz#a9f6a07f2b03c95c8d38c4536a1fdfb521ff55b6" + integrity sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ== + dependencies: + "@webassemblyjs/helper-numbers" "1.13.2" + "@webassemblyjs/helper-wasm-bytecode" "1.13.2" + +"@webassemblyjs/floating-point-hex-parser@1.13.2": + version "1.13.2" + resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.13.2.tgz#fcca1eeddb1cc4e7b6eed4fc7956d6813b21b9fb" + integrity sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA== + +"@webassemblyjs/helper-api-error@1.13.2": + version "1.13.2" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz#e0a16152248bc38daee76dd7e21f15c5ef3ab1e7" + integrity sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ== + +"@webassemblyjs/helper-buffer@1.14.1": + version "1.14.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.14.1.tgz#822a9bc603166531f7d5df84e67b5bf99b72b96b" + integrity sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA== + +"@webassemblyjs/helper-numbers@1.13.2": + version "1.13.2" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-numbers/-/helper-numbers-1.13.2.tgz#dbd932548e7119f4b8a7877fd5a8d20e63490b2d" + integrity sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA== + dependencies: + "@webassemblyjs/floating-point-hex-parser" "1.13.2" + "@webassemblyjs/helper-api-error" "1.13.2" + "@xtuc/long" "4.2.2" + +"@webassemblyjs/helper-wasm-bytecode@1.13.2": + version "1.13.2" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.13.2.tgz#e556108758f448aae84c850e593ce18a0eb31e0b" + integrity sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA== + +"@webassemblyjs/helper-wasm-section@1.14.1": + version "1.14.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.14.1.tgz#9629dda9c4430eab54b591053d6dc6f3ba050348" + integrity sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw== + dependencies: + "@webassemblyjs/ast" "1.14.1" + "@webassemblyjs/helper-buffer" "1.14.1" + "@webassemblyjs/helper-wasm-bytecode" "1.13.2" + "@webassemblyjs/wasm-gen" "1.14.1" + +"@webassemblyjs/ieee754@1.13.2": + version "1.13.2" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.13.2.tgz#1c5eaace1d606ada2c7fd7045ea9356c59ee0dba" + integrity sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw== + dependencies: + "@xtuc/ieee754" "^1.2.0" + +"@webassemblyjs/leb128@1.13.2": + version "1.13.2" + resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.13.2.tgz#57c5c3deb0105d02ce25fa3fd74f4ebc9fd0bbb0" + integrity sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw== + dependencies: + "@xtuc/long" "4.2.2" + +"@webassemblyjs/utf8@1.13.2": + version "1.13.2" + resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.13.2.tgz#917a20e93f71ad5602966c2d685ae0c6c21f60f1" + integrity sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ== + +"@webassemblyjs/wasm-edit@^1.12.1": + version "1.14.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.14.1.tgz#ac6689f502219b59198ddec42dcd496b1004d597" + integrity sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ== + dependencies: + "@webassemblyjs/ast" "1.14.1" + "@webassemblyjs/helper-buffer" "1.14.1" + "@webassemblyjs/helper-wasm-bytecode" "1.13.2" + "@webassemblyjs/helper-wasm-section" "1.14.1" + "@webassemblyjs/wasm-gen" "1.14.1" + "@webassemblyjs/wasm-opt" "1.14.1" + "@webassemblyjs/wasm-parser" "1.14.1" + "@webassemblyjs/wast-printer" "1.14.1" + +"@webassemblyjs/wasm-gen@1.14.1": + version "1.14.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.14.1.tgz#991e7f0c090cb0bb62bbac882076e3d219da9570" + integrity sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg== + dependencies: + "@webassemblyjs/ast" "1.14.1" + "@webassemblyjs/helper-wasm-bytecode" "1.13.2" + "@webassemblyjs/ieee754" "1.13.2" + "@webassemblyjs/leb128" "1.13.2" + "@webassemblyjs/utf8" "1.13.2" + +"@webassemblyjs/wasm-opt@1.14.1": + version "1.14.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.14.1.tgz#e6f71ed7ccae46781c206017d3c14c50efa8106b" + integrity sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw== + dependencies: + "@webassemblyjs/ast" "1.14.1" + "@webassemblyjs/helper-buffer" "1.14.1" + "@webassemblyjs/wasm-gen" "1.14.1" + "@webassemblyjs/wasm-parser" "1.14.1" + +"@webassemblyjs/wasm-parser@1.14.1", "@webassemblyjs/wasm-parser@^1.12.1": + version "1.14.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.14.1.tgz#b3e13f1893605ca78b52c68e54cf6a865f90b9fb" + integrity sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ== + dependencies: + "@webassemblyjs/ast" "1.14.1" + "@webassemblyjs/helper-api-error" "1.13.2" + "@webassemblyjs/helper-wasm-bytecode" "1.13.2" + "@webassemblyjs/ieee754" "1.13.2" + "@webassemblyjs/leb128" "1.13.2" + "@webassemblyjs/utf8" "1.13.2" + +"@webassemblyjs/wast-printer@1.14.1": + version "1.14.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.14.1.tgz#3bb3e9638a8ae5fdaf9610e7a06b4d9f9aa6fe07" + integrity sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw== + dependencies: + "@webassemblyjs/ast" "1.14.1" + "@xtuc/long" "4.2.2" + +"@xtuc/ieee754@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790" + integrity sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA== + +"@xtuc/long@4.2.2": + version "4.2.2" + resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d" + integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== + abbrev@1: version "1.1.1" resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== +abort-controller@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392" + integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg== + dependencies: + event-target-shim "^5.0.0" + accept-language@^3.0.20: version "3.0.20" resolved "https://registry.yarnpkg.com/accept-language/-/accept-language-3.0.20.tgz#e825601d3b59f5ac7487698569b6640e80240cda" @@ -1036,11 +2607,19 @@ acorn-jsx@^5.3.2: resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== -acorn@^8.9.0: +acorn@^8.14.0, acorn@^8.8.2, acorn@^8.9.0: version "8.14.0" resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.14.0.tgz#063e2c70cac5fb4f6467f0b11152e04c682795b0" integrity sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA== +adjust-sourcemap-loader@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/adjust-sourcemap-loader/-/adjust-sourcemap-loader-4.0.0.tgz#fc4a0fd080f7d10471f30a7320f25560ade28c99" + integrity sha512-OXwN5b9pCUXNQHJpwwD2qP40byEmSgzj8B4ydSN0uMNYWiFmJ6x6KwUllMmfk8Rwu/HJDFR7U8ubsWBoN0Xp0A== + dependencies: + loader-utils "^2.0.0" + regex-parser "^2.2.11" + agent-base@6: version "6.0.2" resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" @@ -1055,7 +2634,26 @@ agent-base@^7.0.2, agent-base@^7.1.0: dependencies: debug "^4.3.4" -ajv@^6.12.4: +ajv-formats@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ajv-formats/-/ajv-formats-2.1.1.tgz#6e669400659eb74973bbf2e33327180a0996b520" + integrity sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA== + dependencies: + ajv "^8.0.0" + +ajv-keywords@^3.5.2: + version "3.5.2" + resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d" + integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ== + +ajv-keywords@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-5.1.0.tgz#69d4d385a4733cdbeab44964a1170a88f87f0e16" + integrity sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw== + dependencies: + fast-deep-equal "^3.1.3" + +ajv@^6.12.4, ajv@^6.12.5: version "6.12.6" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== @@ -1065,6 +2663,26 @@ ajv@^6.12.4: json-schema-traverse "^0.4.1" uri-js "^4.2.2" +ajv@^8.0.0, ajv@^8.9.0: + version "8.17.1" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.17.1.tgz#37d9a5c776af6bc92d7f4f9510eba4c0a60d11a6" + integrity sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g== + dependencies: + fast-deep-equal "^3.1.3" + fast-uri "^3.0.1" + json-schema-traverse "^1.0.0" + require-from-string "^2.0.2" + +ansi-html-community@0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/ansi-html-community/-/ansi-html-community-0.0.8.tgz#69fbc4d6ccbe383f9736934ae34c3f8290f1bf41" + integrity sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw== + +ansi-html@^0.0.9: + version "0.0.9" + resolved "https://registry.yarnpkg.com/ansi-html/-/ansi-html-0.0.9.tgz#6512d02342ae2cc68131952644a129cb734cd3f0" + integrity sha512-ozbS3LuenHVxNRh/wdnN16QapUHzauqSomAl1jwwJRRsGwFwtj644lIhxfWu0Fy0acCij2+AEgHvjscq3dlVXg== + ansi-regex@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" @@ -1135,7 +2753,7 @@ aria-query@5.3.0: dependencies: dequal "^2.0.3" -aria-query@^5.3.2: +aria-query@^5.0.0, aria-query@^5.3.2: version "5.3.2" resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-5.3.2.tgz#93f81a43480e33a338f19163a3d10a50c01dcd59" integrity sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw== @@ -1229,6 +2847,26 @@ arraybuffer.prototype.slice@^1.0.3: is-array-buffer "^3.0.4" is-shared-array-buffer "^1.0.2" +asn1.js@^4.10.1: + version "4.10.1" + resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-4.10.1.tgz#b9c2bf5805f1e64aadeed6df3a2bfafb5a73f5a0" + integrity sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw== + dependencies: + bn.js "^4.0.0" + inherits "^2.0.1" + minimalistic-assert "^1.0.0" + +assert@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/assert/-/assert-2.1.0.tgz#6d92a238d05dc02e7427c881fb8be81c8448b2dd" + integrity sha512-eLHpSK/Y4nhMJ07gDaAzoX/XAKS8PSaojml3M0DM4JpV1LAi5JOJ/p6H/XWrl8L+DzVEvVCW1z3vWAaB9oTsQw== + dependencies: + call-bind "^1.0.2" + is-nan "^1.3.2" + object-is "^1.1.5" + object.assign "^4.1.4" + util "^0.12.5" + assertion-error@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-2.0.1.tgz#f641a196b335690b1070bf00b6e7593fec190bf7" @@ -1239,6 +2877,13 @@ ast-types-flow@^0.0.8: resolved "https://registry.yarnpkg.com/ast-types-flow/-/ast-types-flow-0.0.8.tgz#0a85e1c92695769ac13a428bb653e7538bea27d6" integrity sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ== +ast-types@^0.16.1: + version "0.16.1" + resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.16.1.tgz#7a9da1617c9081bc121faafe91711b4c8bb81da2" + integrity sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg== + dependencies: + tslib "^2.0.1" + asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" @@ -1261,11 +2906,48 @@ axobject-query@^4.1.0: resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-4.1.0.tgz#28768c76d0e3cff21bc62a9e2d0b6ac30042a1ee" integrity sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ== +babel-loader@^9.1.3: + version "9.2.1" + resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-9.2.1.tgz#04c7835db16c246dd19ba0914418f3937797587b" + integrity sha512-fqe8naHt46e0yIdkjUZYqddSXfej3AHajX+CSO5X7oy0EmPc6o5Xh+RClNoHjnieWz9AW4kZxW9yyFMhVB1QLA== + dependencies: + find-cache-dir "^4.0.0" + schema-utils "^4.0.0" + +babel-plugin-polyfill-corejs2@^0.4.10: + version "0.4.12" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.12.tgz#ca55bbec8ab0edeeef3d7b8ffd75322e210879a9" + integrity sha512-CPWT6BwvhrTO2d8QVorhTCQw9Y43zOu7G9HigcfxvepOU6b8o3tcWad6oVgZIsZCTt42FFv97aA7ZJsbM4+8og== + dependencies: + "@babel/compat-data" "^7.22.6" + "@babel/helper-define-polyfill-provider" "^0.6.3" + semver "^6.3.1" + +babel-plugin-polyfill-corejs3@^0.10.6: + version "0.10.6" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.6.tgz#2deda57caef50f59c525aeb4964d3b2f867710c7" + integrity sha512-b37+KR2i/khY5sKmWNVQAnitvquQbNdWy6lJdsr0kmquCKEEUgMKK4SboVM3HtfnZilfjr4MMQ7vY58FVWDtIA== + dependencies: + "@babel/helper-define-polyfill-provider" "^0.6.2" + core-js-compat "^3.38.0" + +babel-plugin-polyfill-regenerator@^0.6.1: + version "0.6.3" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.3.tgz#abeb1f3f1c762eace37587f42548b08b57789bc8" + integrity sha512-LiWSbl4CRSIa5x/JAU6jZiG9eit9w6mz+yVMFwDE83LAWvt0AfGBoZ7HS/mkhrKuh2ZlzfVZYKoLjXdqw6Yt7Q== + dependencies: + "@babel/helper-define-polyfill-provider" "^0.6.3" + balanced-match@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== +base64-js@^1.3.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" + integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== + bcp47@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/bcp47/-/bcp47-1.1.2.tgz#354be3307ffd08433a78f5e1e2095845f89fc7fe" @@ -1279,11 +2961,38 @@ bcrypt@^5.1.1: "@mapbox/node-pre-gyp" "^1.0.11" node-addon-api "^5.0.0" +better-opn@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/better-opn/-/better-opn-3.0.2.tgz#f96f35deaaf8f34144a4102651babcf00d1d8817" + integrity sha512-aVNobHnJqLiUelTaHat9DZ1qM2w0C0Eym4LPI/3JxOnSokGVdsl1T1kN7TFvsEAD8G47A6VKQ0TVHqbBnYMJlQ== + dependencies: + open "^8.0.4" + +big.js@^5.2.2: + version "5.2.2" + resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328" + integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ== + binary-extensions@^2.0.0: version "2.3.0" resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.3.0.tgz#f6e14a97858d327252200242d4ccfe522c445522" integrity sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw== +bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.11.9: + version "4.12.1" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.1.tgz#215741fe3c9dba2d7e12c001d0cfdbae43975ba7" + integrity sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg== + +bn.js@^5.2.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.1.tgz#0bc527a6a0d18d0aa8d5b0538ce4a77dccfa7b70" + integrity sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ== + +boolbase@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" + integrity sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww== + brace-expansion@^1.1.7: version "1.1.11" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" @@ -1306,7 +3015,80 @@ braces@^3.0.3, braces@~3.0.2: dependencies: fill-range "^7.1.1" -browserslist@^4.24.0: +brorand@^1.0.1, brorand@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" + integrity sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w== + +browser-assert@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/browser-assert/-/browser-assert-1.2.1.tgz#9aaa5a2a8c74685c2ae05bfe46efd606f068c200" + integrity sha512-nfulgvOR6S4gt9UKCeGJOuSGBPGiFT6oQ/2UBnvTY/5aQ1PnksW72fhZkM30DzoRRv2WpwZf1vHHEr3mtuXIWQ== + +browserify-aes@^1.0.4, browserify-aes@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" + integrity sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA== + dependencies: + buffer-xor "^1.0.3" + cipher-base "^1.0.0" + create-hash "^1.1.0" + evp_bytestokey "^1.0.3" + inherits "^2.0.1" + safe-buffer "^5.0.1" + +browserify-cipher@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/browserify-cipher/-/browserify-cipher-1.0.1.tgz#8d6474c1b870bfdabcd3bcfcc1934a10e94f15f0" + integrity sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w== + dependencies: + browserify-aes "^1.0.4" + browserify-des "^1.0.0" + evp_bytestokey "^1.0.0" + +browserify-des@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/browserify-des/-/browserify-des-1.0.2.tgz#3af4f1f59839403572f1c66204375f7a7f703e9c" + integrity sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A== + dependencies: + cipher-base "^1.0.1" + des.js "^1.0.0" + inherits "^2.0.1" + safe-buffer "^5.1.2" + +browserify-rsa@^4.0.0, browserify-rsa@^4.1.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/browserify-rsa/-/browserify-rsa-4.1.1.tgz#06e530907fe2949dc21fc3c2e2302e10b1437238" + integrity sha512-YBjSAiTqM04ZVei6sXighu679a3SqWORA3qZTEqZImnlkDIFtKc6pNutpjyZ8RJTjQtuYfeetkxM11GwoYXMIQ== + dependencies: + bn.js "^5.2.1" + randombytes "^2.1.0" + safe-buffer "^5.2.1" + +browserify-sign@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.2.3.tgz#7afe4c01ec7ee59a89a558a4b75bd85ae62d4208" + integrity sha512-JWCZW6SKhfhjJxO8Tyiiy+XYB7cqd2S5/+WeYHsKdNKFlCBhKbblba1A/HN/90YwtxKc8tCErjffZl++UNmGiw== + dependencies: + bn.js "^5.2.1" + browserify-rsa "^4.1.0" + create-hash "^1.2.0" + create-hmac "^1.1.7" + elliptic "^6.5.5" + hash-base "~3.0" + inherits "^2.0.4" + parse-asn1 "^5.1.7" + readable-stream "^2.3.8" + safe-buffer "^5.2.1" + +browserify-zlib@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/browserify-zlib/-/browserify-zlib-0.2.0.tgz#2869459d9aa3be245fe8fe2ca1f46e2e7f54d73f" + integrity sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA== + dependencies: + pako "~1.0.5" + +browserslist@^4.24.0, browserslist@^4.24.2: version "4.24.2" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.24.2.tgz#f5845bc91069dbd55ee89faf9822e1d885d16580" integrity sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg== @@ -1316,6 +3098,29 @@ browserslist@^4.24.0: node-releases "^2.0.18" update-browserslist-db "^1.1.1" +buffer-from@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" + integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== + +buffer-xor@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" + integrity sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ== + +buffer@^6.0.3: + version "6.0.3" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6" + integrity sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA== + dependencies: + base64-js "^1.3.1" + ieee754 "^1.2.1" + +builtin-status-codes@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8" + integrity sha512-HpGFw18DgFWlncDfjTa2rcQ4W88O1mC8e8yZ2AvQY5KDaktSTwo+KRf6nHK6FRI5FyRyb/5T6+TSxfP7QyGsmQ== + busboy@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/busboy/-/busboy-1.6.0.tgz#966ea36a9502e43cdb9146962523b92f531f6893" @@ -1328,7 +3133,7 @@ cac@^6.7.14: resolved "https://registry.yarnpkg.com/cac/-/cac-6.7.14.tgz#804e1e6f506ee363cb0e3ccbb09cad5dd9870959" integrity sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ== -call-bind@^1.0.2, call-bind@^1.0.5, call-bind@^1.0.6, call-bind@^1.0.7: +call-bind@^1.0.0, call-bind@^1.0.2, call-bind@^1.0.5, call-bind@^1.0.6, call-bind@^1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.7.tgz#06016599c40c56498c18769d2730be242b6fa3b9" integrity sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w== @@ -1344,6 +3149,14 @@ callsites@^3.0.0: resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== +camel-case@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/camel-case/-/camel-case-4.1.2.tgz#9728072a954f805228225a6deea6b38461e1bd5a" + integrity sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw== + dependencies: + pascal-case "^3.1.2" + tslib "^2.0.3" + camelcase-css@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/camelcase-css/-/camelcase-css-2.0.1.tgz#ee978f6947914cc30c6b44741b6ed1df7f043fd5" @@ -1354,7 +3167,12 @@ caniuse-lite@^1.0.30001579, caniuse-lite@^1.0.30001669: resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001676.tgz#fe133d41fe74af8f7cc93b8a714c3e86a86e6f04" integrity sha512-Qz6zwGCiPghQXGJvgQAem79esjitvJ+CxSbSQkW9H/UX5hg8XM88d4lp2W+MEQ81j+Hip58Il+jGVdazk1z9cw== -chai@^5.1.2: +case-sensitive-paths-webpack-plugin@^2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/case-sensitive-paths-webpack-plugin/-/case-sensitive-paths-webpack-plugin-2.4.0.tgz#db64066c6422eed2e08cc14b986ca43796dbc6d4" + integrity sha512-roIFONhcxog0JSSWbvVAh3OocukmSgpqOH6YpMkCvav/ySIV3JKg4Dc8vYtQjYi/UxpNE36r/9v+VqTQqgkYmw== + +chai@^5.1.1, chai@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/chai/-/chai-5.1.2.tgz#3afbc340b994ae3610ca519a6c70ace77ad4378d" integrity sha512-aGtmf24DW6MLHHG5gCx4zaI3uBq3KRtxeVs0DjFH6Z0rDNbsvTxFASFvdj79pxjxZ8/5u3PIiN3IwEIQkiiuPw== @@ -1365,7 +3183,15 @@ chai@^5.1.2: loupe "^3.1.0" pathval "^2.0.0" -chalk@^4.0.0, chalk@^4.1.0: +chalk@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-3.0.0.tgz#3f73c2bf526591f574cc492c51e2456349f844e4" + integrity sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== @@ -1398,6 +3224,29 @@ chownr@^2.0.0: resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece" integrity sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ== +chromatic@^11.15.0: + version "11.18.1" + resolved "https://registry.yarnpkg.com/chromatic/-/chromatic-11.18.1.tgz#c8f7b330dbd9be3b45a84abcb924f5217dc6c326" + integrity sha512-hkNT9vA6K9+PnE/khhZYBnRCOm8NonaQDs7RZ8YHFo7/lh1b/x/uFMkTjWjaj/mkM6QOR/evu5VcZMtcaauSlw== + +chrome-trace-event@^1.0.2: + version "1.0.4" + resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz#05bffd7ff928465093314708c93bdfa9bd1f0f5b" + integrity sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ== + +cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: + version "1.0.5" + resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.5.tgz#749f80731c7821e9a5fabd51f6998b696f296686" + integrity sha512-xq7ICKB4TMHUx7Tz1L9O2SGKOhYMOTR32oir45Bq28/AQTpHogKgHcoYFSdRbMtddl+ozNXfXY9jWcgYKmde0w== + dependencies: + inherits "^2.0.4" + safe-buffer "^5.2.1" + +cjs-module-lexer@^1.2.3: + version "1.4.1" + resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.4.1.tgz#707413784dbb3a72aa11c2f2b042a0bef4004170" + integrity sha512-cuSVIHi9/9E/+821Qjdvngor+xpnlwnuwIyZOaLmHBVdXL+gP+I6QQB9VkO7RI77YIcTV+S1W9AreJ5eN63JBA== + class-variance-authority@^0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/class-variance-authority/-/class-variance-authority-0.7.0.tgz#1c3134d634d80271b1837452b06d821915954522" @@ -1405,6 +3254,13 @@ class-variance-authority@^0.7.0: dependencies: clsx "2.0.0" +clean-css@^5.2.2: + version "5.3.3" + resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-5.3.3.tgz#b330653cd3bd6b75009cc25c714cae7b93351ccd" + integrity sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg== + dependencies: + source-map "~0.6.0" + client-only@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/client-only/-/client-only-0.0.1.tgz#38bba5d403c41ab150bff64a95c85013cf73bca1" @@ -1453,6 +3309,11 @@ color@^4.2.3: color-convert "^2.0.1" color-string "^1.9.0" +colorette@^2.0.10: + version "2.0.20" + resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.20.tgz#9eb793e6833067f7235902fcd3b09917a000a95a" + integrity sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w== + combined-stream@^1.0.8: version "1.0.8" resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" @@ -1460,11 +3321,31 @@ combined-stream@^1.0.8: dependencies: delayed-stream "~1.0.0" +commander@^2.20.0: + version "2.20.3" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" + integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== + commander@^4.0.0: version "4.1.1" resolved "https://registry.yarnpkg.com/commander/-/commander-4.1.1.tgz#9fd602bd936294e9e9ef46a3f4d6964044b18068" integrity sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA== +commander@^8.3.0: + version "8.3.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66" + integrity sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww== + +common-path-prefix@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/common-path-prefix/-/common-path-prefix-3.0.0.tgz#7d007a7e07c58c4b4d5f433131a19141b29f11e0" + integrity sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w== + +commondir@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" + integrity sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg== + concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" @@ -1475,11 +3356,26 @@ confusing-browser-globals@^1.0.10: resolved "https://registry.yarnpkg.com/confusing-browser-globals/-/confusing-browser-globals-1.0.11.tgz#ae40e9b57cdd3915408a2805ebd3a5585608dc81" integrity sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA== +console-browserify@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.2.0.tgz#67063cef57ceb6cf4993a2ab3a55840ae8c49336" + integrity sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA== + console-control-strings@^1.0.0, console-control-strings@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" integrity sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ== +constants-browserify@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75" + integrity sha512-xFxOwqIzR/e1k1gLiWEophSCMqXcwVHIH7akf7b/vxcUeGunlj3hvZaaqxwHsTgn+IndtkQJgSztIDWeumWJDQ== + +convert-source-map@^1.7.0: + version "1.9.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.9.0.tgz#7faae62353fb4213366d0ca98358d22e8368b05f" + integrity sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A== + convert-source-map@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a" @@ -1490,6 +3386,75 @@ cookie@^0.7.2: resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.7.2.tgz#556369c472a2ba910f2979891b526b3436237ed7" integrity sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w== +core-js-compat@^3.38.0, core-js-compat@^3.38.1: + version "3.39.0" + resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.39.0.tgz#b12dccb495f2601dc860bdbe7b4e3ffa8ba63f61" + integrity sha512-VgEUx3VwlExr5no0tXlBt+silBvhTryPwCXRI2Id1PN8WTKu7MreethvddqOubrYxkFdv/RnYrqlv1sFNAUelw== + dependencies: + browserslist "^4.24.2" + +core-js-pure@^3.23.3: + version "3.39.0" + resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.39.0.tgz#aa0d54d70a15bdc13e7c853db87c10abc30d68f3" + integrity sha512-7fEcWwKI4rJinnK+wLTezeg2smbFFdSBP6E2kQZNbnzM2s1rpKQ6aaRteZSSg7FLU3P0HGGVo/gbpfanU36urg== + +core-util-is@~1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" + integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== + +cosmiconfig@^7.0.1: + version "7.1.0" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-7.1.0.tgz#1443b9afa596b670082ea46cbd8f6a62b84635f6" + integrity sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA== + dependencies: + "@types/parse-json" "^4.0.0" + import-fresh "^3.2.1" + parse-json "^5.0.0" + path-type "^4.0.0" + yaml "^1.10.0" + +cosmiconfig@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-9.0.0.tgz#34c3fc58287b915f3ae905ab6dc3de258b55ad9d" + integrity sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg== + dependencies: + env-paths "^2.2.1" + import-fresh "^3.3.0" + js-yaml "^4.1.0" + parse-json "^5.2.0" + +create-ecdh@^4.0.4: + version "4.0.4" + resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.4.tgz#d6e7f4bffa66736085a0762fd3a632684dabcc4e" + integrity sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A== + dependencies: + bn.js "^4.1.0" + elliptic "^6.5.3" + +create-hash@^1.1.0, create-hash@^1.1.2, create-hash@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196" + integrity sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg== + dependencies: + cipher-base "^1.0.1" + inherits "^2.0.1" + md5.js "^1.3.4" + ripemd160 "^2.0.1" + sha.js "^2.4.0" + +create-hmac@^1.1.4, create-hmac@^1.1.7: + version "1.1.7" + resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff" + integrity sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg== + dependencies: + cipher-base "^1.0.3" + create-hash "^1.1.0" + inherits "^2.0.1" + ripemd160 "^2.0.0" + safe-buffer "^5.0.1" + sha.js "^2.4.8" + cross-spawn@^7.0.0, cross-spawn@^7.0.2: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" @@ -1499,6 +3464,59 @@ cross-spawn@^7.0.0, cross-spawn@^7.0.2: shebang-command "^2.0.0" which "^2.0.1" +crypto-browserify@^3.12.0: + version "3.12.1" + resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.1.tgz#bb8921bec9acc81633379aa8f52d69b0b69e0dac" + integrity sha512-r4ESw/IlusD17lgQi1O20Fa3qNnsckR126TdUuBgAu7GBYSIPvdNyONd3Zrxh0xCwA4+6w/TDArBPsMvhur+KQ== + dependencies: + browserify-cipher "^1.0.1" + browserify-sign "^4.2.3" + create-ecdh "^4.0.4" + create-hash "^1.2.0" + create-hmac "^1.1.7" + diffie-hellman "^5.0.3" + hash-base "~3.0.4" + inherits "^2.0.4" + pbkdf2 "^3.1.2" + public-encrypt "^4.0.3" + randombytes "^2.1.0" + randomfill "^1.0.4" + +css-loader@^6.7.1, css-loader@^6.7.3: + version "6.11.0" + resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-6.11.0.tgz#33bae3bf6363d0a7c2cf9031c96c744ff54d85ba" + integrity sha512-CTJ+AEQJjq5NzLga5pE39qdiSV56F8ywCIsqNIRF0r7BDgWsN25aazToqAFg7ZrtA/U016xudB3ffgweORxX7g== + dependencies: + icss-utils "^5.1.0" + postcss "^8.4.33" + postcss-modules-extract-imports "^3.1.0" + postcss-modules-local-by-default "^4.0.5" + postcss-modules-scope "^3.2.0" + postcss-modules-values "^4.0.0" + postcss-value-parser "^4.2.0" + semver "^7.5.4" + +css-select@^4.1.3: + version "4.3.0" + resolved "https://registry.yarnpkg.com/css-select/-/css-select-4.3.0.tgz#db7129b2846662fd8628cfc496abb2b59e41529b" + integrity sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ== + dependencies: + boolbase "^1.0.0" + css-what "^6.0.1" + domhandler "^4.3.1" + domutils "^2.8.0" + nth-check "^2.0.1" + +css-what@^6.0.1: + version "6.1.0" + resolved "https://registry.yarnpkg.com/css-what/-/css-what-6.1.0.tgz#fb5effcf76f1ddea2c81bdfaa4de44e79bac70f4" + integrity sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw== + +css.escape@^1.5.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/css.escape/-/css.escape-1.5.1.tgz#42e27d4fa04ae32f931a4b4d4191fa9cddee97cb" + integrity sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg== + cssesc@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" @@ -1556,7 +3574,7 @@ data-view-byte-offset@^1.0.0: es-errors "^1.3.0" is-data-view "^1.0.1" -debug@4, debug@^4.1.0, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4, debug@^4.3.5, debug@^4.3.7: +debug@4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4, debug@^4.3.5, debug@^4.3.7: version "4.3.7" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.7.tgz#87945b4151a011d76d95a198d7111c865c360a52" integrity sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ== @@ -1575,6 +3593,11 @@ decimal.js@^10.4.3: resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.4.3.tgz#1044092884d245d1b7f65725fa4ad4c6f781cc23" integrity sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA== +dedent@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c" + integrity sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA== + deep-eql@^5.0.1: version "5.0.2" resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-5.0.2.tgz#4b756d8d770a9257300825d52a2c2cff99c3a341" @@ -1585,6 +3608,11 @@ deep-is@^0.1.3: resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== +deepmerge@^4.2.2: + version "4.3.1" + resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.3.1.tgz#44b5f2147cd3b00d4b56137685966f26fd25dd4a" + integrity sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A== + define-data-property@^1.0.1, define-data-property@^1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.4.tgz#894dc141bb7d3060ae4366f6a0107e68fbe48c5e" @@ -1594,6 +3622,11 @@ define-data-property@^1.0.1, define-data-property@^1.1.4: es-errors "^1.3.0" gopd "^1.0.1" +define-lazy-prop@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz#3f7ae421129bcaaac9bc74905c98a0009ec9ee7f" + integrity sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og== + define-properties@^1.1.3, define-properties@^1.2.0, define-properties@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.1.tgz#10781cc616eb951a80a034bafcaa7377f6af2b6c" @@ -1613,11 +3646,19 @@ delegates@^1.0.0: resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" integrity sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ== -dequal@^2.0.3: +dequal@^2.0.2, dequal@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/dequal/-/dequal-2.0.3.tgz#2644214f1997d39ed0ee0ece72335490a7ac67be" integrity sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA== +des.js@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.1.0.tgz#1d37f5766f3bbff4ee9638e871a8768c173b81da" + integrity sha512-r17GxjhUCjSRy8aiJpr8/UadFIzMzJGexI3Nmz4ADi9LYSFx4gTBp80+NaX/YsXWWLhpZ7v/v/ubEc/bCNfKwg== + dependencies: + inherits "^2.0.1" + minimalistic-assert "^1.0.0" + detect-libc@^2.0.0, detect-libc@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-2.0.3.tgz#f0cd503b40f9939b894697d19ad50895e30cf700" @@ -1628,6 +3669,15 @@ didyoumean@^1.2.2: resolved "https://registry.yarnpkg.com/didyoumean/-/didyoumean-1.2.2.tgz#989346ffe9e839b4555ecf5666edea0d3e8ad037" integrity sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw== +diffie-hellman@^5.0.3: + version "5.0.3" + resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875" + integrity sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg== + dependencies: + bn.js "^4.1.0" + miller-rabin "^4.0.0" + randombytes "^2.0.0" + dlv@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/dlv/-/dlv-1.1.3.tgz#5c198a8a11453596e751494d49874bc7732f2e79" @@ -1652,6 +3702,61 @@ dom-accessibility-api@^0.5.9: resolved "https://registry.yarnpkg.com/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz#5a7429e6066eb3664d911e33fb0e45de8eb08453" integrity sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg== +dom-accessibility-api@^0.6.3: + version "0.6.3" + resolved "https://registry.yarnpkg.com/dom-accessibility-api/-/dom-accessibility-api-0.6.3.tgz#993e925cc1d73f2c662e7d75dd5a5445259a8fd8" + integrity sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w== + +dom-converter@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/dom-converter/-/dom-converter-0.2.0.tgz#6721a9daee2e293682955b6afe416771627bb768" + integrity sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA== + dependencies: + utila "~0.4" + +dom-serializer@^1.0.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-1.4.1.tgz#de5d41b1aea290215dc45a6dae8adcf1d32e2d30" + integrity sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag== + dependencies: + domelementtype "^2.0.1" + domhandler "^4.2.0" + entities "^2.0.0" + +domain-browser@^4.22.0: + version "4.23.0" + resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-4.23.0.tgz#427ebb91efcb070f05cffdfb8a4e9a6c25f8c94b" + integrity sha512-ArzcM/II1wCCujdCNyQjXrAFwS4mrLh4C7DZWlaI8mdh7h3BfKdNd3bKXITfl2PT9FtfQqaGvhi1vPRQPimjGA== + +domelementtype@^2.0.1, domelementtype@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.3.0.tgz#5c45e8e869952626331d7aab326d01daf65d589d" + integrity sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw== + +domhandler@^4.0.0, domhandler@^4.2.0, domhandler@^4.3.1: + version "4.3.1" + resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-4.3.1.tgz#8d792033416f59d68bc03a5aa7b018c1ca89279c" + integrity sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ== + dependencies: + domelementtype "^2.2.0" + +domutils@^2.5.2, domutils@^2.8.0: + version "2.8.0" + resolved "https://registry.yarnpkg.com/domutils/-/domutils-2.8.0.tgz#4437def5db6e2d1f5d6ee859bd95ca7d02048135" + integrity sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A== + dependencies: + dom-serializer "^1.0.1" + domelementtype "^2.2.0" + domhandler "^4.2.0" + +dot-case@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/dot-case/-/dot-case-3.0.4.tgz#9b2b670d00a431667a8a75ba29cd1b98809ce751" + integrity sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w== + dependencies: + no-case "^3.0.4" + tslib "^2.0.3" + dotenv@^16.4.5: version "16.4.5" resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.4.5.tgz#cdd3b3b604cb327e286b4762e13502f717cb099f" @@ -1667,6 +3772,19 @@ electron-to-chromium@^1.5.41: resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.50.tgz#d9ba818da7b2b5ef1f3dd32bce7046feb7e93234" integrity sha512-eMVObiUQ2LdgeO1F/ySTXsvqvxb6ZH2zPGaMYsWzRDdOddUa77tdmI0ltg+L16UpbWdhPmuF3wIQYyQq65WfZw== +elliptic@^6.5.3, elliptic@^6.5.5: + version "6.6.1" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.6.1.tgz#3b8ffb02670bf69e382c7f65bf524c97c5405c06" + integrity sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g== + dependencies: + bn.js "^4.11.9" + brorand "^1.1.0" + hash.js "^1.0.0" + hmac-drbg "^1.0.1" + inherits "^2.0.4" + minimalistic-assert "^1.0.1" + minimalistic-crypto-utils "^1.0.1" + emoji-regex@^8.0.0: version "8.0.0" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" @@ -1677,7 +3795,21 @@ emoji-regex@^9.2.2: resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== -enhanced-resolve@^5.15.0: +emojis-list@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78" + integrity sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q== + +endent@^2.0.1: + version "2.1.0" + resolved "https://registry.yarnpkg.com/endent/-/endent-2.1.0.tgz#5aaba698fb569e5e18e69e1ff7a28ff35373cd88" + integrity sha512-r8VyPX7XL8U01Xgnb1CjZ3XV+z90cXIJ9JPE/R9SEC9vpw2P6CfsRPJmp20DppC5N7ZAMCmjYkJIa744Iyg96w== + dependencies: + dedent "^0.7.0" + fast-json-parse "^1.0.3" + objectorarray "^1.0.5" + +enhanced-resolve@^5.15.0, enhanced-resolve@^5.17.1, enhanced-resolve@^5.7.0: version "5.17.1" resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz#67bfbbcc2f81d511be77d686a90267ef7f898a15" integrity sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg== @@ -1685,11 +3817,35 @@ enhanced-resolve@^5.15.0: graceful-fs "^4.2.4" tapable "^2.2.0" +entities@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55" + integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A== + entities@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/entities/-/entities-4.5.0.tgz#5d268ea5e7113ec74c4d033b79ea5a35a488fb48" integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw== +env-paths@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.1.tgz#420399d416ce1fbe9bc0a07c62fa68d67fd0f8f2" + integrity sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A== + +error-ex@^1.3.1: + version "1.3.2" + resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" + integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== + dependencies: + is-arrayish "^0.2.1" + +error-stack-parser@^2.0.6: + version "2.1.4" + resolved "https://registry.yarnpkg.com/error-stack-parser/-/error-stack-parser-2.1.4.tgz#229cb01cdbfa84440bfa91876285b94680188286" + integrity sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ== + dependencies: + stackframe "^1.3.4" + es-abstract@^1.17.5, es-abstract@^1.22.1, es-abstract@^1.22.3, es-abstract@^1.23.0, es-abstract@^1.23.1, es-abstract@^1.23.2, es-abstract@^1.23.3: version "1.23.3" resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.23.3.tgz#8f0c5a35cd215312573c5a27c87dfd6c881a0aa0" @@ -1774,6 +3930,11 @@ es-iterator-helpers@^1.1.0: iterator.prototype "^1.1.3" safe-array-concat "^1.1.2" +es-module-lexer@^1.2.1, es-module-lexer@^1.5.0: + version "1.5.4" + resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-1.5.4.tgz#a8efec3a3da991e60efa6b633a7cad6ab8d26b78" + integrity sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw== + es-object-atoms@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/es-object-atoms/-/es-object-atoms-1.0.0.tgz#ddb55cd47ac2e240701260bc2a8e31ecb643d941" @@ -1806,6 +3967,43 @@ es-to-primitive@^1.2.1: is-date-object "^1.0.1" is-symbol "^1.0.2" +esbuild-register@^3.5.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/esbuild-register/-/esbuild-register-3.6.0.tgz#cf270cfa677baebbc0010ac024b823cbf723a36d" + integrity sha512-H2/S7Pm8a9CL1uhp9OvjwrBh5Pvx0H8qVOxNu8Wed9Y7qv56MPtq+GGM8RJpq6glYJn9Wspr8uw7l55uyinNeg== + dependencies: + debug "^4.3.4" + +"esbuild@^0.18.0 || ^0.19.0 || ^0.20.0 || ^0.21.0 || ^0.22.0 || ^0.23.0 || ^0.24.0": + version "0.24.0" + resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.24.0.tgz#f2d470596885fcb2e91c21eb3da3b3c89c0b55e7" + integrity sha512-FuLPevChGDshgSicjisSooU0cemp/sGXR841D5LHMB7mTVOmsEHcAxaH3irL53+8YDIeVNQEySh4DaYU/iuPqQ== + optionalDependencies: + "@esbuild/aix-ppc64" "0.24.0" + "@esbuild/android-arm" "0.24.0" + "@esbuild/android-arm64" "0.24.0" + "@esbuild/android-x64" "0.24.0" + "@esbuild/darwin-arm64" "0.24.0" + "@esbuild/darwin-x64" "0.24.0" + "@esbuild/freebsd-arm64" "0.24.0" + "@esbuild/freebsd-x64" "0.24.0" + "@esbuild/linux-arm" "0.24.0" + "@esbuild/linux-arm64" "0.24.0" + "@esbuild/linux-ia32" "0.24.0" + "@esbuild/linux-loong64" "0.24.0" + "@esbuild/linux-mips64el" "0.24.0" + "@esbuild/linux-ppc64" "0.24.0" + "@esbuild/linux-riscv64" "0.24.0" + "@esbuild/linux-s390x" "0.24.0" + "@esbuild/linux-x64" "0.24.0" + "@esbuild/netbsd-x64" "0.24.0" + "@esbuild/openbsd-arm64" "0.24.0" + "@esbuild/openbsd-x64" "0.24.0" + "@esbuild/sunos-x64" "0.24.0" + "@esbuild/win32-arm64" "0.24.0" + "@esbuild/win32-ia32" "0.24.0" + "@esbuild/win32-x64" "0.24.0" + esbuild@^0.21.3: version "0.21.5" resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.21.5.tgz#9ca301b120922959b766360d8ac830da0d02997d" @@ -2003,6 +4201,23 @@ eslint-plugin-react@^7.35.0: string.prototype.matchall "^4.0.11" string.prototype.repeat "^1.0.0" +eslint-plugin-storybook@^0.11.1: + version "0.11.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-storybook/-/eslint-plugin-storybook-0.11.1.tgz#4ef4f3550855fdc4a902296dfc278340ec287506" + integrity sha512-yGKpAYkBm/Q2hZg476vRUAvd9lAccjjSvzU5nYy3BSQbKTPy7uopx7JEpwk2vSuw4weTMZzWF64z9/gp/K5RCg== + dependencies: + "@storybook/csf" "^0.1.11" + "@typescript-eslint/utils" "^8.8.1" + ts-dedent "^2.2.0" + +eslint-scope@5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" + integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== + dependencies: + esrecurse "^4.3.0" + estraverse "^4.1.1" + eslint-scope@^7.2.2: version "7.2.2" resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.2.2.tgz#deb4f92563390f32006894af62a22dba1c46423f" @@ -2016,6 +4231,11 @@ eslint-visitor-keys@^3.4.1, eslint-visitor-keys@^3.4.3: resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== +eslint-visitor-keys@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz#687bacb2af884fcdda8a6e7d65c606f46a14cd45" + integrity sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw== + eslint@^8: version "8.57.1" resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.57.1.tgz#7df109654aba7e3bbe5c8eae533c5e461d3c6ca9" @@ -2069,6 +4289,11 @@ espree@^9.6.0, espree@^9.6.1: acorn-jsx "^5.3.2" eslint-visitor-keys "^3.4.1" +esprima@~4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" + integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== + esquery@^1.4.2: version "1.6.0" resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.6.0.tgz#91419234f804d852a82dceec3e16cdc22cf9dae7" @@ -2083,6 +4308,11 @@ esrecurse@^4.3.0: dependencies: estraverse "^5.2.0" +estraverse@^4.1.1: + version "4.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" + integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== + estraverse@^5.1.0, estraverse@^5.2.0, estraverse@^5.3.0: version "5.3.0" resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" @@ -2100,6 +4330,24 @@ esutils@^2.0.2: resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== +event-target-shim@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789" + integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ== + +events@^3.2.0, events@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" + integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== + +evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02" + integrity sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA== + dependencies: + md5.js "^1.3.4" + safe-buffer "^5.1.1" + expect-type@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/expect-type/-/expect-type-1.1.0.tgz#a146e414250d13dfc49eafcfd1344a4060fa4c75" @@ -2137,6 +4385,11 @@ fast-glob@^3.3.0, fast-glob@^3.3.2: merge2 "^1.3.0" micromatch "^4.0.4" +fast-json-parse@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/fast-json-parse/-/fast-json-parse-1.0.3.tgz#43e5c61ee4efa9265633046b770fb682a7577c4d" + integrity sha512-FRWsaZRWEJ1ESVNbDWmsAlqDk96gPQezzLghafp5J4GUKjbCz3OkAHuZs5TuPEtkbVQERysLp9xv6c24fBm8Aw== + fast-json-stable-stringify@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" @@ -2147,6 +4400,11 @@ fast-levenshtein@^2.0.6: resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== +fast-uri@^3.0.1: + version "3.0.3" + resolved "https://registry.yarnpkg.com/fast-uri/-/fast-uri-3.0.3.tgz#892a1c91802d5d7860de728f18608a0573142241" + integrity sha512-aLrHthzCjH5He4Z2H9YZ+v6Ujb9ocRuW6ZzkJQOrTxleEijANq4v1TsaPaVG1PZcuurEzrLcWRyYBYXD5cEiaw== + fastq@^1.6.0: version "1.17.1" resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.17.1.tgz#2a523f07a4e7b1e81a42b91b8bf2254107753b47" @@ -2161,6 +4419,11 @@ file-entry-cache@^6.0.1: dependencies: flat-cache "^3.0.4" +filesize@^10.0.12: + version "10.1.6" + resolved "https://registry.yarnpkg.com/filesize/-/filesize-10.1.6.tgz#31194da825ac58689c0bce3948f33ce83aabd361" + integrity sha512-sJslQKU2uM33qH5nqewAwVB2QgR6w1aMNsYUp3aN5rMRyXEwJGmZvaWzeJFNTOXWlHQyBFCWrdj3fV/fsTOX8w== + fill-range@^7.1.1: version "7.1.1" resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" @@ -2168,6 +4431,36 @@ fill-range@^7.1.1: dependencies: to-regex-range "^5.0.1" +filter-obj@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/filter-obj/-/filter-obj-2.0.2.tgz#fff662368e505d69826abb113f0f6a98f56e9d5f" + integrity sha512-lO3ttPjHZRfjMcxWKb1j1eDhTFsu4meeR3lnMcnBFhk6RuLhvEiuALu2TlfL310ph4lCYYwgF/ElIjdP739tdg== + +find-cache-dir@^3.3.1: + version "3.3.2" + resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-3.3.2.tgz#b30c5b6eff0730731aea9bbd9dbecbd80256d64b" + integrity sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig== + dependencies: + commondir "^1.0.1" + make-dir "^3.0.2" + pkg-dir "^4.1.0" + +find-cache-dir@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-4.0.0.tgz#a30ee0448f81a3990708f6453633c733e2f6eec2" + integrity sha512-9ZonPT4ZAK4a+1pUPVPZJapbi7O5qbbJPdYw/NOQWZZbVLdDTYM3A4R9z/DpAM08IDaFGsvPgiGZ82WEwUDWjg== + dependencies: + common-path-prefix "^3.0.0" + pkg-dir "^7.0.0" + +find-up@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" + integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== + dependencies: + locate-path "^5.0.0" + path-exists "^4.0.0" + find-up@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" @@ -2176,6 +4469,14 @@ find-up@^5.0.0: locate-path "^6.0.0" path-exists "^4.0.0" +find-up@^6.3.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-6.3.0.tgz#2abab3d3280b2dc7ac10199ef324c4e002c8c790" + integrity sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw== + dependencies: + locate-path "^7.1.0" + path-exists "^5.0.0" + flat-cache@^3.0.4: version "3.2.0" resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.2.0.tgz#2c0c2d5040c99b1632771a9d105725c0115363ee" @@ -2205,6 +4506,24 @@ foreground-child@^3.1.0: cross-spawn "^7.0.0" signal-exit "^4.0.1" +fork-ts-checker-webpack-plugin@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-8.0.0.tgz#dae45dfe7298aa5d553e2580096ced79b6179504" + integrity sha512-mX3qW3idpueT2klaQXBzrIM/pHw+T0B/V9KHEvNrqijTq9NFnMZU6oreVxDYcf33P8a5cW+67PjodNHthGnNVg== + dependencies: + "@babel/code-frame" "^7.16.7" + chalk "^4.1.2" + chokidar "^3.5.3" + cosmiconfig "^7.0.1" + deepmerge "^4.2.2" + fs-extra "^10.0.0" + memfs "^3.4.1" + minimatch "^3.0.4" + node-abort-controller "^3.0.1" + schema-utils "^3.1.1" + semver "^7.3.5" + tapable "^2.2.1" + form-data@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.1.tgz#ba1076daaaa5bfd7e99c1a6cb02aa0a5cff90d48" @@ -2219,6 +4538,15 @@ fp-ts@^2.16.9: resolved "https://registry.yarnpkg.com/fp-ts/-/fp-ts-2.16.9.tgz#99628fc5e0bb3b432c4a16d8f4455247380bae8a" integrity sha512-+I2+FnVB+tVaxcYyQkHUq7ZdKScaBlX53A41mxQtpIccsfyv8PzdzP7fzp2AY832T4aoK6UZ5WRX/ebGd8uZuQ== +fs-extra@^10.0.0: + version "10.1.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.1.0.tgz#02873cfbc4084dde127eaa5f9905eef2325d1abf" + integrity sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ== + dependencies: + graceful-fs "^4.2.0" + jsonfile "^6.0.1" + universalify "^2.0.0" + fs-minipass@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb" @@ -2226,6 +4554,11 @@ fs-minipass@^2.0.0: dependencies: minipass "^3.0.0" +fs-monkey@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/fs-monkey/-/fs-monkey-1.0.6.tgz#8ead082953e88d992cf3ff844faa907b26756da2" + integrity sha512-b1FMfwetIKymC0eioW7mTywihSQE4oLzQn1dB6rZB5fx/3NpNEdAWeCSMB+60/AeT0TCXsxzAlcYVEFCTAksWg== + fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" @@ -2317,6 +4650,11 @@ glob-parent@^6.0.2: dependencies: is-glob "^4.0.3" +glob-to-regexp@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e" + integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw== + glob@^10.3.10: version "10.4.5" resolved "https://registry.yarnpkg.com/glob/-/glob-10.4.5.tgz#f4d9f0b90ffdbab09c9d77f5f29b4262517b0956" @@ -2368,7 +4706,7 @@ gopd@^1.0.1: dependencies: get-intrinsic "^1.1.3" -graceful-fs@^4.2.4: +graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.11, graceful-fs@^4.2.4: version "4.2.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== @@ -2417,6 +4755,31 @@ has-unicode@^2.0.1: resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" integrity sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ== +hash-base@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.1.0.tgz#55c381d9e06e1d2997a883b4a3fddfe7f0d3af33" + integrity sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA== + dependencies: + inherits "^2.0.4" + readable-stream "^3.6.0" + safe-buffer "^5.2.0" + +hash-base@~3.0, hash-base@~3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.0.4.tgz#5fc8686847ecd73499403319a6b0a3f3f6ae4918" + integrity sha512-EeeoJKjTyt868liAlVmcv2ZsUfGHlE3Q+BICOXcZiwN3osr5Q/zFGYmTJpoIzuaSTAwndFy+GqhEwlU4L3j4Ow== + dependencies: + inherits "^2.0.1" + safe-buffer "^5.0.1" + +hash.js@^1.0.0, hash.js@^1.0.3: + version "1.1.7" + resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" + integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA== + dependencies: + inherits "^2.0.3" + minimalistic-assert "^1.0.1" + hasown@^2.0.0, hasown@^2.0.1, hasown@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" @@ -2424,6 +4787,20 @@ hasown@^2.0.0, hasown@^2.0.1, hasown@^2.0.2: dependencies: function-bind "^1.1.2" +he@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" + integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== + +hmac-drbg@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" + integrity sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg== + dependencies: + hash.js "^1.0.3" + minimalistic-assert "^1.0.0" + minimalistic-crypto-utils "^1.0.1" + hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.2: version "3.3.2" resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45" @@ -2438,6 +4815,24 @@ html-encoding-sniffer@^4.0.0: dependencies: whatwg-encoding "^3.1.1" +html-entities@^2.1.0: + version "2.5.2" + resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-2.5.2.tgz#201a3cf95d3a15be7099521620d19dfb4f65359f" + integrity sha512-K//PSRMQk4FZ78Kyau+mZurHn3FH0Vwr+H36eE0rPbeYkRRi9YxceYPhuN60UwWorxyKHhqoAJl2OFKa4BVtaA== + +html-minifier-terser@^6.0.2: + version "6.1.0" + resolved "https://registry.yarnpkg.com/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz#bfc818934cc07918f6b3669f5774ecdfd48f32ab" + integrity sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw== + dependencies: + camel-case "^4.1.2" + clean-css "^5.2.2" + commander "^8.3.0" + he "^1.2.0" + param-case "^3.0.4" + relateurl "^0.2.7" + terser "^5.10.0" + html-parse-stringify@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/html-parse-stringify/-/html-parse-stringify-3.0.1.tgz#dfc1017347ce9f77c8141a507f233040c59c55d2" @@ -2445,6 +4840,27 @@ html-parse-stringify@^3.0.1: dependencies: void-elements "3.1.0" +html-webpack-plugin@^5.5.0: + version "5.6.3" + resolved "https://registry.yarnpkg.com/html-webpack-plugin/-/html-webpack-plugin-5.6.3.tgz#a31145f0fee4184d53a794f9513147df1e653685" + integrity sha512-QSf1yjtSAsmf7rYBV7XX86uua4W/vkhIt0xNXKbsi2foEeW7vjJQz4bhnpL3xH+l1ryl1680uNv968Z+X6jSYg== + dependencies: + "@types/html-minifier-terser" "^6.0.0" + html-minifier-terser "^6.0.2" + lodash "^4.17.21" + pretty-error "^4.0.0" + tapable "^2.0.0" + +htmlparser2@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-6.1.0.tgz#c4d762b6c3371a05dbe65e94ae43a9f845fb8fb7" + integrity sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A== + dependencies: + domelementtype "^2.0.1" + domhandler "^4.0.0" + domutils "^2.5.2" + entities "^2.0.0" + http-proxy-agent@^7.0.2: version "7.0.2" resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz#9a8b1f246866c028509486585f62b8f2c18c270e" @@ -2453,6 +4869,11 @@ http-proxy-agent@^7.0.2: agent-base "^7.1.0" debug "^4.3.4" +https-browserify@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73" + integrity sha512-J+FkSdyD+0mA0N+81tMotaRMfSL9SGi+xpD3T6YApKsc3bGSXJlfXri3VyFOeYkfLRQisDk1W+jIFFKBeUBbBg== + https-proxy-agent@^5.0.0: version "5.0.1" resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6" @@ -2497,12 +4918,29 @@ iconv-lite@0.6.3: dependencies: safer-buffer ">= 2.1.2 < 3.0.0" +icss-utils@^5.0.0, icss-utils@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-5.1.0.tgz#c6be6858abd013d768e98366ae47e25d5887b1ae" + integrity sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA== + +ieee754@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" + integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== + ignore@^5.2.0, ignore@^5.3.1: version "5.3.2" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.2.tgz#3cd40e729f3643fd87cb04e50bf0eb722bc596f5" integrity sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g== -import-fresh@^3.2.1: +image-size@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/image-size/-/image-size-1.1.1.tgz#ddd67d4dc340e52ac29ce5f546a09f4e29e840ac" + integrity sha512-541xKlUw6jr/6gGuk92F+mYM5zaFAc5ahphvkqvNe2bQ6gVBkd6bfrmVJ2t4KDAfikAYZyIqTnktX3i6/aQDrQ== + dependencies: + queue "6.0.2" + +import-fresh@^3.2.1, import-fresh@^3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== @@ -2515,6 +4953,11 @@ imurmurhash@^0.1.4: resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== +indent-string@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" + integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== + inflight@^1.0.4: version "1.0.6" resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" @@ -2523,7 +4966,7 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2, inherits@^2.0.3: +inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3, inherits@~2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== @@ -2537,6 +4980,14 @@ internal-slot@^1.0.7: hasown "^2.0.0" side-channel "^1.0.4" +is-arguments@^1.0.4: + version "1.1.1" + resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.1.tgz#15b3f88fda01f2a97fec84ca761a560f123efa9b" + integrity sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA== + dependencies: + call-bind "^1.0.2" + has-tostringtag "^1.0.0" + is-array-buffer@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/is-array-buffer/-/is-array-buffer-3.0.4.tgz#7a1f92b3d61edd2bc65d24f130530ea93d7fae98" @@ -2545,6 +4996,11 @@ is-array-buffer@^3.0.4: call-bind "^1.0.2" get-intrinsic "^1.2.1" +is-arrayish@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" + integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== + is-arrayish@^0.3.1: version "0.3.2" resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.3.2.tgz#4574a2ae56f7ab206896fb431eaeed066fdf8f03" @@ -2612,6 +5068,11 @@ is-date-object@^1.0.1, is-date-object@^1.0.5: dependencies: has-tostringtag "^1.0.0" +is-docker@^2.0.0, is-docker@^2.1.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa" + integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ== + is-extglob@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" @@ -2629,7 +5090,7 @@ is-fullwidth-code-point@^3.0.0: resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== -is-generator-function@^1.0.10: +is-generator-function@^1.0.10, is-generator-function@^1.0.7: version "1.0.10" resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.0.10.tgz#f1558baf1ac17e0deea7c0415c438351ff2b3c72" integrity sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A== @@ -2648,6 +5109,14 @@ is-map@^2.0.3: resolved "https://registry.yarnpkg.com/is-map/-/is-map-2.0.3.tgz#ede96b7fe1e270b3c4465e3a465658764926d62e" integrity sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw== +is-nan@^1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/is-nan/-/is-nan-1.3.2.tgz#043a54adea31748b55b6cd4e09aadafa69bd9e1d" + integrity sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w== + dependencies: + call-bind "^1.0.0" + define-properties "^1.1.3" + is-negative-zero@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.3.tgz#ced903a027aca6381b777a5743069d7376a49747" @@ -2709,7 +5178,7 @@ is-symbol@^1.0.2, is-symbol@^1.0.3: dependencies: has-symbols "^1.0.2" -is-typed-array@^1.1.13: +is-typed-array@^1.1.13, is-typed-array@^1.1.3: version "1.1.13" resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.13.tgz#d6c5ca56df62334959322d7d7dd1cca50debe229" integrity sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw== @@ -2736,11 +5205,23 @@ is-weakset@^2.0.3: call-bind "^1.0.7" get-intrinsic "^1.2.4" +is-wsl@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" + integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww== + dependencies: + is-docker "^2.0.0" + isarray@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723" integrity sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw== +isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== + isexe@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" @@ -2766,7 +5247,16 @@ jackspeak@^3.1.2: optionalDependencies: "@pkgjs/parseargs" "^0.11.0" -jiti@^1.21.0: +jest-worker@^27.4.5: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.5.1.tgz#8d146f0900e8973b106b6f73cc1e9a8cb86f8db0" + integrity sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg== + dependencies: + "@types/node" "*" + merge-stream "^2.0.0" + supports-color "^8.0.0" + +jiti@^1.20.0, jiti@^1.21.0: version "1.21.6" resolved "https://registry.yarnpkg.com/jiti/-/jiti-1.21.6.tgz#6c7f7398dd4b3142767f9a168af2f317a428d268" integrity sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w== @@ -2783,6 +5273,11 @@ js-yaml@^4.1.0: dependencies: argparse "^2.0.1" +jsdoc-type-pratt-parser@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-4.1.0.tgz#ff6b4a3f339c34a6c188cbf50a16087858d22113" + integrity sha512-Hicd6JK5Njt2QB6XYFS7ok9e37O8AYk3jTcppG4YVQnYjOemymvTcmc7OWsmq/Qqj5TdRFO5/x/tIPmBeRtGHg== + jsdom@^25.0.1: version "25.0.1" resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-25.0.1.tgz#536ec685c288fc8a5773a65f82d8b44badcc73ef" @@ -2810,7 +5305,7 @@ jsdom@^25.0.1: ws "^8.18.0" xml-name-validator "^5.0.0" -jsesc@^3.0.2: +jsesc@^3.0.2, jsesc@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-3.0.2.tgz#bb8b09a6597ba426425f2e4a07245c3d00b9343e" integrity sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g== @@ -2820,11 +5315,21 @@ json-buffer@3.0.1: resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== +json-parse-even-better-errors@^2.3.0, json-parse-even-better-errors@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" + integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== + json-schema-traverse@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== +json-schema-traverse@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" + integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== + json-stable-stringify-without-jsonify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" @@ -2837,11 +5342,20 @@ json5@^1.0.2: dependencies: minimist "^1.2.0" -json5@^2.2.3: +json5@^2.1.2, json5@^2.2.2, json5@^2.2.3: version "2.2.3" resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== +jsonfile@^6.0.1, jsonfile@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae" + integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ== + dependencies: + universalify "^2.0.0" + optionalDependencies: + graceful-fs "^4.1.6" + "jsx-ast-utils@^2.4.1 || ^3.0.0", jsx-ast-utils@^3.3.5: version "3.3.5" resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz#4766bd05a8e2a11af222becd19e15575e52a853a" @@ -2894,6 +5408,32 @@ lines-and-columns@^1.1.6: resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== +loader-runner@^4.2.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-4.3.0.tgz#c1b4a163b99f614830353b16755e7149ac2314e1" + integrity sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg== + +loader-utils@^2.0.0, loader-utils@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-2.0.4.tgz#8b5cb38b5c34a9a018ee1fc0e6a066d1dfcc528c" + integrity sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw== + dependencies: + big.js "^5.2.2" + emojis-list "^3.0.0" + json5 "^2.1.2" + +loader-utils@^3.2.1: + version "3.3.1" + resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-3.3.1.tgz#735b9a19fd63648ca7adbd31c2327dfe281304e5" + integrity sha512-FMJTLMXfCLMLfJxcX9PFqX5qD88Z5MRGaZCVzfuqeZSPsyiBzs+pahDQjbIWz2QIzPZz0NX9Zy4FX3lmK6YHIg== + +locate-path@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" + integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== + dependencies: + p-locate "^4.1.0" + locate-path@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" @@ -2901,23 +5441,47 @@ locate-path@^6.0.0: dependencies: p-locate "^5.0.0" +locate-path@^7.1.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-7.2.0.tgz#69cb1779bd90b35ab1e771e1f2f89a202c2a8a8a" + integrity sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA== + dependencies: + p-locate "^6.0.0" + +lodash.debounce@^4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" + integrity sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow== + lodash.merge@^4.6.2: version "4.6.2" resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== -loose-envify@^1.4.0: +lodash@^4.17.20, lodash@^4.17.21: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== + +loose-envify@^1.1.0, loose-envify@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== dependencies: js-tokens "^3.0.0 || ^4.0.0" -loupe@^3.1.0, loupe@^3.1.2: +loupe@^3.1.0, loupe@^3.1.1, loupe@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/loupe/-/loupe-3.1.2.tgz#c86e0696804a02218f2206124c45d8b15291a240" integrity sha512-23I4pFZHmAemUnz8WZXbYRSKYj801VDaNv9ETuMh7IrMc7VuVVSo+Z9iLE3ni30+U48iDWfi30d3twAXBYmnCg== +lower-case@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-2.0.2.tgz#6fa237c63dbdc4a82ca0fd882e4722dc5e634e28" + integrity sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg== + dependencies: + tslib "^2.0.3" + lru-cache@^10.2.0: version "10.4.3" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.4.3.tgz#410fc8a17b70e598013df257c2446b7f3383f119" @@ -2947,19 +5511,59 @@ magic-string@^0.30.12: dependencies: "@jridgewell/sourcemap-codec" "^1.5.0" -make-dir@^3.1.0: +magic-string@^0.30.5: + version "0.30.13" + resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.13.tgz#92438e3ff4946cf54f18247c981e5c161c46683c" + integrity sha512-8rYBO+MsWkgjDSOvLomYnzhdwEG51olQ4zL5KXnNJWV5MNmrb4rTZdrtkhxjnD/QyZUqR/Z/XDsUs/4ej2nx0g== + dependencies: + "@jridgewell/sourcemap-codec" "^1.5.0" + +make-dir@^3.0.2, make-dir@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== dependencies: semver "^6.0.0" +map-or-similar@^1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/map-or-similar/-/map-or-similar-1.5.0.tgz#6de2653174adfb5d9edc33c69d3e92a1b76faf08" + integrity sha512-0aF7ZmVon1igznGI4VS30yugpduQW3y3GkcgGJOp7d8x8QrizhigUxjI/m2UojsXXto+jLAH3KSz+xOJTiORjg== + +md5.js@^1.3.4: + version "1.3.5" + resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" + integrity sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg== + dependencies: + hash-base "^3.0.0" + inherits "^2.0.1" + safe-buffer "^5.1.2" + +memfs@^3.4.1, memfs@^3.4.12: + version "3.6.0" + resolved "https://registry.yarnpkg.com/memfs/-/memfs-3.6.0.tgz#d7a2110f86f79dd950a8b6df6d57bc984aa185f6" + integrity sha512-EGowvkkgbMcIChjMTMkESFDbZeSh8xZ7kNSF0hAiAN4Jh6jgHCRS0Ga/+C8y6Au+oqpezRHCfPsmJ2+DwAgiwQ== + dependencies: + fs-monkey "^1.0.4" + +memoizerific@^1.11.3: + version "1.11.3" + resolved "https://registry.yarnpkg.com/memoizerific/-/memoizerific-1.11.3.tgz#7c87a4646444c32d75438570905f2dbd1b1a805a" + integrity sha512-/EuHYwAPdLtXwAwSZkh/Gutery6pD2KYd44oQLhAvQp/50mpyduZh8Q7PYHXTCJ+wuXxt7oij2LXyIJOOYFPog== + dependencies: + map-or-similar "^1.5.0" + +merge-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" + integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== + merge2@^1.3.0: version "1.4.1" resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== -micromatch@^4.0.4, micromatch@^4.0.5: +micromatch@^4.0.2, micromatch@^4.0.4, micromatch@^4.0.5: version "4.0.8" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.8.tgz#d66fa18f3a47076789320b9b1af32bd86d9fa202" integrity sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA== @@ -2967,19 +5571,42 @@ micromatch@^4.0.4, micromatch@^4.0.5: braces "^3.0.3" picomatch "^2.3.1" +miller-rabin@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d" + integrity sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA== + dependencies: + bn.js "^4.0.0" + brorand "^1.0.1" + mime-db@1.52.0: version "1.52.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== -mime-types@^2.1.12: +mime-types@^2.1.12, mime-types@^2.1.27, mime-types@^2.1.31: version "2.1.35" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== dependencies: mime-db "1.52.0" -minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: +min-indent@^1.0.0, min-indent@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869" + integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg== + +minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" + integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== + +minimalistic-crypto-utils@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" + integrity sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg== + +minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== @@ -3064,6 +5691,11 @@ negotiator@^0.6.3: resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.4.tgz#777948e2452651c570b712dd01c23e262713fff7" integrity sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w== +neo-async@^2.6.2: + version "2.6.2" + resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" + integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== + next-i18n-router@^5.5.1: version "5.5.1" resolved "https://registry.yarnpkg.com/next-i18n-router/-/next-i18n-router-5.5.1.tgz#3d4c34d431e38aa4ba8f52cd54d4387fc70db6d2" @@ -3072,6 +5704,11 @@ next-i18n-router@^5.5.1: "@formatjs/intl-localematcher" "^0.5.2" negotiator "^0.6.3" +next-themes@^0.4.3: + version "0.4.3" + resolved "https://registry.yarnpkg.com/next-themes/-/next-themes-0.4.3.tgz#ea54552d5986936d177eed393ea50b658ae44800" + integrity sha512-nG84VPkTdUHR2YeD89YchvV4I9RbiMAql3GiLEQlPvq1ioaqPaIReK+yMRdg/zgiXws620qS1rU30TiWmmG9lA== + next@15.0.2: version "15.0.2" resolved "https://registry.yarnpkg.com/next/-/next-15.0.2.tgz#4a2224c007856118010b8cef5e9b2383cd743388" @@ -3095,6 +5732,19 @@ next@15.0.2: "@next/swc-win32-x64-msvc" "15.0.2" sharp "^0.33.5" +no-case@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/no-case/-/no-case-3.0.4.tgz#d361fd5c9800f558551a8369fc0dcd4662b6124d" + integrity sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg== + dependencies: + lower-case "^2.0.2" + tslib "^2.0.3" + +node-abort-controller@^3.0.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/node-abort-controller/-/node-abort-controller-3.1.1.tgz#a94377e964a9a37ac3976d848cb5c765833b8548" + integrity sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ== + node-addon-api@^5.0.0: version "5.1.0" resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-5.1.0.tgz#49da1ca055e109a23d537e9de43c09cca21eb762" @@ -3107,6 +5757,37 @@ node-fetch@^2.6.7: dependencies: whatwg-url "^5.0.0" +node-polyfill-webpack-plugin@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/node-polyfill-webpack-plugin/-/node-polyfill-webpack-plugin-2.0.1.tgz#141d86f177103a8517c71d99b7c6a46edbb1bb58" + integrity sha512-ZUMiCnZkP1LF0Th2caY6J/eKKoA0TefpoVa68m/LQU1I/mE8rGt4fNYGgNuCcK+aG8P8P43nbeJ2RqJMOL/Y1A== + dependencies: + assert "^2.0.0" + browserify-zlib "^0.2.0" + buffer "^6.0.3" + console-browserify "^1.2.0" + constants-browserify "^1.0.0" + crypto-browserify "^3.12.0" + domain-browser "^4.22.0" + events "^3.3.0" + filter-obj "^2.0.2" + https-browserify "^1.0.0" + os-browserify "^0.3.0" + path-browserify "^1.0.1" + process "^0.11.10" + punycode "^2.1.1" + querystring-es3 "^0.2.1" + readable-stream "^4.0.0" + stream-browserify "^3.0.0" + stream-http "^3.2.0" + string_decoder "^1.3.0" + timers-browserify "^2.0.12" + tty-browserify "^0.0.1" + type-fest "^2.14.0" + url "^0.11.0" + util "^0.12.4" + vm-browserify "^1.1.2" + node-releases@^2.0.18: version "2.0.18" resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.18.tgz#f010e8d35e2fe8d6b2944f03f70213ecedc4ca3f" @@ -3134,6 +5815,13 @@ npmlog@^5.0.1: gauge "^3.0.0" set-blocking "^2.0.0" +nth-check@^2.0.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-2.1.1.tgz#c9eab428effce36cd6b92c924bdb000ef1f1ed1d" + integrity sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w== + dependencies: + boolbase "^1.0.0" + nwsapi@^2.2.12: version "2.2.13" resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.13.tgz#e56b4e98960e7a040e5474536587e599c4ff4655" @@ -3154,6 +5842,14 @@ object-inspect@^1.13.1: resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.2.tgz#dea0088467fb991e67af4058147a24824a3043ff" integrity sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g== +object-is@^1.1.5: + version "1.1.6" + resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.6.tgz#1a6a53aed2dd8f7e6775ff870bea58545956ab07" + integrity sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + object-keys@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" @@ -3206,6 +5902,11 @@ object.values@^1.1.6, object.values@^1.2.0: define-properties "^1.2.1" es-object-atoms "^1.0.0" +objectorarray@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/objectorarray/-/objectorarray-1.0.5.tgz#2c05248bbefabd8f43ad13b41085951aac5e68a5" + integrity sha512-eJJDYkhJFFbBBAxeh8xW+weHlkI28n2ZdQV/J/DNfWfSKlGEf2xcfAbZTv3riEXHAhL9SVOTs2pRmXiSTf78xg== + once@^1.3.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" @@ -3213,6 +5914,15 @@ once@^1.3.0: dependencies: wrappy "1" +open@^8.0.4: + version "8.4.2" + resolved "https://registry.yarnpkg.com/open/-/open-8.4.2.tgz#5b5ffe2a8f793dcd2aad73e550cb87b59cb084f9" + integrity sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ== + dependencies: + define-lazy-prop "^2.0.0" + is-docker "^2.1.1" + is-wsl "^2.2.0" + optionator@^0.9.3: version "0.9.4" resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.4.tgz#7ea1c1a5d91d764fb282139c88fe11e182a3a734" @@ -3225,6 +5935,18 @@ optionator@^0.9.3: type-check "^0.4.0" word-wrap "^1.2.5" +os-browserify@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27" + integrity sha512-gjcpUc3clBf9+210TRaDWbf+rZZZEshZ+DlXMRCeAjp0xhTrnQsKHypIy1J3d5hKdUzj69t708EHtU8P6bUn0A== + +p-limit@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" + integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== + dependencies: + p-try "^2.0.0" + p-limit@^3.0.2: version "3.1.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" @@ -3232,6 +5954,20 @@ p-limit@^3.0.2: dependencies: yocto-queue "^0.1.0" +p-limit@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-4.0.0.tgz#914af6544ed32bfa54670b061cafcbd04984b644" + integrity sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ== + dependencies: + yocto-queue "^1.0.0" + +p-locate@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" + integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== + dependencies: + p-limit "^2.2.0" + p-locate@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" @@ -3239,11 +5975,36 @@ p-locate@^5.0.0: dependencies: p-limit "^3.0.2" +p-locate@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-6.0.0.tgz#3da9a49d4934b901089dca3302fa65dc5a05c04f" + integrity sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw== + dependencies: + p-limit "^4.0.0" + +p-try@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" + integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== + package-json-from-dist@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz#4f1471a010827a86f94cfd9b0727e36d267de505" integrity sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw== +pako@~1.0.5: + version "1.0.11" + resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf" + integrity sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw== + +param-case@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/param-case/-/param-case-3.0.4.tgz#7d17fe4aa12bde34d4a77d91acfb6219caad01c5" + integrity sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A== + dependencies: + dot-case "^3.0.4" + tslib "^2.0.3" + parent-module@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" @@ -3251,6 +6012,28 @@ parent-module@^1.0.0: dependencies: callsites "^3.0.0" +parse-asn1@^5.0.0, parse-asn1@^5.1.7: + version "5.1.7" + resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.7.tgz#73cdaaa822125f9647165625eb45f8a051d2df06" + integrity sha512-CTM5kuWR3sx9IFamcl5ErfPl6ea/N8IYwiJ+vpeB2g+1iknv7zBl5uPwbMbRVznRVbrNY6lGuDoE5b30grmbqg== + dependencies: + asn1.js "^4.10.1" + browserify-aes "^1.2.0" + evp_bytestokey "^1.0.3" + hash-base "~3.0" + pbkdf2 "^3.1.2" + safe-buffer "^5.2.1" + +parse-json@^5.0.0, parse-json@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" + integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== + dependencies: + "@babel/code-frame" "^7.0.0" + error-ex "^1.3.1" + json-parse-even-better-errors "^2.3.0" + lines-and-columns "^1.1.6" + parse5@^7.1.2: version "7.2.1" resolved "https://registry.yarnpkg.com/parse5/-/parse5-7.2.1.tgz#8928f55915e6125f430cc44309765bf17556a33a" @@ -3258,11 +6041,29 @@ parse5@^7.1.2: dependencies: entities "^4.5.0" +pascal-case@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/pascal-case/-/pascal-case-3.1.2.tgz#b48e0ef2b98e205e7c1dae747d0b1508237660eb" + integrity sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g== + dependencies: + no-case "^3.0.4" + tslib "^2.0.3" + +path-browserify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-1.0.1.tgz#d98454a9c3753d5790860f16f68867b9e46be1fd" + integrity sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g== + path-exists@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== +path-exists@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-5.0.0.tgz#a6aad9489200b21fab31e49cf09277e5116fb9e7" + integrity sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ== + path-is-absolute@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" @@ -3286,6 +6087,11 @@ path-scurry@^1.11.1: lru-cache "^10.2.0" minipass "^5.0.0 || ^6.0.2 || ^7.0.0" +path-type@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" + integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== + pathe@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/pathe/-/pathe-1.1.2.tgz#6c4cb47a945692e48a1ddd6e4094d170516437ec" @@ -3296,7 +6102,18 @@ pathval@^2.0.0: resolved "https://registry.yarnpkg.com/pathval/-/pathval-2.0.0.tgz#7e2550b422601d4f6b8e26f1301bc8f15a741a25" integrity sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA== -picocolors@^1.0.0, picocolors@^1.1.0: +pbkdf2@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.1.2.tgz#dd822aa0887580e52f1a039dc3eda108efae3075" + integrity sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA== + dependencies: + create-hash "^1.1.2" + create-hmac "^1.1.4" + ripemd160 "^2.0.1" + safe-buffer "^5.0.1" + sha.js "^2.4.8" + +picocolors@^1.0.0, picocolors@^1.1.0, picocolors@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b" integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA== @@ -3316,6 +6133,34 @@ pirates@^4.0.1: resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.6.tgz#3018ae32ecfcff6c29ba2267cbf21166ac1f36b9" integrity sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg== +pkg-dir@^4.1.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" + integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== + dependencies: + find-up "^4.0.0" + +pkg-dir@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-7.0.0.tgz#8f0c08d6df4476756c5ff29b3282d0bab7517d11" + integrity sha512-Ie9z/WINcxxLp27BKOCHGde4ITq9UklYKDzVo1nhk5sqGEXU3FpkwP5GM2voTGJkGd9B3Otl+Q4uwSOeSUtOBA== + dependencies: + find-up "^6.3.0" + +pnp-webpack-plugin@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/pnp-webpack-plugin/-/pnp-webpack-plugin-1.7.0.tgz#65741384f6d8056f36e2255a8d67ffc20866f5c9" + integrity sha512-2Rb3vm+EXble/sMXNSu6eoBx8e79gKqhNq9F5ZWW6ERNCTE/Q0wQNne5541tE5vKjfM8hpNCYL+LGc1YTfI0dg== + dependencies: + ts-pnp "^1.1.6" + +polished@^4.2.2: + version "4.3.1" + resolved "https://registry.yarnpkg.com/polished/-/polished-4.3.1.tgz#5a00ae32715609f83d89f6f31d0f0261c6170548" + integrity sha512-OBatVyC/N7SCW/FaDHrSd+vn0o5cS855TOmYi4OkdWUMSJCET/xip//ch8xGUvtr3i44X9LVyWwQlRMTN3pwSA== + dependencies: + "@babel/runtime" "^7.17.8" + possible-typed-array-names@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz#89bb63c6fada2c3e90adc4a647beeeb39cc7bf8f" @@ -3345,6 +6190,43 @@ postcss-load-config@^4.0.1: lilconfig "^3.0.0" yaml "^2.3.4" +postcss-loader@^8.1.1: + version "8.1.1" + resolved "https://registry.yarnpkg.com/postcss-loader/-/postcss-loader-8.1.1.tgz#2822589e7522927344954acb55bbf26e8b195dfe" + integrity sha512-0IeqyAsG6tYiDRCYKQJLAmgQr47DX6N7sFSWvQxt6AcupX8DIdmykuk/o/tx0Lze3ErGHJEp5OSRxrelC6+NdQ== + dependencies: + cosmiconfig "^9.0.0" + jiti "^1.20.0" + semver "^7.5.4" + +postcss-modules-extract-imports@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.1.0.tgz#b4497cb85a9c0c4b5aabeb759bb25e8d89f15002" + integrity sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q== + +postcss-modules-local-by-default@^4.0.5: + version "4.1.0" + resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.1.0.tgz#b0db6bc81ffc7bdc52eb0f84d6ca0bedf0e36d21" + integrity sha512-rm0bdSv4jC3BDma3s9H19ZddW0aHX6EoqwDYU2IfZhRN+53QrufTRo2IdkAbRqLx4R2IYbZnbjKKxg4VN5oU9Q== + dependencies: + icss-utils "^5.0.0" + postcss-selector-parser "^7.0.0" + postcss-value-parser "^4.1.0" + +postcss-modules-scope@^3.2.0: + version "3.2.1" + resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-3.2.1.tgz#1bbccddcb398f1d7a511e0a2d1d047718af4078c" + integrity sha512-m9jZstCVaqGjTAuny8MdgE88scJnCiQSlSrOWcTQgM2t32UBe+MUmFSO5t7VMSfAf/FJKImAxBav8ooCHJXCJA== + dependencies: + postcss-selector-parser "^7.0.0" + +postcss-modules-values@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz#d7c5e7e68c3bb3c9b27cbf48ca0bb3ffb4602c9c" + integrity sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ== + dependencies: + icss-utils "^5.0.0" + postcss-nested@^6.0.1: version "6.2.0" resolved "https://registry.yarnpkg.com/postcss-nested/-/postcss-nested-6.2.0.tgz#4c2d22ab5f20b9cb61e2c5c5915950784d068131" @@ -3360,7 +6242,15 @@ postcss-selector-parser@^6.0.11, postcss-selector-parser@^6.1.1: cssesc "^3.0.0" util-deprecate "^1.0.2" -postcss-value-parser@^4.0.0: +postcss-selector-parser@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-7.0.0.tgz#41bd8b56f177c093ca49435f65731befe25d6b9c" + integrity sha512-9RbEr1Y7FFfptd/1eEdntyjMwLeghW1bHX9GWjXo19vx4ytPQhANltvVxDggzJl7mnWM+dX28kb6cyS/4iQjlQ== + dependencies: + cssesc "^3.0.0" + util-deprecate "^1.0.2" + +postcss-value-parser@^4.0.0, postcss-value-parser@^4.1.0, postcss-value-parser@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514" integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ== @@ -3383,6 +6273,15 @@ postcss@^8, postcss@^8.4.23, postcss@^8.4.43: picocolors "^1.1.0" source-map-js "^1.2.1" +postcss@^8.2.14, postcss@^8.4.33, postcss@^8.4.38: + version "8.4.49" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.49.tgz#4ea479048ab059ab3ae61d082190fabfd994fe19" + integrity sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA== + dependencies: + nanoid "^3.3.7" + picocolors "^1.1.1" + source-map-js "^1.2.1" + postgres@^3.4.5: version "3.4.5" resolved "https://registry.yarnpkg.com/postgres/-/postgres-3.4.5.tgz#1ef99e51b0ba9b53cbda8a215dd406725f7d15f9" @@ -3405,6 +6304,14 @@ prettier@^3.3.3: resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.3.3.tgz#30c54fe0be0d8d12e6ae61dbb10109ea00d53105" integrity sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew== +pretty-error@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/pretty-error/-/pretty-error-4.0.0.tgz#90a703f46dd7234adb46d0f84823e9d1cb8f10d6" + integrity sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw== + dependencies: + lodash "^4.17.20" + renderkid "^3.0.0" + pretty-format@^27.0.2: version "27.5.1" resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-27.5.1.tgz#2181879fdea51a7a5851fb39d920faa63f01d88e" @@ -3414,6 +6321,16 @@ pretty-format@^27.0.2: ansi-styles "^5.0.0" react-is "^17.0.1" +process-nextick-args@~2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" + integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== + +process@^0.11.10: + version "0.11.10" + resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" + integrity sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A== + prop-types@^15.8.1: version "15.8.1" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" @@ -3423,16 +6340,79 @@ prop-types@^15.8.1: object-assign "^4.1.1" react-is "^16.13.1" -punycode@^2.1.0, punycode@^2.3.1: +public-encrypt@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/public-encrypt/-/public-encrypt-4.0.3.tgz#4fcc9d77a07e48ba7527e7cbe0de33d0701331e0" + integrity sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q== + dependencies: + bn.js "^4.1.0" + browserify-rsa "^4.0.0" + create-hash "^1.1.0" + parse-asn1 "^5.0.0" + randombytes "^2.0.1" + safe-buffer "^5.1.2" + +punycode@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" + integrity sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ== + +punycode@^2.1.0, punycode@^2.1.1, punycode@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== +qs@^6.12.3: + version "6.13.1" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.13.1.tgz#3ce5fc72bd3a8171b85c99b93c65dd20b7d1b16e" + integrity sha512-EJPeIn0CYrGu+hli1xilKAPXODtJ12T0sP63Ijx2/khC2JtuaN3JyNIpvmnkmaEtha9ocbG4A4cMcr+TvqvwQg== + dependencies: + side-channel "^1.0.6" + +querystring-es3@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73" + integrity sha512-773xhDQnZBMFobEiztv8LIl70ch5MSF/jUQVlhwFyBILqq96anmoctVIYz+ZRp0qbCKATTn6ev02M3r7Ga5vqA== + queue-microtask@^1.2.2: version "1.2.3" resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== +queue@6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/queue/-/queue-6.0.2.tgz#b91525283e2315c7553d2efa18d83e76432fed65" + integrity sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA== + dependencies: + inherits "~2.0.3" + +randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5, randombytes@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" + integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== + dependencies: + safe-buffer "^5.1.0" + +randomfill@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/randomfill/-/randomfill-1.0.4.tgz#c92196fc86ab42be983f1bf31778224931d61458" + integrity sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw== + dependencies: + randombytes "^2.0.5" + safe-buffer "^5.1.0" + +range-parser@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" + integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== + +react-confetti@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/react-confetti/-/react-confetti-6.1.0.tgz#03dc4340d955acd10b174dbf301f374a06e29ce6" + integrity sha512-7Ypx4vz0+g8ECVxr88W9zhcQpbeujJAVqL14ZnXJ3I23mOI9/oBVTQ3dkJhUmB0D6XOtCZEM6N0Gm9PMngkORw== + dependencies: + tween-functions "^1.2.0" + react-cookie@^7.2.2: version "7.2.2" resolved "https://registry.yarnpkg.com/react-cookie/-/react-cookie-7.2.2.tgz#a7559e552ea9cca39a4b3686723a5acf504b8f84" @@ -3442,6 +6422,27 @@ react-cookie@^7.2.2: hoist-non-react-statics "^3.3.2" universal-cookie "^7.0.0" +react-docgen-typescript@^2.2.2: + version "2.2.2" + resolved "https://registry.yarnpkg.com/react-docgen-typescript/-/react-docgen-typescript-2.2.2.tgz#4611055e569edc071204aadb20e1c93e1ab1659c" + integrity sha512-tvg2ZtOpOi6QDwsb3GZhOjDkkX0h8Z2gipvTg6OVMUyoYoURhEiRNePT8NZItTVCDh39JJHnLdfCOkzoLbFnTg== + +react-docgen@^7.0.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/react-docgen/-/react-docgen-7.1.0.tgz#4b41e557dab939a5157be09ee532fd09c07d99fc" + integrity sha512-APPU8HB2uZnpl6Vt/+0AFoVYgSRtfiP6FLrZgPPTDmqSb2R4qZRbgd0A3VzIFxDt5e+Fozjx79WjLWnF69DK8g== + dependencies: + "@babel/core" "^7.18.9" + "@babel/traverse" "^7.18.9" + "@babel/types" "^7.18.9" + "@types/babel__core" "^7.18.0" + "@types/babel__traverse" "^7.18.0" + "@types/doctrine" "^0.0.9" + "@types/resolve" "^1.20.2" + doctrine "^3.0.0" + resolve "^1.22.1" + strip-indent "^4.0.0" + react-dom@19.0.0-rc-69d4b800-20241021: version "19.0.0-rc-69d4b800-20241021" resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-19.0.0-rc-69d4b800-20241021.tgz#e27b4f2c962236e9ece496a0ea1c9c7161608ea0" @@ -3449,6 +6450,14 @@ react-dom@19.0.0-rc-69d4b800-20241021: dependencies: scheduler "0.25.0-rc-69d4b800-20241021" +"react-dom@^16.8.0 || ^17.0.0 || ^18.0.0": + version "18.3.1" + resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.3.1.tgz#c2265d79511b57d479b3dd3fdfa51536494c5cb4" + integrity sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw== + dependencies: + loose-envify "^1.1.0" + scheduler "^0.23.2" + react-i18next@^15.1.0: version "15.1.0" resolved "https://registry.yarnpkg.com/react-i18next/-/react-i18next-15.1.0.tgz#9494e4add2389f04c205dd7628c1aa75747b98a3" @@ -3467,7 +6476,7 @@ react-is@^17.0.1: resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0" integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w== -react-refresh@^0.14.2: +react-refresh@^0.14.0, react-refresh@^0.14.2: version "0.14.2" resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.14.2.tgz#3833da01ce32da470f1f936b9d477da5c7028bf9" integrity sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA== @@ -3477,6 +6486,13 @@ react@19.0.0-rc-69d4b800-20241021: resolved "https://registry.yarnpkg.com/react/-/react-19.0.0-rc-69d4b800-20241021.tgz#2c3ce2a581df8c4c9e4059189af29b89022edd41" integrity sha512-dXki4tN+rP+4xhsm65q/QI/19VCZdu5vPcy4h6zaJt20XP8/1r/LCwrLFYuj8hElbNz5AmxW6JtRa7ej0BzZdg== +"react@^16.8.0 || ^17.0.0 || ^18.0.0": + version "18.3.1" + resolved "https://registry.yarnpkg.com/react/-/react-18.3.1.tgz#49ab892009c53933625bd16b2533fc754cab2891" + integrity sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ== + dependencies: + loose-envify "^1.1.0" + read-cache@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/read-cache/-/read-cache-1.0.0.tgz#e664ef31161166c9751cdbe8dbcf86b5fb58f774" @@ -3484,7 +6500,20 @@ read-cache@^1.0.0: dependencies: pify "^2.3.0" -readable-stream@^3.6.0: +readable-stream@^2.3.8: + version "2.3.8" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b" + integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.1.1" + util-deprecate "~1.0.1" + +readable-stream@^3.5.0, readable-stream@^3.6.0: version "3.6.2" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== @@ -3493,6 +6522,17 @@ readable-stream@^3.6.0: string_decoder "^1.1.1" util-deprecate "^1.0.1" +readable-stream@^4.0.0: + version "4.5.2" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-4.5.2.tgz#9e7fc4c45099baeed934bff6eb97ba6cf2729e09" + integrity sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g== + dependencies: + abort-controller "^3.0.0" + buffer "^6.0.3" + events "^3.3.0" + process "^0.11.10" + string_decoder "^1.3.0" + readdirp@~3.6.0: version "3.6.0" resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" @@ -3500,6 +6540,25 @@ readdirp@~3.6.0: dependencies: picomatch "^2.2.1" +recast@^0.23.5: + version "0.23.9" + resolved "https://registry.yarnpkg.com/recast/-/recast-0.23.9.tgz#587c5d3a77c2cfcb0c18ccce6da4361528c2587b" + integrity sha512-Hx/BGIbwj+Des3+xy5uAtAbdCyqK9y9wbBcDFDYanLS9JnMqf7OeF87HQwUimE87OEc72mr6tkKUKMBBL+hF9Q== + dependencies: + ast-types "^0.16.1" + esprima "~4.0.0" + source-map "~0.6.1" + tiny-invariant "^1.3.3" + tslib "^2.0.1" + +redent@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/redent/-/redent-3.0.0.tgz#e557b7998316bb53c9f1f56fa626352c6963059f" + integrity sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg== + dependencies: + indent-string "^4.0.0" + strip-indent "^3.0.0" + reflect-metadata@^0.2.2: version "0.2.2" resolved "https://registry.yarnpkg.com/reflect-metadata/-/reflect-metadata-0.2.2.tgz#400c845b6cba87a21f2c65c4aeb158f4fa4d9c5b" @@ -3518,11 +6577,35 @@ reflect.getprototypeof@^1.0.4: globalthis "^1.0.3" which-builtin-type "^1.1.3" +regenerate-unicode-properties@^10.2.0: + version "10.2.0" + resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-10.2.0.tgz#626e39df8c372338ea9b8028d1f99dc3fd9c3db0" + integrity sha512-DqHn3DwbmmPVzeKj9woBadqmXxLvQoQIwu7nopMc72ztvxVmVk2SBhSnx67zuye5TP+lJsb/TBQsjLKhnDf3MA== + dependencies: + regenerate "^1.4.2" + +regenerate@^1.4.2: + version "1.4.2" + resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.2.tgz#b9346d8827e8f5a32f7ba29637d398b69014848a" + integrity sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A== + regenerator-runtime@^0.14.0: version "0.14.1" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz#356ade10263f685dda125100cd862c1db895327f" integrity sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw== +regenerator-transform@^0.15.2: + version "0.15.2" + resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.15.2.tgz#5bbae58b522098ebdf09bca2f83838929001c7a4" + integrity sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg== + dependencies: + "@babel/runtime" "^7.8.4" + +regex-parser@^2.2.11: + version "2.3.0" + resolved "https://registry.yarnpkg.com/regex-parser/-/regex-parser-2.3.0.tgz#4bb61461b1a19b8b913f3960364bb57887f920ee" + integrity sha512-TVILVSz2jY5D47F4mA4MppkBrafEaiUWJO/TcZHEIuI13AqoZMkK1WMA4Om1YkYbTx+9Ki1/tSUXbceyr9saRg== + regexp.prototype.flags@^1.5.2: version "1.5.3" resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.5.3.tgz#b3ae40b1d2499b8350ab2c3fe6ef3845d3a96f42" @@ -3533,6 +6616,51 @@ regexp.prototype.flags@^1.5.2: es-errors "^1.3.0" set-function-name "^2.0.2" +regexpu-core@^6.1.1: + version "6.1.1" + resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-6.1.1.tgz#b469b245594cb2d088ceebc6369dceb8c00becac" + integrity sha512-k67Nb9jvwJcJmVpw0jPttR1/zVfnKf8Km0IPatrU/zJ5XeG3+Slx0xLXs9HByJSzXzrlz5EDvN6yLNMDc2qdnw== + dependencies: + regenerate "^1.4.2" + regenerate-unicode-properties "^10.2.0" + regjsgen "^0.8.0" + regjsparser "^0.11.0" + unicode-match-property-ecmascript "^2.0.0" + unicode-match-property-value-ecmascript "^2.1.0" + +regjsgen@^0.8.0: + version "0.8.0" + resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.8.0.tgz#df23ff26e0c5b300a6470cad160a9d090c3a37ab" + integrity sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q== + +regjsparser@^0.11.0: + version "0.11.2" + resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.11.2.tgz#7404ad42be00226d72bcf1f003f1f441861913d8" + integrity sha512-3OGZZ4HoLJkkAZx/48mTXJNlmqTGOzc0o9OWQPuWpkOlXXPbyN6OafCcoXUnBqE2D3f/T5L+pWc1kdEmnfnRsA== + dependencies: + jsesc "~3.0.2" + +relateurl@^0.2.7: + version "0.2.7" + resolved "https://registry.yarnpkg.com/relateurl/-/relateurl-0.2.7.tgz#54dbf377e51440aca90a4cd274600d3ff2d888a9" + integrity sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog== + +renderkid@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/renderkid/-/renderkid-3.0.0.tgz#5fd823e4d6951d37358ecc9a58b1f06836b6268a" + integrity sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg== + dependencies: + css-select "^4.1.3" + dom-converter "^0.2.0" + htmlparser2 "^6.1.0" + lodash "^4.17.21" + strip-ansi "^6.0.1" + +require-from-string@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" + integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== + resolve-from@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" @@ -3543,7 +6671,18 @@ resolve-pkg-maps@^1.0.0: resolved "https://registry.yarnpkg.com/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz#616b3dc2c57056b5588c31cdf4b3d64db133720f" integrity sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw== -resolve@^1.1.7, resolve@^1.22.2, resolve@^1.22.4: +resolve-url-loader@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/resolve-url-loader/-/resolve-url-loader-5.0.0.tgz#ee3142fb1f1e0d9db9524d539cfa166e9314f795" + integrity sha512-uZtduh8/8srhBoMx//5bwqjQ+rfYOUq8zC9NrMUGtjBiGTtFJM42s58/36+hTqeqINcnYe08Nj3LkK9lW4N8Xg== + dependencies: + adjust-sourcemap-loader "^4.0.0" + convert-source-map "^1.7.0" + loader-utils "^2.0.0" + postcss "^8.2.14" + source-map "0.6.1" + +resolve@^1.1.7, resolve@^1.14.2, resolve@^1.22.1, resolve@^1.22.2, resolve@^1.22.4, resolve@^1.22.8: version "1.22.8" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d" integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== @@ -3573,6 +6712,14 @@ rimraf@^3.0.2: dependencies: glob "^7.1.3" +ripemd160@^2.0.0, ripemd160@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" + integrity sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA== + dependencies: + hash-base "^3.0.0" + inherits "^2.0.1" + rollup@^4.20.0: version "4.24.3" resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.24.3.tgz#8b259063740af60b0030315f88665ba2041789b8" @@ -3622,11 +6769,16 @@ safe-array-concat@^1.1.2: has-symbols "^1.0.3" isarray "^2.0.5" -safe-buffer@~5.2.0: +safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@^5.2.1, safe-buffer@~5.2.0: version "5.2.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== +safe-buffer@~5.1.0, safe-buffer@~5.1.1: + version "5.1.2" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== + safe-regex-test@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/safe-regex-test/-/safe-regex-test-1.0.3.tgz#a5b4c0f06e0ab50ea2c395c14d8371232924c377" @@ -3641,6 +6793,13 @@ safe-regex-test@^1.0.3: resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== +sass-loader@^13.2.0: + version "13.3.3" + resolved "https://registry.yarnpkg.com/sass-loader/-/sass-loader-13.3.3.tgz#60df5e858788cffb1a3215e5b92e9cba61e7e133" + integrity sha512-mt5YN2F1MOZr3d/wBRcZxeFgwgkH44wVc2zohO2YF6JiOMkiXe4BYRZpSu2sO1g71mo/j16txzUhsKZlqjVGzA== + dependencies: + neo-async "^2.6.2" + saxes@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/saxes/-/saxes-6.0.0.tgz#fe5b4a4768df4f14a201b1ba6a65c1f3d9988cc5" @@ -3653,16 +6812,49 @@ scheduler@0.25.0-rc-69d4b800-20241021: resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.25.0-rc-69d4b800-20241021.tgz#336e47ef2bd5eddb0ebacfd910b5df1b236d92bd" integrity sha512-S5AYX/YhMAN6u9AXgKYbZP4U4ZklC6R9Q7HmFSBk7d4DLiHVNxvAvlSvuM4nxFkwOk50MnpfTKQ7UWHXDOc9Eg== +scheduler@^0.23.2: + version "0.23.2" + resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.23.2.tgz#414ba64a3b282892e944cf2108ecc078d115cdc3" + integrity sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ== + dependencies: + loose-envify "^1.1.0" + +schema-utils@^3.1.1, schema-utils@^3.2.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.3.0.tgz#f50a88877c3c01652a15b622ae9e9795df7a60fe" + integrity sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg== + dependencies: + "@types/json-schema" "^7.0.8" + ajv "^6.12.5" + ajv-keywords "^3.5.2" + +schema-utils@^4.0.0, schema-utils@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-4.2.0.tgz#70d7c93e153a273a805801882ebd3bff20d89c8b" + integrity sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw== + dependencies: + "@types/json-schema" "^7.0.9" + ajv "^8.9.0" + ajv-formats "^2.1.1" + ajv-keywords "^5.1.0" + semver@^6.0.0, semver@^6.3.0, semver@^6.3.1: version "6.3.1" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== -semver@^7.3.5, semver@^7.6.0, semver@^7.6.3: +semver@^7.3.5, semver@^7.3.7, semver@^7.5.4, semver@^7.6.0, semver@^7.6.2, semver@^7.6.3: version "7.6.3" resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.3.tgz#980f7b5550bc175fb4dc09403085627f9eb33143" integrity sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A== +serialize-javascript@^6.0.1: + version "6.0.2" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.2.tgz#defa1e055c83bf6d59ea805d8da862254eb6a6c2" + integrity sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g== + dependencies: + randombytes "^2.1.0" + server-only@^0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/server-only/-/server-only-0.0.1.tgz#0f366bb6afb618c37c9255a314535dc412cd1c9e" @@ -3695,7 +6887,20 @@ set-function-name@^2.0.1, set-function-name@^2.0.2: functions-have-names "^1.2.3" has-property-descriptors "^1.0.2" -sharp@^0.33.5: +setimmediate@^1.0.4: + version "1.0.5" + resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" + integrity sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA== + +sha.js@^2.4.0, sha.js@^2.4.8: + version "2.4.11" + resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7" + integrity sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ== + dependencies: + inherits "^2.0.1" + safe-buffer "^5.0.1" + +sharp@^0.33.3, sharp@^0.33.5: version "0.33.5" resolved "https://registry.yarnpkg.com/sharp/-/sharp-0.33.5.tgz#13e0e4130cc309d6a9497596715240b2ec0c594e" integrity sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw== @@ -3773,16 +6978,78 @@ source-map-js@^1.0.2, source-map-js@^1.2.1: resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.1.tgz#1ce5650fddd87abc099eda37dcff024c2667ae46" integrity sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA== +source-map-support@~0.5.20: + version "0.5.21" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" + integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +source-map@0.6.1, source-map@^0.6.0, source-map@~0.6.0, source-map@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + +source-map@^0.7.3: + version "0.7.4" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.4.tgz#a9bbe705c9d8846f4e08ff6765acf0f1b0898656" + integrity sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA== + stackback@0.0.2: version "0.0.2" resolved "https://registry.yarnpkg.com/stackback/-/stackback-0.0.2.tgz#1ac8a0d9483848d1695e418b6d031a3c3ce68e3b" integrity sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw== +stackframe@^1.3.4: + version "1.3.4" + resolved "https://registry.yarnpkg.com/stackframe/-/stackframe-1.3.4.tgz#b881a004c8c149a5e8efef37d51b16e412943310" + integrity sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw== + std-env@^3.7.0: version "3.7.0" resolved "https://registry.yarnpkg.com/std-env/-/std-env-3.7.0.tgz#c9f7386ced6ecf13360b6c6c55b8aaa4ef7481d2" integrity sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg== +storybook-dark-mode@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/storybook-dark-mode/-/storybook-dark-mode-4.0.2.tgz#2536d1a229ac050172d37aa50bd9f6f7cdad0425" + integrity sha512-zjcwwQ01R5t1VsakA6alc2JDIRVtavryW8J3E3eKLDIlAMcvsgtpxlelWkZs2cuNspk6Z10XzhQVrUWtYc3F0w== + dependencies: + "@storybook/components" "^8.0.0" + "@storybook/core-events" "^8.0.0" + "@storybook/global" "^5.0.0" + "@storybook/icons" "^1.2.5" + "@storybook/manager-api" "^8.0.0" + "@storybook/theming" "^8.0.0" + fast-deep-equal "^3.1.3" + memoizerific "^1.11.3" + +storybook@^8.4.5: + version "8.4.5" + resolved "https://registry.yarnpkg.com/storybook/-/storybook-8.4.5.tgz#ba9589e2887958d1353dbc1a2cb6142e80e36a2c" + integrity sha512-9tfgabXnMibYp3SvoaJXXMD63Pw0SA9Hnf5v6TxysCYZs4DZ/04fAkK+9RW+K4C5JkV83qXMMlrsPj766R47fg== + dependencies: + "@storybook/core" "8.4.5" + +stream-browserify@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-3.0.0.tgz#22b0a2850cdf6503e73085da1fc7b7d0c2122f2f" + integrity sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA== + dependencies: + inherits "~2.0.4" + readable-stream "^3.5.0" + +stream-http@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-3.2.0.tgz#1872dfcf24cb15752677e40e5c3f9cc1926028b5" + integrity sha512-Oq1bLqisTyK3TSCXpPbT4sdeYNdmyZJv1LxpEm2vu1ZhK89kSE5YXwZc3cWk0MagGaKriBh9mCFbVGtO+vY29A== + dependencies: + builtin-status-codes "^3.0.0" + inherits "^2.0.4" + readable-stream "^3.6.0" + xtend "^4.0.2" + streamsearch@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-1.1.0.tgz#404dd1e2247ca94af554e841a8ef0eaa238da764" @@ -3878,13 +7145,20 @@ string.prototype.trimstart@^1.0.8: define-properties "^1.2.1" es-object-atoms "^1.0.0" -string_decoder@^1.1.1: +string_decoder@^1.1.1, string_decoder@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== dependencies: safe-buffer "~5.2.0" +string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== + dependencies: + safe-buffer "~5.1.0" + "strip-ansi-cjs@npm:strip-ansi@^6.0.1": version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" @@ -3899,7 +7173,7 @@ strip-ansi@^6.0.0, strip-ansi@^6.0.1: dependencies: ansi-regex "^5.0.1" -strip-ansi@^7.0.1: +strip-ansi@^7.0.1, strip-ansi@^7.1.0: version "7.1.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" integrity sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ== @@ -3911,12 +7185,31 @@ strip-bom@^3.0.0: resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" integrity sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA== +strip-indent@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-3.0.0.tgz#c32e1cee940b6b3432c771bc2c54bcce73cd3001" + integrity sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ== + dependencies: + min-indent "^1.0.0" + +strip-indent@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-4.0.0.tgz#b41379433dd06f5eae805e21d631e07ee670d853" + integrity sha512-mnVSV2l+Zv6BLpSD/8V87CW/y9EmmbYzGCIavsnsI6/nwn26DwffM/yztm30Z/I2DY9wdS3vXVCMnHDgZaVNoA== + dependencies: + min-indent "^1.0.1" + strip-json-comments@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== -styled-jsx@5.1.6: +style-loader@^3.3.1: + version "3.3.4" + resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-3.3.4.tgz#f30f786c36db03a45cbd55b6a70d930c479090e7" + integrity sha512-0WqXzrsMTyb8yjZJHDqwmnwRJvhALK9LfRtRc6B4UTWe8AijYLZYZ9thuJTZc2VfQWINADW/j+LiJnfy2RoC1w== + +styled-jsx@5.1.6, styled-jsx@^5.1.6: version "5.1.6" resolved "https://registry.yarnpkg.com/styled-jsx/-/styled-jsx-5.1.6.tgz#83b90c077e6c6a80f7f5e8781d0f311b2fe41499" integrity sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA== @@ -3943,6 +7236,13 @@ supports-color@^7.1.0: dependencies: has-flag "^4.0.0" +supports-color@^8.0.0: + version "8.1.1" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" + integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== + dependencies: + has-flag "^4.0.0" + supports-preserve-symlinks-flag@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" @@ -3999,7 +7299,7 @@ tailwindcss@^3.4.1: resolve "^1.22.2" sucrase "^3.32.0" -tapable@^2.2.0: +tapable@^2.0.0, tapable@^2.1.1, tapable@^2.2.0, tapable@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== @@ -4016,6 +7316,27 @@ tar@^6.1.11: mkdirp "^1.0.3" yallist "^4.0.0" +terser-webpack-plugin@^5.3.1, terser-webpack-plugin@^5.3.10: + version "5.3.10" + resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz#904f4c9193c6fd2a03f693a2150c62a92f40d199" + integrity sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w== + dependencies: + "@jridgewell/trace-mapping" "^0.3.20" + jest-worker "^27.4.5" + schema-utils "^3.1.1" + serialize-javascript "^6.0.1" + terser "^5.26.0" + +terser@^5.10.0, terser@^5.26.0: + version "5.36.0" + resolved "https://registry.yarnpkg.com/terser/-/terser-5.36.0.tgz#8b0dbed459ac40ff7b4c9fd5a3a2029de105180e" + integrity sha512-IYV9eNMuFAV4THUspIRXkLakHnV6XO7FEdtKjf/mDyrnqUg9LnlOn6/RwRvM9SZjR4GUq8Nk8zj67FzVARr74w== + dependencies: + "@jridgewell/source-map" "^0.3.3" + acorn "^8.8.2" + commander "^2.20.0" + source-map-support "~0.5.20" + text-table@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" @@ -4035,6 +7356,18 @@ thenify-all@^1.0.0: dependencies: any-promise "^1.0.0" +timers-browserify@^2.0.12: + version "2.0.12" + resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.12.tgz#44a45c11fbf407f34f97bccd1577c652361b00ee" + integrity sha512-9phl76Cqm6FhSX9Xe1ZUAMLtm1BLkKj2Qd5ApyWkXzsMRaA7dgr81kf4wJmQf/hAvg8EEyJxDo3du/0KlhPiKQ== + dependencies: + setimmediate "^1.0.4" + +tiny-invariant@^1.3.1, tiny-invariant@^1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.3.3.tgz#46680b7a873a0d5d10005995eb90a70d74d60127" + integrity sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg== + tinybench@^2.9.0: version "2.9.0" resolved "https://registry.yarnpkg.com/tinybench/-/tinybench-2.9.0.tgz#103c9f8ba6d7237a47ab6dd1dcff77251863426b" @@ -4055,7 +7388,7 @@ tinyrainbow@^1.2.0: resolved "https://registry.yarnpkg.com/tinyrainbow/-/tinyrainbow-1.2.0.tgz#5c57d2fc0fb3d1afd78465c33ca885d04f02abb5" integrity sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ== -tinyspy@^3.0.2: +tinyspy@^3.0.0, tinyspy@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/tinyspy/-/tinyspy-3.0.2.tgz#86dd3cf3d737b15adcf17d7887c84a75201df20a" integrity sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q== @@ -4103,11 +7436,31 @@ ts-api-utils@^1.3.0: resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.3.0.tgz#4b490e27129f1e8e686b45cc4ab63714dc60eea1" integrity sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ== +ts-dedent@^2.0.0, ts-dedent@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/ts-dedent/-/ts-dedent-2.2.0.tgz#39e4bd297cd036292ae2394eb3412be63f563bb5" + integrity sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ== + ts-interface-checker@^0.1.9: version "0.1.13" resolved "https://registry.yarnpkg.com/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz#784fd3d679722bc103b1b4b8030bcddb5db2a699" integrity sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA== +ts-pnp@^1.1.6: + version "1.2.0" + resolved "https://registry.yarnpkg.com/ts-pnp/-/ts-pnp-1.2.0.tgz#a500ad084b0798f1c3071af391e65912c86bca92" + integrity sha512-csd+vJOb/gkzvcCHgTGSChYpy5f1/XKNsmvBGO4JXS+z1v2HobugDz4s1IeFXM3wZB44uczs+eazB5Q/ccdhQw== + +tsconfig-paths-webpack-plugin@^4.0.1: + version "4.2.0" + resolved "https://registry.yarnpkg.com/tsconfig-paths-webpack-plugin/-/tsconfig-paths-webpack-plugin-4.2.0.tgz#f7459a8ed1dd4cf66ad787aefc3d37fff3cf07fc" + integrity sha512-zbem3rfRS8BgeNK50Zz5SIQgXzLafiHjOwUAvk/38/o1jHn/V5QAgVUcz884or7WYcPaH3N2CIfUc2u0ul7UcA== + dependencies: + chalk "^4.1.0" + enhanced-resolve "^5.7.0" + tapable "^2.2.1" + tsconfig-paths "^4.1.2" + tsconfig-paths@^3.15.0: version "3.15.0" resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz#5299ec605e55b1abb23ec939ef15edaf483070d4" @@ -4118,7 +7471,16 @@ tsconfig-paths@^3.15.0: minimist "^1.2.6" strip-bom "^3.0.0" -tslib@*, tslib@2, tslib@^2.4.0, tslib@^2.6.2: +tsconfig-paths@^4.0.0, tsconfig-paths@^4.1.2, tsconfig-paths@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz#ef78e19039133446d244beac0fd6a1632e2d107c" + integrity sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg== + dependencies: + json5 "^2.2.2" + minimist "^1.2.6" + strip-bom "^3.0.0" + +tslib@*, tslib@2, tslib@^2.0.0, tslib@^2.0.1, tslib@^2.0.3, tslib@^2.4.0, tslib@^2.6.2: version "2.8.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== @@ -4135,6 +7497,16 @@ tsyringe@^4.8.0: dependencies: tslib "^1.9.3" +tty-browserify@^0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.1.tgz#3f05251ee17904dfd0677546670db9651682b811" + integrity sha512-C3TaO7K81YvjCgQH9Q1S3R3P3BtN3RIM8n+OvX4il1K1zgE8ZhI0op7kClgkxtutIE8hQrcrHBXvIheqKUUCxw== + +tween-functions@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/tween-functions/-/tween-functions-1.2.0.tgz#1ae3a50e7c60bb3def774eac707acbca73bbc3ff" + integrity sha512-PZBtLYcCLtEcjL14Fzb1gSxPBeL7nWvGhO5ZFPGqziCcr8uvHp0NDmdjBchp6KHL+tExcg0m3NISmKxhU394dA== + type-check@^0.4.0, type-check@~0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" @@ -4147,6 +7519,11 @@ type-fest@^0.20.2: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== +type-fest@^2.14.0, type-fest@^2.19.0: + version "2.19.0" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-2.19.0.tgz#88068015bb33036a598b952e55e9311a60fd3a9b" + integrity sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA== + typed-array-buffer@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz#1867c5d83b20fcb5ccf32649e5e2fc7424474ff3" @@ -4206,11 +7583,34 @@ unbox-primitive@^1.0.2: has-symbols "^1.0.3" which-boxed-primitive "^1.0.2" -undici-types@~6.19.2: +undici-types@~6.19.2, undici-types@~6.19.8: version "6.19.8" resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.19.8.tgz#35111c9d1437ab83a7cdc0abae2f26d88eda0a02" integrity sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw== +unicode-canonical-property-names-ecmascript@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.1.tgz#cb3173fe47ca743e228216e4a3ddc4c84d628cc2" + integrity sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg== + +unicode-match-property-ecmascript@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz#54fd16e0ecb167cf04cf1f756bdcc92eba7976c3" + integrity sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q== + dependencies: + unicode-canonical-property-names-ecmascript "^2.0.0" + unicode-property-aliases-ecmascript "^2.0.0" + +unicode-match-property-value-ecmascript@^2.1.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.2.0.tgz#a0401aee72714598f739b68b104e4fe3a0cb3c71" + integrity sha512-4IehN3V/+kkr5YeSSDDQG8QLqO26XpL2XP3GQtqwlT/QYSECAwFztxVHjlbh0+gjJ3XmNLS0zDsbgs9jWKExLg== + +unicode-property-aliases-ecmascript@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz#43d41e3be698bd493ef911077c9b131f827e8ccd" + integrity sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w== + universal-cookie@^7.0.0: version "7.2.2" resolved "https://registry.yarnpkg.com/universal-cookie/-/universal-cookie-7.2.2.tgz#93ae9ec55baab89b24300473543170bb8112773c" @@ -4219,6 +7619,19 @@ universal-cookie@^7.0.0: "@types/cookie" "^0.6.0" cookie "^0.7.2" +universalify@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.1.tgz#168efc2180964e6386d061e094df61afe239b18d" + integrity sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw== + +unplugin@^1.3.1: + version "1.16.0" + resolved "https://registry.yarnpkg.com/unplugin/-/unplugin-1.16.0.tgz#ca0f248bf8798cd752dd02e5b381223b737cef72" + integrity sha512-5liCNPuJW8dqh3+DM6uNM2EI3MLLpCKp/KY+9pB5M2S2SR2qvvDHhKgBOaTWEbZTAws3CXfB0rKTIolWKL05VQ== + dependencies: + acorn "^8.14.0" + webpack-virtual-modules "^0.6.2" + update-browserslist-db@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz#80846fba1d79e82547fb661f8d141e0945755fe5" @@ -4234,11 +7647,40 @@ uri-js@^4.2.2: dependencies: punycode "^2.1.0" -util-deprecate@^1.0.1, util-deprecate@^1.0.2: +url@^0.11.0: + version "0.11.4" + resolved "https://registry.yarnpkg.com/url/-/url-0.11.4.tgz#adca77b3562d56b72746e76b330b7f27b6721f3c" + integrity sha512-oCwdVC7mTuWiPyjLUz/COz5TLk6wgp0RCsN+wHZ2Ekneac9w8uuV0njcbbie2ME+Vs+d6duwmYuR3HgQXs1fOg== + dependencies: + punycode "^1.4.1" + qs "^6.12.3" + +util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== +util@^0.12.4, util@^0.12.5: + version "0.12.5" + resolved "https://registry.yarnpkg.com/util/-/util-0.12.5.tgz#5f17a6059b73db61a875668781a1c2b136bd6fbc" + integrity sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA== + dependencies: + inherits "^2.0.3" + is-arguments "^1.0.4" + is-generator-function "^1.0.7" + is-typed-array "^1.1.3" + which-typed-array "^1.1.2" + +utila@~0.4: + version "0.4.0" + resolved "https://registry.yarnpkg.com/utila/-/utila-0.4.0.tgz#8a16a05d445657a3aea5eecc5b12a4fa5379772c" + integrity sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA== + +uuid@^9.0.0: + version "9.0.1" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-9.0.1.tgz#e188d4c8853cc722220392c424cd637f32293f30" + integrity sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA== + vite-node@2.1.4: version "2.1.4" resolved "https://registry.yarnpkg.com/vite-node/-/vite-node-2.1.4.tgz#97ffb6de913fd8d42253afe441f9512e9dbdfd5c" @@ -4286,6 +7728,11 @@ vitest@^2.1.4: vite-node "2.1.4" why-is-node-running "^2.3.0" +vm-browserify@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0" + integrity sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ== + void-elements@3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-3.1.0.tgz#614f7fbf8d801f0bb5f0661f5b2f5785750e4f09" @@ -4298,6 +7745,14 @@ w3c-xmlserializer@^5.0.0: dependencies: xml-name-validator "^5.0.0" +watchpack@^2.4.1: + version "2.4.2" + resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.2.tgz#2feeaed67412e7c33184e5a79ca738fbd38564da" + integrity sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw== + dependencies: + glob-to-regexp "^0.4.1" + graceful-fs "^4.1.2" + webidl-conversions@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" @@ -4308,6 +7763,65 @@ webidl-conversions@^7.0.0: resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-7.0.0.tgz#256b4e1882be7debbf01d05f0aa2039778ea080a" integrity sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g== +webpack-dev-middleware@^6.1.2: + version "6.1.3" + resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-6.1.3.tgz#79f4103f8c898564c9e96c3a9c2422de50f249bc" + integrity sha512-A4ChP0Qj8oGociTs6UdlRUGANIGrCDL3y+pmQMc+dSsraXHCatFpmMey4mYELA+juqwUqwQsUgJJISXl1KWmiw== + dependencies: + colorette "^2.0.10" + memfs "^3.4.12" + mime-types "^2.1.31" + range-parser "^1.2.1" + schema-utils "^4.0.0" + +webpack-hot-middleware@^2.25.1: + version "2.26.1" + resolved "https://registry.yarnpkg.com/webpack-hot-middleware/-/webpack-hot-middleware-2.26.1.tgz#87214f1e3f9f3acab9271fef9e6ed7b637d719c0" + integrity sha512-khZGfAeJx6I8K9zKohEWWYN6KDlVw2DHownoe+6Vtwj1LP9WFgegXnVMSkZ/dBEBtXFwrkkydsaPFlB7f8wU2A== + dependencies: + ansi-html-community "0.0.8" + html-entities "^2.1.0" + strip-ansi "^6.0.0" + +webpack-sources@^3.2.3: + version "3.2.3" + resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.3.tgz#2d4daab8451fd4b240cc27055ff6a0c2ccea0cde" + integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w== + +webpack-virtual-modules@^0.6.0, webpack-virtual-modules@^0.6.2: + version "0.6.2" + resolved "https://registry.yarnpkg.com/webpack-virtual-modules/-/webpack-virtual-modules-0.6.2.tgz#057faa9065c8acf48f24cb57ac0e77739ab9a7e8" + integrity sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ== + +webpack@5: + version "5.96.1" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.96.1.tgz#3676d1626d8312b6b10d0c18cc049fba7ac01f0c" + integrity sha512-l2LlBSvVZGhL4ZrPwyr8+37AunkcYj5qh8o6u2/2rzoPc8gxFJkLj1WxNgooi9pnoc06jh0BjuXnamM4qlujZA== + dependencies: + "@types/eslint-scope" "^3.7.7" + "@types/estree" "^1.0.6" + "@webassemblyjs/ast" "^1.12.1" + "@webassemblyjs/wasm-edit" "^1.12.1" + "@webassemblyjs/wasm-parser" "^1.12.1" + acorn "^8.14.0" + browserslist "^4.24.0" + chrome-trace-event "^1.0.2" + enhanced-resolve "^5.17.1" + es-module-lexer "^1.2.1" + eslint-scope "5.1.1" + events "^3.2.0" + glob-to-regexp "^0.4.1" + graceful-fs "^4.2.11" + json-parse-even-better-errors "^2.3.1" + loader-runner "^4.2.0" + mime-types "^2.1.27" + neo-async "^2.6.2" + schema-utils "^3.2.0" + tapable "^2.1.1" + terser-webpack-plugin "^5.3.10" + watchpack "^2.4.1" + webpack-sources "^3.2.3" + whatwg-encoding@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz#d0f4ef769905d426e1688f3e34381a99b60b76e5" @@ -4375,7 +7889,7 @@ which-collection@^1.0.2: is-weakmap "^2.0.2" is-weakset "^2.0.3" -which-typed-array@^1.1.14, which-typed-array@^1.1.15: +which-typed-array@^1.1.14, which-typed-array@^1.1.15, which-typed-array@^1.1.2: version "1.1.15" resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.15.tgz#264859e9b11a649b388bfaaf4f767df1f779b38d" integrity sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA== @@ -4436,7 +7950,7 @@ wrappy@1: resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== -ws@^8.18.0: +ws@^8.18.0, ws@^8.2.3: version "8.18.0" resolved "https://registry.yarnpkg.com/ws/-/ws-8.18.0.tgz#0d7505a6eafe2b0e712d232b42279f53bc289bbc" integrity sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw== @@ -4451,6 +7965,11 @@ xmlchars@^2.2.0: resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb" integrity sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw== +xtend@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" + integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== + yallist@^3.0.2: version "3.1.1" resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" @@ -4461,6 +7980,11 @@ yallist@^4.0.0: resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== +yaml@^1.10.0: + version "1.10.2" + resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" + integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== + yaml@^2.3.4: version "2.6.0" resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.6.0.tgz#14059ad9d0b1680d0f04d3a60fe00f3a857303c3" @@ -4471,6 +7995,11 @@ yocto-queue@^0.1.0: resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== +yocto-queue@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-1.1.1.tgz#fef65ce3ac9f8a32ceac5a634f74e17e5b232110" + integrity sha512-b4JR1PFR10y1mKjhHY9LaGo6tmrgjit7hxVIeAmyMw3jegXR4dhYqLaQF5zMXZxY7tLpMyJeLjr1C4rLmkVe8g== + zod@^3.23.8: version "3.23.8" resolved "https://registry.yarnpkg.com/zod/-/zod-3.23.8.tgz#e37b957b5d52079769fb8097099b592f0ef4067d" -- 2.39.5