diff --git a/apps/dashboard/eslint.config.js b/apps/dashboard/eslint.config.js index 95bb45ab773..16d07b7f581 100644 --- a/apps/dashboard/eslint.config.js +++ b/apps/dashboard/eslint.config.js @@ -20,7 +20,7 @@ export default tseslint.config( rules: { ...reactHooks.configs.recommended.rules, '@typescript-eslint/no-explicit-any': 'warn', - 'react-refresh/only-export-components': ['warn', { allowConstantExport: true }], + 'react-refresh/only-export-components': ['error', { allowConstantExport: true }], '@typescript-eslint/no-unused-vars': ['off'], '@typescript-eslint/naming-convention': [ 'error', diff --git a/apps/dashboard/src/components/error-page.tsx b/apps/dashboard/src/components/error-page.tsx index a7068f9eb8a..c3b3b679fe7 100644 --- a/apps/dashboard/src/components/error-page.tsx +++ b/apps/dashboard/src/components/error-page.tsx @@ -1,7 +1,7 @@ import { useRouteError } from 'react-router-dom'; export default function ErrorPage() { - const error = useRouteError() as any; + const error = useRouteError() as { statusText?: string; message: string }; console.error(error); return ( diff --git a/apps/dashboard/src/components/icons/utils.ts b/apps/dashboard/src/components/icons/utils.ts index 857fa6222a5..33d4743c775 100644 --- a/apps/dashboard/src/components/icons/utils.ts +++ b/apps/dashboard/src/components/icons/utils.ts @@ -1,4 +1,3 @@ -import { StepTypeEnum } from '@novu/shared'; import { RiCellphoneFill, RiChatThreadFill, @@ -11,6 +10,7 @@ import { Mail3Fill } from './mail-3-fill'; import { Notification5Fill } from './notification-5-fill'; import { Sms } from './sms'; import { IconType } from 'react-icons/lib'; +import { StepTypeEnum } from '@/utils/enums'; export const STEP_TYPE_TO_ICON: Record = { [StepTypeEnum.CHAT]: RiChatThreadFill, diff --git a/apps/dashboard/src/components/primitives/badge.tsx b/apps/dashboard/src/components/primitives/badge.tsx index 80995abb838..391f37897cd 100644 --- a/apps/dashboard/src/components/primitives/badge.tsx +++ b/apps/dashboard/src/components/primitives/badge.tsx @@ -1,39 +1,7 @@ import * as React from 'react'; -import { cva, type VariantProps } from 'class-variance-authority'; +import { type VariantProps } from 'class-variance-authority'; import { cn } from '@/utils/ui'; - -const badgeVariants = cva( - 'inline-flex items-center h-5 border px-2 py-1 transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2', - { - variants: { - variant: { - neutral: 'border-neutral-500 bg-neutral-500', - feature: 'border-feature bg-feature', - information: 'border-information bg-information', - highlighted: 'border-highlighted bg-highlighted', - stable: 'border-stable bg-stable', - verified: 'border-verified bg-verified', - destructive: 'border-destructive bg-destructive', - 'destructive-light': 'border-transparent bg-destructive/10', - success: 'border-success bg-success', - 'success-light': 'border-transparent bg-success/10', - warning: 'border-warning bg-warning', - 'warning-light': 'border-transparent bg-warning/10', - alert: 'border-alert bg-alert', - soft: 'border-neutral-alpha-200 bg-neutral-alpha-200', - }, - kind: { - default: 'rounded-md', - pill: 'rounded-full', - 'pill-stroke': 'rounded-full bg-transparent', - }, - }, - defaultVariants: { - variant: 'neutral', - kind: 'default', - }, - } -); +import { badgeContentVariants, badgeVariants } from './variants'; export interface BadgeProps extends React.HTMLAttributes, VariantProps {} @@ -41,28 +9,6 @@ function Badge({ className, variant, kind, ...props }: BadgeProps) { return
; } -const badgeContentVariants = cva('text-xs font-medium', { - variants: { - variant: { - foreground: 'text-foreground', - 'neutral-foreground': 'text-neutral-foreground', - neutral: 'text-neutral-500', - feature: 'text-feature', - information: 'text-information', - highlighted: 'text-highlighted', - stable: 'text-stable', - verified: 'text-verified', - destructive: 'text-destructive', - success: 'text-success', - warning: 'text-warning', - alert: 'text-alert', - }, - }, - defaultVariants: { - variant: 'foreground', - }, -}); - export interface BadgeContentProps extends React.HTMLAttributes, VariantProps {} @@ -71,4 +17,4 @@ function BadgeContent({ className, variant, ...props }: BadgeContentProps) { return ; } -export { Badge, BadgeContent, badgeVariants, badgeContentVariants }; +export { Badge, BadgeContent }; diff --git a/apps/dashboard/src/components/primitives/button.tsx b/apps/dashboard/src/components/primitives/button.tsx index d2a4d9ce6ea..14ddf1bcf7f 100644 --- a/apps/dashboard/src/components/primitives/button.tsx +++ b/apps/dashboard/src/components/primitives/button.tsx @@ -1,39 +1,8 @@ import * as React from 'react'; import { Slot } from '@radix-ui/react-slot'; -import { cva, type VariantProps } from 'class-variance-authority'; +import { type VariantProps } from 'class-variance-authority'; import { cn } from '@/utils/ui'; - -const buttonVariants = cva( - `relative isolate inline-flex items-center justify-center whitespace-nowrap rounded-lg 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`, - { - variants: { - variant: { - default: - 'bg-gradient-to-b from-neutral-alpha-900 to-neutral-900 text-neutral-foreground shadow-[inset_0_-4px_2px_-2px_hsl(var(--neutral-900)),inset_0_0_0_1px_rgba(255,255,255,0.16),0_0_0_1px_hsl(var(--neutral-900)),0px_1px_2px_0px_#0E121B3D] after:content-[""] after:absolute after:w-full after:h-full after:bg-gradient-to-b after:from-background/10 after:opacity-0 hover:after:opacity-100 after:rounded-lg after:transition-opacity after:duration-300', - primary: - 'bg-gradient-to-b from-primary/90 to-primary text-primary-foreground shadow-[inset_0_-4px_2px_-2px_hsl(var(--primary)),inset_0_0_0_1px_rgba(255,255,255,0.16),0_0_0_1px_hsl(var(--primary)),0px_1px_2px_0px_#0E121B3D] after:content-[""] after:absolute after:w-full after:h-full after:bg-gradient-to-b after:from-background/10 after:opacity-0 hover:after:opacity-100 after:rounded-lg after:transition-opacity after:duration-300', - destructive: - 'bg-gradient-to-b from-destructive/90 to-destructive text-destructive-foreground shadow-[inset_0_-4px_2px_-2px_hsl(var(--destructive)),inset_0_0_0_1px_rgba(255,255,255,0.16),0_0_0_1px_hsl(var(--destructive)),0px_1px_2px_0px_#0E121B3D] after:content-[""] after:absolute after:w-full after:h-full after:bg-gradient-to-b after:from-background/10 after:opacity-0 hover:after:opacity-100 after:rounded-lg after:transition-opacity after:duration-300', - outline: 'border border-input bg-background shadow-xs hover:bg-accent hover:text-accent-foreground', - ghost: 'hover:bg-accent', - link: 'underline-offset-4 hover:underline', - light: - 'bg-destructive/10 hover:bg-background hover:border hover:border-destructive text-destructive focus-visible:ring-destructive/10 focus-visible:ring-2 focus-visible:ring-offset-1 focus-visible:bg-background focus-visible:border focus-visible:border-destructive', - }, - size: { - default: 'h-9 p-2.5', - xs: 'h-6 px-1.5 rounded-md text-xs', - sm: 'h-8 px-3 rounded-md text-xs', - lg: 'h-10 rounded-md px-8', - icon: 'size-8', - }, - }, - defaultVariants: { - variant: 'default', - size: 'default', - }, - } -); +import { buttonVariants } from './variants'; export interface ButtonProps extends React.ButtonHTMLAttributes, @@ -49,4 +18,4 @@ const Button = React.forwardRef( ); Button.displayName = 'Button'; -export { Button, buttonVariants }; +export { Button }; diff --git a/apps/dashboard/src/components/primitives/form/form-context.ts b/apps/dashboard/src/components/primitives/form/form-context.ts new file mode 100644 index 00000000000..2bb7ee46756 --- /dev/null +++ b/apps/dashboard/src/components/primitives/form/form-context.ts @@ -0,0 +1,40 @@ +import React from 'react'; +import { FieldPath, FieldValues, useFormContext } from 'react-hook-form'; + +type FormFieldContextValue< + TFieldValues extends FieldValues = FieldValues, + TName extends FieldPath = FieldPath, +> = { + name: TName; +}; + +export const FormFieldContext = React.createContext({} as FormFieldContextValue); + +type FormItemContextValue = { + id: string; +}; + +export const FormItemContext = React.createContext({} as FormItemContextValue); + +export const useFormField = () => { + const fieldContext = React.useContext(FormFieldContext); + const itemContext = React.useContext(FormItemContext); + const { getFieldState, formState } = useFormContext(); + + const fieldState = getFieldState(fieldContext.name, formState); + + if (!fieldContext) { + throw new Error('useFormField should be used within '); + } + + const { id } = itemContext; + + return { + id, + name: fieldContext.name, + formItemId: `${id}-form-item`, + formDescriptionId: `${id}-form-item-description`, + formMessageId: `${id}-form-item-message`, + ...fieldState, + }; +}; diff --git a/apps/dashboard/src/components/primitives/form.tsx b/apps/dashboard/src/components/primitives/form/form.tsx similarity index 73% rename from apps/dashboard/src/components/primitives/form.tsx rename to apps/dashboard/src/components/primitives/form/form.tsx index 73666e05385..9fdd342a4ed 100644 --- a/apps/dashboard/src/components/primitives/form.tsx +++ b/apps/dashboard/src/components/primitives/form/form.tsx @@ -1,24 +1,16 @@ import * as React from 'react'; import * as LabelPrimitive from '@radix-ui/react-label'; import { Slot } from '@radix-ui/react-slot'; -import { Controller, ControllerProps, FieldPath, FieldValues, FormProvider, useFormContext } from 'react-hook-form'; +import { Controller, ControllerProps, FieldPath, FieldValues, FormProvider } from 'react-hook-form'; import { cn } from '@/utils/ui'; import { Label } from '@/components/primitives/label'; import { cva } from 'class-variance-authority'; import { RiInformationFill } from 'react-icons/ri'; +import { FormFieldContext, FormItemContext, useFormField } from './form-context'; const Form = FormProvider; -type FormFieldContextValue< - TFieldValues extends FieldValues = FieldValues, - TName extends FieldPath = FieldPath, -> = { - name: TName; -}; - -const FormFieldContext = React.createContext({} as FormFieldContextValue); - const FormField = < TFieldValues extends FieldValues = FieldValues, TName extends FieldPath = FieldPath, @@ -32,35 +24,6 @@ const FormField = < ); }; -const useFormField = () => { - const fieldContext = React.useContext(FormFieldContext); - const itemContext = React.useContext(FormItemContext); - const { getFieldState, formState } = useFormContext(); - - const fieldState = getFieldState(fieldContext.name, formState); - - if (!fieldContext) { - throw new Error('useFormField should be used within '); - } - - const { id } = itemContext; - - return { - id, - name: fieldContext.name, - formItemId: `${id}-form-item`, - formDescriptionId: `${id}-form-item-description`, - formMessageId: `${id}-form-item-message`, - ...fieldState, - }; -}; - -type FormItemContextValue = { - id: string; -}; - -const FormItemContext = React.createContext({} as FormItemContextValue); - const FormItem = React.forwardRef>( ({ className, ...props }, ref) => { const id = React.useId(); @@ -145,4 +108,4 @@ const FormMessage = React.forwardRef) => ( diff --git a/apps/dashboard/src/components/primitives/step.tsx b/apps/dashboard/src/components/primitives/step.tsx index f21397ca5b3..b7915724960 100644 --- a/apps/dashboard/src/components/primitives/step.tsx +++ b/apps/dashboard/src/components/primitives/step.tsx @@ -1,34 +1,8 @@ import * as React from 'react'; -import { cva, type VariantProps } from 'class-variance-authority'; +import { type VariantProps } from 'class-variance-authority'; import { cn } from '@/utils/ui'; - -const stepVariants = cva( - 'inline-flex items-center shadow-xs rounded-full border text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 bg-neutral-50', - { - variants: { - variant: { - // use solid bg here because we usually stack these on top of each other - neutral: 'border-neutral-100 text-neutral-400', - feature: 'border-feature/30 text-feature/30', - information: 'border-information/30 text-information/30', - highlighted: 'border-highlighted/30 text-highlighted/30', - stable: 'border-stable/30 text-stable/30', - verified: 'border-verified/30 text-verified/30', - destructive: 'border-destructive/30 text-destructive/30', - warning: 'border-warning/30 text-warning/30', - alert: 'border-alert/30 text-alert/30', - }, - size: { - default: 'p-1 [&>svg]:size-3.5', - }, - }, - defaultVariants: { - variant: 'neutral', - size: 'default', - }, - } -); +import { stepVariants } from './variants'; export interface StepProps extends React.HTMLAttributes, VariantProps {} @@ -36,4 +10,4 @@ function Step({ className, variant, ...props }: StepProps) { return
; } -export { Step, stepVariants }; +export { Step }; diff --git a/apps/dashboard/src/components/primitives/tag.tsx b/apps/dashboard/src/components/primitives/tag.tsx index 608ace4b297..644930420cf 100644 --- a/apps/dashboard/src/components/primitives/tag.tsx +++ b/apps/dashboard/src/components/primitives/tag.tsx @@ -25,4 +25,4 @@ function Tag({ className, variant, ...props }: TagProps) { return
; } -export { Tag, tagVariants }; +export { Tag }; diff --git a/apps/dashboard/src/components/primitives/variants.ts b/apps/dashboard/src/components/primitives/variants.ts new file mode 100644 index 00000000000..0cabae5f439 --- /dev/null +++ b/apps/dashboard/src/components/primitives/variants.ts @@ -0,0 +1,115 @@ +import { cva } from 'class-variance-authority'; + +export const badgeVariants = cva( + 'inline-flex items-center h-5 border px-2 py-1 transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2', + { + variants: { + variant: { + neutral: 'border-neutral-500 bg-neutral-500', + feature: 'border-feature bg-feature', + information: 'border-information bg-information', + highlighted: 'border-highlighted bg-highlighted', + stable: 'border-stable bg-stable', + verified: 'border-verified bg-verified', + destructive: 'border-destructive bg-destructive', + 'destructive-light': 'border-transparent bg-destructive/10', + success: 'border-success bg-success', + 'success-light': 'border-transparent bg-success/10', + warning: 'border-warning bg-warning', + 'warning-light': 'border-transparent bg-warning/10', + alert: 'border-alert bg-alert', + soft: 'border-neutral-alpha-200 bg-neutral-alpha-200', + }, + kind: { + default: 'rounded-md', + pill: 'rounded-full', + 'pill-stroke': 'rounded-full bg-transparent', + }, + }, + defaultVariants: { + variant: 'neutral', + kind: 'default', + }, + } +); + +export const badgeContentVariants = cva('text-xs font-medium', { + variants: { + variant: { + foreground: 'text-foreground', + 'neutral-foreground': 'text-neutral-foreground', + neutral: 'text-neutral-500', + feature: 'text-feature', + information: 'text-information', + highlighted: 'text-highlighted', + stable: 'text-stable', + verified: 'text-verified', + destructive: 'text-destructive', + success: 'text-success', + warning: 'text-warning', + alert: 'text-alert', + }, + }, + defaultVariants: { + variant: 'foreground', + }, +}); + +export const buttonVariants = cva( + `relative isolate inline-flex items-center justify-center whitespace-nowrap rounded-lg 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`, + { + variants: { + variant: { + default: + 'bg-gradient-to-b from-neutral-alpha-900 to-neutral-900 text-neutral-foreground shadow-[inset_0_-4px_2px_-2px_hsl(var(--neutral-900)),inset_0_0_0_1px_rgba(255,255,255,0.16),0_0_0_1px_hsl(var(--neutral-900)),0px_1px_2px_0px_#0E121B3D] after:content-[""] after:absolute after:w-full after:h-full after:bg-gradient-to-b after:from-background/10 after:opacity-0 hover:after:opacity-100 after:rounded-lg after:transition-opacity after:duration-300', + primary: + 'bg-gradient-to-b from-primary/90 to-primary text-primary-foreground shadow-[inset_0_-4px_2px_-2px_hsl(var(--primary)),inset_0_0_0_1px_rgba(255,255,255,0.16),0_0_0_1px_hsl(var(--primary)),0px_1px_2px_0px_#0E121B3D] after:content-[""] after:absolute after:w-full after:h-full after:bg-gradient-to-b after:from-background/10 after:opacity-0 hover:after:opacity-100 after:rounded-lg after:transition-opacity after:duration-300', + destructive: + 'bg-gradient-to-b from-destructive/90 to-destructive text-destructive-foreground shadow-[inset_0_-4px_2px_-2px_hsl(var(--destructive)),inset_0_0_0_1px_rgba(255,255,255,0.16),0_0_0_1px_hsl(var(--destructive)),0px_1px_2px_0px_#0E121B3D] after:content-[""] after:absolute after:w-full after:h-full after:bg-gradient-to-b after:from-background/10 after:opacity-0 hover:after:opacity-100 after:rounded-lg after:transition-opacity after:duration-300', + outline: 'border border-input bg-background shadow-xs hover:bg-accent hover:text-accent-foreground', + ghost: 'hover:bg-accent', + link: 'underline-offset-4 hover:underline', + light: + 'bg-destructive/10 hover:bg-background hover:border hover:border-destructive text-destructive focus-visible:ring-destructive/10 focus-visible:ring-2 focus-visible:ring-offset-1 focus-visible:bg-background focus-visible:border focus-visible:border-destructive', + }, + size: { + default: 'h-9 p-2.5', + xs: 'h-6 px-1.5 rounded-md text-xs', + sm: 'h-8 px-3 rounded-md text-xs', + lg: 'h-10 rounded-md px-8', + icon: 'size-8', + }, + }, + defaultVariants: { + variant: 'default', + size: 'default', + }, + } +); + +export const stepVariants = cva( + 'inline-flex items-center shadow-xs rounded-full border text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 bg-neutral-50', + { + variants: { + variant: { + // use solid bg here because we usually stack these on top of each other + neutral: 'border-neutral-100 text-neutral-400', + feature: 'border-feature/30 text-feature/30', + information: 'border-information/30 text-information/30', + highlighted: 'border-highlighted/30 text-highlighted/30', + stable: 'border-stable/30 text-stable/30', + verified: 'border-verified/30 text-verified/30', + destructive: 'border-destructive/30 text-destructive/30', + warning: 'border-warning/30 text-warning/30', + alert: 'border-alert/30 text-alert/30', + }, + size: { + default: 'p-1 [&>svg]:size-3.5', + }, + }, + defaultVariants: { + variant: 'neutral', + size: 'default', + }, + } +); diff --git a/apps/dashboard/src/components/workflow-editor/add-step-menu.tsx b/apps/dashboard/src/components/workflow-editor/add-step-menu.tsx index 1f57ca3af5f..2b78b678d59 100644 --- a/apps/dashboard/src/components/workflow-editor/add-step-menu.tsx +++ b/apps/dashboard/src/components/workflow-editor/add-step-menu.tsx @@ -1,13 +1,13 @@ import { ReactNode, useState } from 'react'; import { RiAddLine } from 'react-icons/ri'; import { PopoverPortal } from '@radix-ui/react-popover'; -import { StepTypeEnum } from '@novu/shared'; import { Node } from './base-node'; import { Popover, PopoverContent, PopoverTrigger } from '../primitives/popover'; import { STEP_TYPE_TO_ICON } from '../icons/utils'; import { STEP_TYPE_TO_COLOR } from '@/utils/color'; import { Badge, BadgeContent } from '../primitives/badge'; import { cn } from '@/utils/ui'; +import { StepTypeEnum } from '@/utils/enums'; const MenuGroup = ({ children }: { children: ReactNode }) => { return
{children}
; diff --git a/apps/dashboard/src/components/workflow-editor/base-node.tsx b/apps/dashboard/src/components/workflow-editor/base-node.tsx index 2fbb504bac7..84e7a7fc9c5 100644 --- a/apps/dashboard/src/components/workflow-editor/base-node.tsx +++ b/apps/dashboard/src/components/workflow-editor/base-node.tsx @@ -1,8 +1,8 @@ import { ReactNode } from 'react'; import { cva, VariantProps } from 'class-variance-authority'; -import { StepTypeEnum } from '@novu/shared'; import { Badge, BadgeContent, BadgeContentProps, BadgeProps } from '../primitives/badge'; import { STEP_TYPE_TO_COLOR } from '@/utils/color'; +import { StepTypeEnum } from '@/utils/enums'; const nodeIconVariants = cva('w-5 h-5 border rounded-full opacity-40 flex items-center justify-center p-1', { variants: { @@ -66,7 +66,7 @@ export const NodeBody = ({ children }: { children: ReactNode }) => { export const NODE_WIDTH = 300; export const NODE_HEIGHT = 86; -export const nodeVariants = cva( +const nodeVariants = cva( `border-neutral-alpha-200 bg-foreground-0 flex w-[300px] flex-col gap-1 border p-1 shadow-xs`, { variants: { diff --git a/apps/dashboard/src/components/workflow-editor/nodes.tsx b/apps/dashboard/src/components/workflow-editor/nodes.tsx index 2854c5dda19..350c1951310 100644 --- a/apps/dashboard/src/components/workflow-editor/nodes.tsx +++ b/apps/dashboard/src/components/workflow-editor/nodes.tsx @@ -1,10 +1,10 @@ import { Handle, Node as FlowNode, NodeProps, Position } from '@xyflow/react'; import { RiPlayCircleLine } from 'react-icons/ri'; -import { StepTypeEnum } from '@novu/shared'; import { STEP_TYPE_TO_COLOR } from '@/utils/color'; import { STEP_TYPE_TO_ICON } from '../icons/utils'; import { AddStepMenu } from './add-step-menu'; import { Node, NodeBody, NodeHeader, NodeIcon, NodeName } from './base-node'; +import { StepTypeEnum } from '@/utils/enums'; export type NodeData = { name: string; diff --git a/apps/dashboard/src/components/workflow-editor/workflow-canvas.tsx b/apps/dashboard/src/components/workflow-editor/workflow-canvas.tsx index 9560156f8ef..2a482bdf010 100644 --- a/apps/dashboard/src/components/workflow-editor/workflow-canvas.tsx +++ b/apps/dashboard/src/components/workflow-editor/workflow-canvas.tsx @@ -9,7 +9,7 @@ import { useReactFlow, ViewportHelperFunctionOptions, } from '@xyflow/react'; -import { StepTypeEnum, type StepResponseDto } from '@novu/shared'; +import type { StepResponseDto } from '@novu/shared'; import '@xyflow/react/dist/style.css'; import { AddNode, @@ -26,6 +26,7 @@ import { } from './nodes'; import { AddNodeEdgeType, AddNodeEdge } from './edges'; import { NODE_HEIGHT, NODE_WIDTH } from './base-node'; +import { StepTypeEnum } from '@/utils/enums'; const nodeTypes = { trigger: TriggerNode, diff --git a/apps/dashboard/src/components/workflow-editor/workflow-editor.tsx b/apps/dashboard/src/components/workflow-editor/workflow-editor.tsx index 8615ee0dbb0..6b4f8d5c68f 100644 --- a/apps/dashboard/src/components/workflow-editor/workflow-editor.tsx +++ b/apps/dashboard/src/components/workflow-editor/workflow-editor.tsx @@ -4,14 +4,14 @@ import { useForm } from 'react-hook-form'; import { zodResolver } from '@hookform/resolvers/zod'; import * as z from 'zod'; import { useNavigate, useParams } from 'react-router-dom'; -import { StepTypeEnum } from '@novu/shared'; import { useFetchWorkflow } from '@/hooks/use-fetch-workflow'; -import { Form } from '../primitives/form'; +import { Form } from '../primitives/form/form'; import { buildRoute, ROUTES } from '@/utils/routes'; import { useEnvironment } from '@/context/environment/hooks'; import { Tabs, TabsContent, TabsList, TabsTrigger } from '../primitives/tabs'; import { WorkflowCanvas } from './workflow-canvas'; +import { StepTypeEnum } from '@/utils/enums'; const formSchema = z.object({ name: z.string(), diff --git a/apps/dashboard/src/components/workflow-list.tsx b/apps/dashboard/src/components/workflow-list.tsx index fc2de9ebd52..fac50f5bf04 100644 --- a/apps/dashboard/src/components/workflow-list.tsx +++ b/apps/dashboard/src/components/workflow-list.tsx @@ -1,7 +1,23 @@ +import { keepPreviousData, useQuery } from '@tanstack/react-query'; +import { FaCode } from 'react-icons/fa6'; +import { createSearchParams, Link, useLocation, useNavigate, useSearchParams } from 'react-router-dom'; +import { + RiRouteFill, + RiBookMarkedLine, + RiMore2Fill, + RiPlayCircleLine, + RiGitPullRequestFill, + RiPulseFill, + RiPauseCircleLine, + RiDeleteBin2Line, +} from 'react-icons/ri'; +import type { ListWorkflowResponse } from '@novu/shared'; + import { getV2 } from '@/api/api.client'; import { DefaultPagination } from '@/components/default-pagination'; import { Badge, BadgeContent } from '@/components/primitives/badge'; -import { Button, buttonVariants } from '@/components/primitives/button'; +import { Button } from '@/components/primitives/button'; +import { buttonVariants } from '@/components/primitives/variants'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/primitives/select'; import { Skeleton } from '@/components/primitives/skeleton'; import { @@ -19,20 +35,6 @@ import { WorkflowStatus } from '@/components/workflow-status'; import { WorkflowSteps } from '@/components/workflow-steps'; import { WorkflowTags } from '@/components/workflow-tags'; import { useEnvironment } from '@/context/environment/hooks'; -import { ListWorkflowResponse, WorkflowOriginEnum, WorkflowStatusEnum } from '@novu/shared'; -import { keepPreviousData, useQuery } from '@tanstack/react-query'; -import { FaCode } from 'react-icons/fa6'; -import { createSearchParams, Link, useLocation, useNavigate, useSearchParams } from 'react-router-dom'; -import { - RiRouteFill, - RiBookMarkedLine, - RiMore2Fill, - RiPlayCircleLine, - RiGitPullRequestFill, - RiPulseFill, - RiPauseCircleLine, - RiDeleteBin2Line, -} from 'react-icons/ri'; import { DropdownMenu, DropdownMenuContent, @@ -42,6 +44,7 @@ import { DropdownMenuTrigger, } from '@/components/primitives/dropdown-menu'; import { buildRoute, ROUTES } from '@/utils/routes'; +import { WorkflowOriginEnum, WorkflowStatusEnum } from '@/utils/enums'; export const WorkflowList = () => { const { currentEnvironment } = useEnvironment(); diff --git a/apps/dashboard/src/components/workflow-status.tsx b/apps/dashboard/src/components/workflow-status.tsx index 83224838eff..ea46f7beded 100644 --- a/apps/dashboard/src/components/workflow-status.tsx +++ b/apps/dashboard/src/components/workflow-status.tsx @@ -1,5 +1,6 @@ -import { Badge, BadgeContent, badgeContentVariants, badgeVariants } from '@/components/primitives/badge'; -import { WorkflowStatusEnum } from '@novu/shared'; +import { Badge, BadgeContent } from '@/components/primitives/badge'; +import { badgeContentVariants, badgeVariants } from '@/components/primitives/variants'; +import { WorkflowStatusEnum } from '@/utils/enums'; type WorkflowStatusProps = { status: WorkflowStatusEnum; diff --git a/apps/dashboard/src/components/workflow-step.tsx b/apps/dashboard/src/components/workflow-step.tsx index fa7d6e4f897..fd4128fd16f 100644 --- a/apps/dashboard/src/components/workflow-step.tsx +++ b/apps/dashboard/src/components/workflow-step.tsx @@ -1,7 +1,8 @@ -import { Step, StepProps, stepVariants } from '@/components/primitives/step'; -import { StepTypeEnum } from '@novu/shared'; +import { Step, StepProps } from '@/components/primitives/step'; +import { stepVariants } from '@/components/primitives/variants'; import { IconType } from 'react-icons/lib'; import { STEP_TYPE_TO_ICON } from './icons/utils'; +import { StepTypeEnum } from '@/utils/enums'; type WorkflowStepProps = StepProps & { step: StepTypeEnum; diff --git a/apps/dashboard/src/components/workflow-steps.tsx b/apps/dashboard/src/components/workflow-steps.tsx index 9ef25c53bf6..10186df338a 100644 --- a/apps/dashboard/src/components/workflow-steps.tsx +++ b/apps/dashboard/src/components/workflow-steps.tsx @@ -1,6 +1,6 @@ import { Step } from '@/components/primitives/step'; import { WorkflowStep } from '@/components/workflow-step'; -import { StepTypeEnum } from '@novu/shared'; +import type { StepTypeEnum } from '@/utils/enums'; type WorkflowStepsProps = { steps: StepTypeEnum[]; diff --git a/apps/dashboard/src/context/auth/auth-context.tsx b/apps/dashboard/src/context/auth/auth-context.tsx index 7c40311087b..65cf35b45e0 100644 --- a/apps/dashboard/src/context/auth/auth-context.tsx +++ b/apps/dashboard/src/context/auth/auth-context.tsx @@ -1,6 +1,5 @@ -import { createContextAndHook } from '@/utils/context'; +import React from 'react'; import { AuthContextValue } from './types'; -const [AuthContext, useAuth] = createContextAndHook('AuthContext'); - -export { AuthContext, useAuth }; +export const AuthContext = React.createContext({} as AuthContextValue); +AuthContext.displayName = 'AuthContext'; diff --git a/apps/dashboard/src/context/auth/hooks.ts b/apps/dashboard/src/context/auth/hooks.ts new file mode 100644 index 00000000000..57f5ddb84ba --- /dev/null +++ b/apps/dashboard/src/context/auth/hooks.ts @@ -0,0 +1,4 @@ +import { AuthContext } from './auth-context'; +import { createContextHook } from '@/utils/context'; + +export const useAuth = createContextHook(AuthContext); diff --git a/apps/dashboard/src/context/auth/index.ts b/apps/dashboard/src/context/auth/index.ts index b675812fe7b..3137341d714 100644 --- a/apps/dashboard/src/context/auth/index.ts +++ b/apps/dashboard/src/context/auth/index.ts @@ -1,2 +1,3 @@ export * from './auth-provider'; export * from './auth-context'; +export * from './hooks'; diff --git a/apps/dashboard/src/context/auth/mappers.ts b/apps/dashboard/src/context/auth/mappers.ts index c3a76d13b25..46a98a045bf 100644 --- a/apps/dashboard/src/context/auth/mappers.ts +++ b/apps/dashboard/src/context/auth/mappers.ts @@ -1,4 +1,4 @@ -import type { IOrganizationEntity, IUserEntity } from '@novu/shared'; +import type { IOrganizationEntity, IServicesHashes, IUserEntity, JobTitleEnum, ProductUseCases } from '@novu/shared'; import { OrganizationResource, UserResource } from '@clerk/types'; export const toUserEntity = (clerkUser: UserResource): IUserEntity => { @@ -23,9 +23,9 @@ export const toUserEntity = (clerkUser: UserResource): IUserEntity => { profilePicture: clerkUser.imageUrl, createdAt: clerkUser.createdAt?.toISOString() ?? '', showOnBoarding: !!clerkUser.publicMetadata.showOnBoarding, - showOnBoardingTour: clerkUser.publicMetadata.showOnBoardingTour as any, - servicesHashes: clerkUser.publicMetadata.servicesHashes as any, - jobTitle: clerkUser.publicMetadata.jobTitle as any, + showOnBoardingTour: clerkUser.publicMetadata.showOnBoardingTour as number, + servicesHashes: clerkUser.publicMetadata.servicesHashes as IServicesHashes, + jobTitle: clerkUser.publicMetadata.jobTitle as JobTitleEnum, hasPassword: clerkUser.passwordEnabled, }; }; @@ -46,12 +46,12 @@ export const toOrganizationEntity = (clerkOrganization: OrganizationResource): I */ return { - _id: (clerkOrganization.publicMetadata.externalOrgId as any) ?? clerkOrganization.id, + _id: (clerkOrganization.publicMetadata.externalOrgId as string) ?? clerkOrganization.id, name: clerkOrganization.name, createdAt: clerkOrganization.createdAt.toISOString(), updatedAt: clerkOrganization.updatedAt.toISOString(), - domain: clerkOrganization.publicMetadata.domain as any, - productUseCases: clerkOrganization.publicMetadata.productUseCases as any, - language: clerkOrganization.publicMetadata.language as any, + domain: clerkOrganization.publicMetadata.domain as string, + productUseCases: clerkOrganization.publicMetadata.productUseCases as ProductUseCases, + language: clerkOrganization.publicMetadata.language as string[], }; }; diff --git a/apps/dashboard/src/context/environment/environment-context.tsx b/apps/dashboard/src/context/environment/environment-context.tsx index 58a301f1814..ccee86a9c2d 100644 --- a/apps/dashboard/src/context/environment/environment-context.tsx +++ b/apps/dashboard/src/context/environment/environment-context.tsx @@ -1,5 +1,5 @@ +import React from 'react'; import type { IEnvironment } from '@novu/shared'; -import { createContextAndHook } from '@/utils/context'; export type EnvironmentContextValue = { currentEnvironment?: IEnvironment; @@ -10,7 +10,5 @@ export type EnvironmentContextValue = { setBridgeUrl: (url: string) => void; }; -const [EnvironmentContext, useEnvironmentContext] = - createContextAndHook('Environment Context'); - -export { EnvironmentContext, useEnvironmentContext }; +export const EnvironmentContext = React.createContext({} as EnvironmentContextValue); +EnvironmentContext.displayName = 'EnvironmentContext'; diff --git a/apps/dashboard/src/context/environment/hooks.ts b/apps/dashboard/src/context/environment/hooks.ts index 24b71346f0a..e69502a8b6c 100644 --- a/apps/dashboard/src/context/environment/hooks.ts +++ b/apps/dashboard/src/context/environment/hooks.ts @@ -1,8 +1,11 @@ import { useQuery } from '@tanstack/react-query'; import type { IEnvironment } from '@novu/shared'; import { QueryKeys } from '@/utils/query-keys'; -import { useEnvironmentContext } from './environment-context'; +import { EnvironmentContext } from './environment-context'; import { getEnvironments } from '@/api/environments'; +import { createContextHook } from '@/utils/context'; + +const useEnvironmentContext = createContextHook(EnvironmentContext); export function useEnvironment() { const { readOnly, ...rest } = useEnvironmentContext(); diff --git a/apps/dashboard/src/context/environment/index.ts b/apps/dashboard/src/context/environment/index.ts index e03a2107a8f..abdcb82a753 100644 --- a/apps/dashboard/src/context/environment/index.ts +++ b/apps/dashboard/src/context/environment/index.ts @@ -1 +1,2 @@ export * from './environment-provider'; +export * from './hooks'; diff --git a/apps/dashboard/src/context/index.ts b/apps/dashboard/src/context/index.ts index 30f084be530..af426cefddc 100644 --- a/apps/dashboard/src/context/index.ts +++ b/apps/dashboard/src/context/index.ts @@ -1,4 +1,4 @@ export * from './clerk-provider'; -export * from './segment-provider'; +export * from './segment'; export * from './auth'; export * from './environment'; diff --git a/apps/dashboard/src/context/segment-provider.tsx b/apps/dashboard/src/context/segment-provider.tsx deleted file mode 100644 index 70011c5c949..00000000000 --- a/apps/dashboard/src/context/segment-provider.tsx +++ /dev/null @@ -1,28 +0,0 @@ -import { SegmentService } from '@/utils/segment'; -import React from 'react'; - -type Props = { - children: React.ReactNode; -}; - -const SegmentContext = React.createContext(undefined as any); - -export const SegmentProvider = ({ children }: Props) => { - const segment = React.useMemo(() => new SegmentService(), []); - - return {children}; -}; - -/** - * Note: you cannot destructure the result of this hook without risking pre-mature access of the underlying AnalyticsService. - * - * const segment = useSegment(); - */ -export const useSegment = () => { - const result = React.useContext(SegmentContext); - if (!result) { - throw new Error('Context used outside of its Provider!'); - } - - return result; -}; diff --git a/apps/dashboard/src/context/segment/hooks.ts b/apps/dashboard/src/context/segment/hooks.ts new file mode 100644 index 00000000000..6121ce4ff15 --- /dev/null +++ b/apps/dashboard/src/context/segment/hooks.ts @@ -0,0 +1,16 @@ +import React from 'react'; +import { SegmentContext } from './segment-provider'; + +/** + * Note: you cannot destructure the result of this hook without risking pre-mature access of the underlying AnalyticsService. + * + * const segment = useSegment(); + */ +export const useSegment = () => { + const result = React.useContext(SegmentContext); + if (!result) { + throw new Error('Context used outside of its Provider!'); + } + + return result; +}; diff --git a/apps/dashboard/src/context/segment/index.ts b/apps/dashboard/src/context/segment/index.ts new file mode 100644 index 00000000000..4b99da45f6a --- /dev/null +++ b/apps/dashboard/src/context/segment/index.ts @@ -0,0 +1,2 @@ +export * from './segment-provider'; +export * from './hooks'; diff --git a/apps/dashboard/src/context/segment/segment-provider.tsx b/apps/dashboard/src/context/segment/segment-provider.tsx new file mode 100644 index 00000000000..fd72ab33bc8 --- /dev/null +++ b/apps/dashboard/src/context/segment/segment-provider.tsx @@ -0,0 +1,14 @@ +import { SegmentService } from '@/utils/segment'; +import React from 'react'; + +type Props = { + children: React.ReactNode; +}; + +export const SegmentContext = React.createContext({} as SegmentService); + +export const SegmentProvider = ({ children }: Props) => { + const segment = React.useMemo(() => new SegmentService(), []); + + return {children}; +}; diff --git a/apps/dashboard/src/hooks/use-billing-subscription.ts b/apps/dashboard/src/hooks/use-billing-subscription.ts index 9ce2e874997..de9655b1dc6 100644 --- a/apps/dashboard/src/hooks/use-billing-subscription.ts +++ b/apps/dashboard/src/hooks/use-billing-subscription.ts @@ -1,7 +1,7 @@ import { useQuery } from '@tanstack/react-query'; import { useMemo } from 'react'; import { differenceInDays, isSameDay } from 'date-fns'; -import { GetSubscriptionDto } from '@novu/shared'; +import type { GetSubscriptionDto } from '@novu/shared'; import { useAuth } from '@/context'; import { getBillingSubscription } from '@/api/billing'; import { QueryKeys } from '@/utils/query-keys'; diff --git a/apps/dashboard/src/utils/color.ts b/apps/dashboard/src/utils/color.ts index 54cae7b15ef..0966b01e571 100644 --- a/apps/dashboard/src/utils/color.ts +++ b/apps/dashboard/src/utils/color.ts @@ -1,4 +1,4 @@ -import { StepTypeEnum } from '@novu/shared'; +import { StepTypeEnum } from './enums'; export enum StepColorEnum { NEUTRAL = 'neutral', diff --git a/apps/dashboard/src/utils/context.ts b/apps/dashboard/src/utils/context.ts index 69ce721db49..d6b7db85865 100644 --- a/apps/dashboard/src/utils/context.ts +++ b/apps/dashboard/src/utils/context.ts @@ -1,45 +1,20 @@ import React from 'react'; -export function assertContextExists(contextVal: unknown, msgOrCtx: string | React.Context): asserts contextVal { +export function assertContextExists(contextVal: unknown, msgOrCtx: string | React.Context): asserts contextVal { if (!contextVal) { throw typeof msgOrCtx === 'string' ? new Error(msgOrCtx) : new Error(`${msgOrCtx.displayName} not found`); } } -type Options = { assertCtxFn?: (v: unknown, msg: string) => void }; -type ContextOf = React.Context; type UseCtxFn = () => T; -/** - * - * Nice little utility function from https://github.com/clerk/javascript/blob/main/packages/shared/src/react/hooks/createContextAndHook.ts - * - * Creates and returns a Context and two hooks that return the context value. - * The Context type is derived from the type passed in by the user. - * The first hook returned guarantees that the context exists so the returned value is always CtxValue - * The second hook makes no guarantees, so the returned value can be CtxValue | undefined - * - */ -export const createContextAndHook = ( - displayName: string, - options?: Options -): [ContextOf, UseCtxFn, UseCtxFn>] => { - const { assertCtxFn = assertContextExists } = options || {}; - const Ctx = React.createContext({} as CtxVal); - Ctx.displayName = displayName; - +export const createContextHook = (context: React.Context): UseCtxFn => { const useCtx = () => { - const ctx = React.useContext(Ctx); - assertCtxFn(ctx, `${displayName} not found`); - - return ctx; - }; - - const useCtxWithoutGuarantee = () => { - const ctx = React.useContext(Ctx); + const ctx = React.useContext(context); + assertContextExists(ctx, `${context.displayName} not found`); return ctx; }; - return [Ctx, useCtx, useCtxWithoutGuarantee]; + return useCtx; }; diff --git a/apps/dashboard/src/utils/enums.ts b/apps/dashboard/src/utils/enums.ts new file mode 100644 index 00000000000..8b40090551c --- /dev/null +++ b/apps/dashboard/src/utils/enums.ts @@ -0,0 +1,28 @@ +export enum StepTypeEnum { + IN_APP = 'in_app', + EMAIL = 'email', + SMS = 'sms', + CHAT = 'chat', + PUSH = 'push', + DIGEST = 'digest', + TRIGGER = 'trigger', + DELAY = 'delay', + CUSTOM = 'custom', +} + +export enum WorkflowTypeEnum { + REGULAR = 'REGULAR', + ECHO = 'ECHO', // @deprecated + BRIDGE = 'BRIDGE', +} + +export enum WorkflowOriginEnum { + NOVU_CLOUD = 'novu-cloud', + EXTERNAL = 'external', +} + +export enum WorkflowStatusEnum { + ACTIVE = 'ACTIVE', + INACTIVE = 'INACTIVE', + ERROR = 'ERROR', +} diff --git a/apps/dashboard/src/utils/segment.ts b/apps/dashboard/src/utils/segment.ts index 26a104193f1..295cc4b95e5 100644 --- a/apps/dashboard/src/utils/segment.ts +++ b/apps/dashboard/src/utils/segment.ts @@ -96,7 +96,6 @@ export class SegmentService { //@ts-expect-error missing from types mixpanel.get_session_recording_properties(); - // eslint-disable-next-line @typescript-eslint/no-unused-vars data = { ...(data || {}), ...sessionReplayProperties, diff --git a/apps/dashboard/tailwind.config.js b/apps/dashboard/tailwind.config.js index c8283040fba..79ff9581205 100644 --- a/apps/dashboard/tailwind.config.js +++ b/apps/dashboard/tailwind.config.js @@ -1,7 +1,7 @@ /** @type {import('tailwindcss').Config} */ export default { darkMode: ['class'], - content: ['./index.html', './src/**/*.{js,ts,jsx,tsx}'], + content: ['./index.html', './src/**/*.{ts,tsx}'], theme: { boxShadow: { xs: '0px 1px 2px 0px rgba(10, 13, 20, 0.03)', diff --git a/apps/dashboard/tests-examples/demo-todo-app.spec.ts b/apps/dashboard/tests-examples/demo-todo-app.spec.ts index 90883c7b53c..a6a34b22b25 100644 --- a/apps/dashboard/tests-examples/demo-todo-app.spec.ts +++ b/apps/dashboard/tests-examples/demo-todo-app.spec.ts @@ -402,14 +402,14 @@ async function checkNumberOfTodosInLocalStorage(page: Page, expected: number) { async function checkNumberOfCompletedTodosInLocalStorage(page: Page, expected: number) { return await page.waitForFunction((e) => { - return JSON.parse(localStorage['react-todos']).filter((todo: any) => todo.completed).length === e; + return JSON.parse(localStorage['react-todos']).filter((todo) => todo.completed).length === e; }, expected); } async function checkTodosInLocalStorage(page: Page, title: string) { return await page.waitForFunction((t) => { return JSON.parse(localStorage['react-todos']) - .map((todo: any) => todo.title) + .map((todo) => todo.title) .includes(t); }, title); } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7d476bb51cd..7233af92368 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -34556,8 +34556,8 @@ snapshots: dependencies: '@aws-crypto/sha256-browser': 3.0.0 '@aws-crypto/sha256-js': 3.0.0 - '@aws-sdk/client-sso-oidc': 3.575.0 - '@aws-sdk/client-sts': 3.575.0(@aws-sdk/client-sso-oidc@3.575.0) + '@aws-sdk/client-sso-oidc': 3.575.0(@aws-sdk/client-sts@3.575.0) + '@aws-sdk/client-sts': 3.575.0 '@aws-sdk/core': 3.575.0 '@aws-sdk/credential-provider-node': 3.575.0(@aws-sdk/client-sso-oidc@3.575.0)(@aws-sdk/client-sts@3.575.0) '@aws-sdk/middleware-host-header': 3.575.0 @@ -34758,8 +34758,8 @@ snapshots: '@aws-crypto/sha1-browser': 3.0.0 '@aws-crypto/sha256-browser': 3.0.0 '@aws-crypto/sha256-js': 3.0.0 - '@aws-sdk/client-sso-oidc': 3.575.0 - '@aws-sdk/client-sts': 3.575.0(@aws-sdk/client-sso-oidc@3.575.0) + '@aws-sdk/client-sso-oidc': 3.575.0(@aws-sdk/client-sts@3.575.0) + '@aws-sdk/client-sts': 3.575.0 '@aws-sdk/core': 3.575.0 '@aws-sdk/credential-provider-node': 3.575.0(@aws-sdk/client-sso-oidc@3.575.0)(@aws-sdk/client-sts@3.575.0) '@aws-sdk/middleware-bucket-endpoint': 3.575.0 @@ -34985,11 +34985,11 @@ snapshots: - aws-crt optional: true - '@aws-sdk/client-sso-oidc@3.575.0': + '@aws-sdk/client-sso-oidc@3.575.0(@aws-sdk/client-sts@3.575.0)': dependencies: '@aws-crypto/sha256-browser': 3.0.0 '@aws-crypto/sha256-js': 3.0.0 - '@aws-sdk/client-sts': 3.575.0(@aws-sdk/client-sso-oidc@3.575.0) + '@aws-sdk/client-sts': 3.575.0 '@aws-sdk/core': 3.575.0 '@aws-sdk/credential-provider-node': 3.575.0(@aws-sdk/client-sso-oidc@3.575.0)(@aws-sdk/client-sts@3.575.0) '@aws-sdk/middleware-host-header': 3.575.0 @@ -35028,6 +35028,7 @@ snapshots: '@smithy/util-utf8': 3.0.0 tslib: 2.7.0 transitivePeerDependencies: + - '@aws-sdk/client-sts' - aws-crt '@aws-sdk/client-sso-oidc@3.637.0(@aws-sdk/client-sts@3.637.0)': @@ -35412,11 +35413,11 @@ snapshots: - aws-crt optional: true - '@aws-sdk/client-sts@3.575.0(@aws-sdk/client-sso-oidc@3.575.0)': + '@aws-sdk/client-sts@3.575.0': dependencies: '@aws-crypto/sha256-browser': 3.0.0 '@aws-crypto/sha256-js': 3.0.0 - '@aws-sdk/client-sso-oidc': 3.575.0 + '@aws-sdk/client-sso-oidc': 3.575.0(@aws-sdk/client-sts@3.575.0) '@aws-sdk/core': 3.575.0 '@aws-sdk/credential-provider-node': 3.575.0(@aws-sdk/client-sso-oidc@3.575.0)(@aws-sdk/client-sts@3.575.0) '@aws-sdk/middleware-host-header': 3.575.0 @@ -35455,7 +35456,6 @@ snapshots: '@smithy/util-utf8': 3.0.0 tslib: 2.7.0 transitivePeerDependencies: - - '@aws-sdk/client-sso-oidc' - aws-crt '@aws-sdk/client-sts@3.637.0': @@ -35685,7 +35685,7 @@ snapshots: '@aws-sdk/credential-provider-ini@3.575.0(@aws-sdk/client-sso-oidc@3.575.0)(@aws-sdk/client-sts@3.575.0)': dependencies: - '@aws-sdk/client-sts': 3.575.0(@aws-sdk/client-sso-oidc@3.575.0) + '@aws-sdk/client-sts': 3.575.0 '@aws-sdk/credential-provider-env': 3.575.0 '@aws-sdk/credential-provider-process': 3.575.0 '@aws-sdk/credential-provider-sso': 3.575.0(@aws-sdk/client-sso-oidc@3.575.0) @@ -35996,7 +35996,7 @@ snapshots: '@aws-sdk/credential-provider-web-identity@3.575.0(@aws-sdk/client-sts@3.575.0)': dependencies: - '@aws-sdk/client-sts': 3.575.0(@aws-sdk/client-sso-oidc@3.575.0) + '@aws-sdk/client-sts': 3.575.0 '@aws-sdk/types': 3.575.0 '@smithy/property-provider': 3.1.3 '@smithy/types': 3.3.0 @@ -36517,7 +36517,7 @@ snapshots: '@aws-sdk/token-providers@3.575.0(@aws-sdk/client-sso-oidc@3.575.0)': dependencies: - '@aws-sdk/client-sso-oidc': 3.575.0 + '@aws-sdk/client-sso-oidc': 3.575.0(@aws-sdk/client-sts@3.575.0) '@aws-sdk/types': 3.575.0 '@smithy/property-provider': 3.1.3 '@smithy/shared-ini-file-loader': 3.1.4 @@ -36526,7 +36526,7 @@ snapshots: '@aws-sdk/token-providers@3.614.0(@aws-sdk/client-sso-oidc@3.575.0)': dependencies: - '@aws-sdk/client-sso-oidc': 3.575.0 + '@aws-sdk/client-sso-oidc': 3.575.0(@aws-sdk/client-sts@3.575.0) '@aws-sdk/types': 3.609.0 '@smithy/property-provider': 3.1.3 '@smithy/shared-ini-file-loader': 3.1.4 @@ -62728,7 +62728,7 @@ snapshots: eslint-import-resolver-node@0.3.9: dependencies: - debug: 3.2.7(supports-color@5.5.0) + debug: 3.2.7(supports-color@8.1.1) is-core-module: 2.15.1 resolve: 1.22.8 transitivePeerDependencies: @@ -62737,7 +62737,7 @@ snapshots: eslint-import-resolver-webpack@0.13.8(eslint-plugin-import@2.29.1)(webpack@5.94.0(@swc/core@1.3.107(@swc/helpers@0.5.12))): dependencies: array.prototype.find: 2.2.3 - debug: 3.2.7(supports-color@5.5.0) + debug: 3.2.7(supports-color@8.1.1) enhanced-resolve: 0.9.1 eslint-plugin-import: 2.29.1(@typescript-eslint/parser@8.3.0(eslint@8.57.1)(typescript@5.6.2))(eslint-import-resolver-webpack@0.13.8)(eslint@8.57.1) find-root: 1.1.0 @@ -62754,7 +62754,7 @@ snapshots: eslint-module-utils@2.8.2(@typescript-eslint/parser@5.62.0(eslint@9.9.1(jiti@1.21.6))(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-webpack@0.13.8(eslint-plugin-import@2.29.1)(webpack@5.94.0(@swc/core@1.3.107(@swc/helpers@0.5.12))))(eslint@9.9.1(jiti@1.21.6)): dependencies: - debug: 3.2.7(supports-color@5.5.0) + debug: 3.2.7(supports-color@8.1.1) optionalDependencies: '@typescript-eslint/parser': 5.62.0(eslint@9.9.1(jiti@1.21.6))(typescript@5.6.2) eslint: 9.9.1(jiti@1.21.6) @@ -62765,7 +62765,7 @@ snapshots: eslint-module-utils@2.8.2(@typescript-eslint/parser@8.3.0(eslint@8.57.1)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-webpack@0.13.8(eslint-plugin-import@2.29.1)(webpack@5.94.0(@swc/core@1.3.107(@swc/helpers@0.5.12))))(eslint@8.57.1): dependencies: - debug: 3.2.7(supports-color@5.5.0) + debug: 3.2.7(supports-color@8.1.1) optionalDependencies: '@typescript-eslint/parser': 8.3.0(eslint@8.57.1)(typescript@5.6.2) eslint: 8.57.1 @@ -62847,7 +62847,7 @@ snapshots: array.prototype.findlastindex: 1.2.5 array.prototype.flat: 1.3.2 array.prototype.flatmap: 1.3.2 - debug: 3.2.7(supports-color@5.5.0) + debug: 3.2.7(supports-color@8.1.1) doctrine: 2.1.0 eslint: 9.9.1(jiti@1.21.6) eslint-import-resolver-node: 0.3.9 @@ -62874,7 +62874,7 @@ snapshots: array.prototype.findlastindex: 1.2.5 array.prototype.flat: 1.3.2 array.prototype.flatmap: 1.3.2 - debug: 3.2.7(supports-color@5.5.0) + debug: 3.2.7(supports-color@8.1.1) doctrine: 2.1.0 eslint: 8.57.1 eslint-import-resolver-node: 0.3.9 @@ -70721,7 +70721,7 @@ snapshots: needle@2.4.0: dependencies: - debug: 3.2.7(supports-color@5.5.0) + debug: 3.2.7(supports-color@8.1.1) iconv-lite: 0.4.24 sax: 1.4.1 transitivePeerDependencies: @@ -70729,7 +70729,7 @@ snapshots: needle@3.2.0: dependencies: - debug: 3.2.7(supports-color@5.5.0) + debug: 3.2.7(supports-color@8.1.1) iconv-lite: 0.6.3 sax: 1.2.4 transitivePeerDependencies: @@ -72433,7 +72433,7 @@ snapshots: portfinder@1.0.32: dependencies: async: 2.6.4 - debug: 3.2.7(supports-color@5.5.0) + debug: 3.2.7(supports-color@8.1.1) mkdirp: 0.5.6 transitivePeerDependencies: - supports-color