Compare commits
9 Commits
fix/multip
...
feat/notif
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f797af64e7 | ||
|
|
1f0c780763 | ||
|
|
149277ef39 | ||
|
|
c8dcb17510 | ||
|
|
2f4aea52eb | ||
|
|
7973d8de2f | ||
|
|
7a0f89c4c0 | ||
|
|
105ba45412 | ||
|
|
3c46d82b7a |
@@ -20,7 +20,6 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@aws-sdk/client-s3": "^3.802.0",
|
"@aws-sdk/client-s3": "^3.802.0",
|
||||||
"@aws-sdk/lib-storage": "^3.802.0",
|
|
||||||
"@aws-sdk/s3-request-presigner": "^3.812.0",
|
"@aws-sdk/s3-request-presigner": "^3.812.0",
|
||||||
"@headlessui/react": "^2.2.0",
|
"@headlessui/react": "^2.2.0",
|
||||||
"@hookform/resolvers": "^3.3.4",
|
"@hookform/resolvers": "^3.3.4",
|
||||||
|
|||||||
@@ -387,46 +387,54 @@ export interface SlashNodeAttrs {
|
|||||||
label?: string | null;
|
label?: string | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const CommandItems: SlashCommandItem[] = [
|
const getCommandItems = (disableHeadings: boolean): SlashCommandItem[] => {
|
||||||
{
|
const headingCommands: SlashCommandItem[] = disableHeadings
|
||||||
title: "Heading 1",
|
? []
|
||||||
icon: <HiH1 />,
|
: [
|
||||||
command: ({ editor }) =>
|
{
|
||||||
editor.chain().focus().setHeading({ level: 1 }).run(),
|
title: "Heading 1",
|
||||||
},
|
icon: <HiH1 />,
|
||||||
{
|
command: ({ editor }) =>
|
||||||
title: "Heading 2",
|
editor.chain().focus().setHeading({ level: 1 }).run(),
|
||||||
icon: <HiH2 />,
|
},
|
||||||
command: ({ editor }) =>
|
{
|
||||||
editor.chain().focus().setHeading({ level: 2 }).run(),
|
title: "Heading 2",
|
||||||
},
|
icon: <HiH2 />,
|
||||||
{
|
command: ({ editor }) =>
|
||||||
title: "Heading 3",
|
editor.chain().focus().setHeading({ level: 2 }).run(),
|
||||||
icon: <HiH3 />,
|
},
|
||||||
command: ({ editor }) =>
|
{
|
||||||
editor.chain().focus().setHeading({ level: 3 }).run(),
|
title: "Heading 3",
|
||||||
},
|
icon: <HiH3 />,
|
||||||
{
|
command: ({ editor }) =>
|
||||||
title: "Bullet List",
|
editor.chain().focus().setHeading({ level: 3 }).run(),
|
||||||
icon: <HiOutlineListBullet />,
|
},
|
||||||
command: ({ editor }) => editor.chain().focus().toggleBulletList().run(),
|
];
|
||||||
},
|
|
||||||
{
|
return [
|
||||||
title: "Ordered List",
|
...headingCommands,
|
||||||
icon: <HiOutlineNumberedList />,
|
{
|
||||||
command: ({ editor }) => editor.chain().focus().toggleOrderedList().run(),
|
title: "Bullet List",
|
||||||
},
|
icon: <HiOutlineListBullet />,
|
||||||
{
|
command: ({ editor }) => editor.chain().focus().toggleBulletList().run(),
|
||||||
title: "Blockquote",
|
},
|
||||||
icon: <HiOutlineChatBubbleLeftEllipsis />,
|
{
|
||||||
command: ({ editor }) => editor.chain().focus().toggleBlockquote().run(),
|
title: "Ordered List",
|
||||||
},
|
icon: <HiOutlineNumberedList />,
|
||||||
{
|
command: ({ editor }) => editor.chain().focus().toggleOrderedList().run(),
|
||||||
title: "Code Block",
|
},
|
||||||
icon: <HiOutlineCodeBracketSquare />,
|
{
|
||||||
command: ({ editor }) => editor.chain().focus().toggleCodeBlock().run(),
|
title: "Blockquote",
|
||||||
},
|
icon: <HiOutlineChatBubbleLeftEllipsis />,
|
||||||
];
|
command: ({ editor }) => editor.chain().focus().toggleBlockquote().run(),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Code Block",
|
||||||
|
icon: <HiOutlineCodeBracketSquare />,
|
||||||
|
command: ({ editor }) => editor.chain().focus().toggleCodeBlock().run(),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
export default function Editor({
|
export default function Editor({
|
||||||
content,
|
content,
|
||||||
@@ -435,6 +443,8 @@ export default function Editor({
|
|||||||
readOnly = false,
|
readOnly = false,
|
||||||
workspaceMembers,
|
workspaceMembers,
|
||||||
enableYouTubeEmbed = true,
|
enableYouTubeEmbed = true,
|
||||||
|
placeholder,
|
||||||
|
disableHeadings = false,
|
||||||
}: {
|
}: {
|
||||||
content: string | null;
|
content: string | null;
|
||||||
onChange?: (value: string) => void;
|
onChange?: (value: string) => void;
|
||||||
@@ -442,18 +452,23 @@ export default function Editor({
|
|||||||
readOnly?: boolean;
|
readOnly?: boolean;
|
||||||
workspaceMembers: WorkspaceMember[];
|
workspaceMembers: WorkspaceMember[];
|
||||||
enableYouTubeEmbed?: boolean;
|
enableYouTubeEmbed?: boolean;
|
||||||
|
placeholder?: string;
|
||||||
|
disableHeadings?: boolean;
|
||||||
}) {
|
}) {
|
||||||
const containerRef = useRef<HTMLDivElement>(null);
|
const containerRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
const editor = useEditor(
|
const editor = useEditor(
|
||||||
{
|
{
|
||||||
extensions: [
|
extensions: [
|
||||||
StarterKit,
|
StarterKit.configure({
|
||||||
|
heading: disableHeadings ? false : undefined,
|
||||||
|
}),
|
||||||
Markdown,
|
Markdown,
|
||||||
Placeholder.configure({
|
Placeholder.configure({
|
||||||
placeholder: readOnly
|
placeholder: readOnly
|
||||||
? ""
|
? ""
|
||||||
: t`Add description... (type '/' to open commands or '@' to mention)`,
|
: placeholder ??
|
||||||
|
t`Add description... (type '/' to open commands or '@' to mention)`,
|
||||||
}),
|
}),
|
||||||
Link.configure({
|
Link.configure({
|
||||||
openOnClick: true,
|
openOnClick: true,
|
||||||
@@ -466,10 +481,10 @@ export default function Editor({
|
|||||||
autolink: true,
|
autolink: true,
|
||||||
}),
|
}),
|
||||||
SlashCommands.configure({
|
SlashCommands.configure({
|
||||||
commandItems: CommandItems,
|
commandItems: getCommandItems(disableHeadings),
|
||||||
suggestion: {
|
suggestion: {
|
||||||
items: ({ query }: { query: string }) =>
|
items: ({ query }: { query: string }) =>
|
||||||
filterSlashCommandItems(CommandItems, query),
|
filterSlashCommandItems(getCommandItems(disableHeadings), query),
|
||||||
startOfLine: true,
|
startOfLine: true,
|
||||||
char: "/",
|
char: "/",
|
||||||
},
|
},
|
||||||
@@ -481,20 +496,28 @@ export default function Editor({
|
|||||||
suggestion: {
|
suggestion: {
|
||||||
char: "@",
|
char: "@",
|
||||||
items: ({ query }: { query: string }) => {
|
items: ({ query }: { query: string }) => {
|
||||||
const all: MentionItem[] = workspaceMembers.map(
|
const withEmail = workspaceMembers.filter((member) => member.email);
|
||||||
(member: WorkspaceMember) => ({
|
|
||||||
id: member.publicId,
|
const mapped = withEmail.map((member: WorkspaceMember) => ({
|
||||||
label: member?.user?.name ?? member.email,
|
id: member.publicId,
|
||||||
image: member?.user?.image ?? null,
|
label: member?.user?.name?.trim() || member.email || "",
|
||||||
}),
|
image: member?.user?.image ?? null,
|
||||||
|
}));
|
||||||
|
|
||||||
|
const all: MentionItem[] = mapped.filter(
|
||||||
|
(item) => item.label && item.label.length > 0,
|
||||||
);
|
);
|
||||||
const q = query.toLowerCase();
|
|
||||||
return all.filter(
|
const q = query.toLowerCase().trim();
|
||||||
(u) =>
|
|
||||||
u.label &&
|
if (q === "") {
|
||||||
typeof u.label === "string" &&
|
return all;
|
||||||
u.label.toLowerCase().includes(q),
|
}
|
||||||
|
|
||||||
|
const filtered = all.filter((u) =>
|
||||||
|
u.label.toLowerCase().includes(q),
|
||||||
);
|
);
|
||||||
|
return filtered;
|
||||||
},
|
},
|
||||||
command: ({ editor, range, props }) => {
|
command: ({ editor, range, props }) => {
|
||||||
const id = props.id ?? "";
|
const id = props.id ?? "";
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import type { NextApiRequest, NextApiResponse } from "next";
|
import type { NextApiRequest, NextApiResponse } from "next";
|
||||||
import { Upload } from "@aws-sdk/lib-storage";
|
import { PutObjectCommand } from "@aws-sdk/client-s3";
|
||||||
|
|
||||||
import { createNextApiContext } from "@kan/api/trpc";
|
import { createNextApiContext } from "@kan/api/trpc";
|
||||||
import * as cardRepo from "@kan/db/repository/card.repo";
|
import * as cardRepo from "@kan/db/repository/card.repo";
|
||||||
@@ -90,19 +90,16 @@ export default withRateLimit(
|
|||||||
|
|
||||||
const client = createS3Client();
|
const client = createS3Client();
|
||||||
|
|
||||||
const upload = new Upload({
|
// Upload the file to S3
|
||||||
client,
|
await client.send(
|
||||||
params: {
|
new PutObjectCommand({
|
||||||
Bucket: bucket,
|
Bucket: bucket,
|
||||||
Key: s3Key,
|
Key: s3Key,
|
||||||
Body: req,
|
Body: req,
|
||||||
ContentType: contentType,
|
ContentType: contentType,
|
||||||
ContentLength: contentLength,
|
ContentLength: contentLength,
|
||||||
},
|
}),
|
||||||
leavePartsOnError: false,
|
);
|
||||||
});
|
|
||||||
|
|
||||||
await upload.done();
|
|
||||||
|
|
||||||
// Create attachment record and log activity
|
// Create attachment record and log activity
|
||||||
const attachment = await cardAttachmentRepo.create(db, {
|
const attachment = await cardAttachmentRepo.create(db, {
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
import { t } from "@lingui/core/macro";
|
import { t } from "@lingui/core/macro";
|
||||||
import { formatDistanceToNow } from "date-fns";
|
import { formatDistanceToNow } from "date-fns";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import ContentEditable from "react-contenteditable";
|
|
||||||
import { useForm } from "react-hook-form";
|
import { useForm } from "react-hook-form";
|
||||||
import { HiEllipsisHorizontal, HiPencil, HiTrash } from "react-icons/hi2";
|
import { HiEllipsisHorizontal, HiPencil, HiTrash } from "react-icons/hi2";
|
||||||
|
|
||||||
import Avatar from "~/components/Avatar";
|
import Avatar from "~/components/Avatar";
|
||||||
import Button from "~/components/Button";
|
import Button from "~/components/Button";
|
||||||
|
import Editor from "~/components/Editor";
|
||||||
|
import type { WorkspaceMember } from "~/components/Editor";
|
||||||
import Dropdown from "~/components/Dropdown";
|
import Dropdown from "~/components/Dropdown";
|
||||||
import { usePermissions } from "~/hooks/usePermissions";
|
import { usePermissions } from "~/hooks/usePermissions";
|
||||||
import { useModal } from "~/providers/modal";
|
import { useModal } from "~/providers/modal";
|
||||||
@@ -29,7 +30,6 @@ const Comment = ({
|
|||||||
createdAt,
|
createdAt,
|
||||||
comment,
|
comment,
|
||||||
isAuthor,
|
isAuthor,
|
||||||
isAdmin,
|
|
||||||
isEdited = false,
|
isEdited = false,
|
||||||
isViewOnly = false,
|
isViewOnly = false,
|
||||||
}: {
|
}: {
|
||||||
@@ -42,7 +42,6 @@ const Comment = ({
|
|||||||
createdAt: string;
|
createdAt: string;
|
||||||
comment: string | undefined;
|
comment: string | undefined;
|
||||||
isAuthor: boolean;
|
isAuthor: boolean;
|
||||||
isAdmin: boolean;
|
|
||||||
isEdited: boolean;
|
isEdited: boolean;
|
||||||
isViewOnly: boolean;
|
isViewOnly: boolean;
|
||||||
}) => {
|
}) => {
|
||||||
@@ -57,6 +56,30 @@ const Comment = ({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const { data: cardData } = api.card.byId.useQuery(
|
||||||
|
{
|
||||||
|
cardPublicId,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
enabled: !!cardPublicId && cardPublicId.length >= 12,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
const workspaceMembers: WorkspaceMember[] =
|
||||||
|
cardData?.list.board.workspace.members
|
||||||
|
.filter((member) => member.email)
|
||||||
|
.map((member) => ({
|
||||||
|
publicId: member.publicId,
|
||||||
|
email: member.email,
|
||||||
|
user: member.user
|
||||||
|
? {
|
||||||
|
id: member.user.id,
|
||||||
|
name: member.user.name ?? null,
|
||||||
|
image: member.user.image ?? null,
|
||||||
|
}
|
||||||
|
: null,
|
||||||
|
})) ?? [];
|
||||||
|
|
||||||
if (!publicId) return null;
|
if (!publicId) return null;
|
||||||
|
|
||||||
const updateCommentMutation = api.card.updateComment.useMutation({
|
const updateCommentMutation = api.card.updateComment.useMutation({
|
||||||
@@ -142,21 +165,28 @@ const Comment = ({
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
{!isEditing ? (
|
{!isEditing ? (
|
||||||
<ContentEditable
|
<div className="mt-2">
|
||||||
html={comment ?? ""}
|
<Editor
|
||||||
disabled={true}
|
content={comment ?? null}
|
||||||
className="break-anywhere mt-2 text-sm"
|
readOnly={true}
|
||||||
/>
|
workspaceMembers={workspaceMembers}
|
||||||
|
enableYouTubeEmbed={false}
|
||||||
|
disableHeadings={true}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<form onSubmit={handleSubmit(onSubmit)}>
|
<form onSubmit={handleSubmit(onSubmit)}>
|
||||||
<ContentEditable
|
<div className="mt-2">
|
||||||
placeholder={t`Add a comment...`}
|
<Editor
|
||||||
html={watch("comment")}
|
content={watch("comment")}
|
||||||
disabled={false}
|
onChange={(value) => setValue("comment", value)}
|
||||||
onChange={(e) => setValue("comment", e.target.value)}
|
workspaceMembers={workspaceMembers}
|
||||||
className="block w-full max-w-[800px] border-0 bg-transparent py-1.5 text-sm text-light-900 focus-visible:outline-none dark:text-dark-1000 sm:text-sm sm:leading-6"
|
enableYouTubeEmbed={false}
|
||||||
/>
|
placeholder={t`Add comment... (type '/' to open commands or '@' to mention)`}
|
||||||
<div className="flex justify-end space-x-2">
|
disableHeadings={true}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="flex justify-end space-x-2 mt-2">
|
||||||
<Button
|
<Button
|
||||||
size="sm"
|
size="sm"
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
import { t } from "@lingui/core/macro";
|
import { t } from "@lingui/core/macro";
|
||||||
import ContentEditable from "react-contenteditable";
|
|
||||||
import { useForm } from "react-hook-form";
|
import { useForm } from "react-hook-form";
|
||||||
import { HiOutlineArrowUp } from "react-icons/hi2";
|
import { HiOutlineArrowUp } from "react-icons/hi2";
|
||||||
|
|
||||||
|
import Editor from "~/components/Editor";
|
||||||
|
import type { WorkspaceMember } from "~/components/Editor";
|
||||||
import LoadingSpinner from "~/components/LoadingSpinner";
|
import LoadingSpinner from "~/components/LoadingSpinner";
|
||||||
import { usePermissions } from "~/hooks/usePermissions";
|
import { usePermissions } from "~/hooks/usePermissions";
|
||||||
import { usePopup } from "~/providers/popup";
|
import { usePopup } from "~/providers/popup";
|
||||||
@@ -13,7 +14,13 @@ interface FormValues {
|
|||||||
comment: string;
|
comment: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const NewCommentForm = ({ cardPublicId }: { cardPublicId: string }) => {
|
const NewCommentForm = ({
|
||||||
|
cardPublicId,
|
||||||
|
workspaceMembers,
|
||||||
|
}: {
|
||||||
|
cardPublicId: string;
|
||||||
|
workspaceMembers: WorkspaceMember[];
|
||||||
|
}) => {
|
||||||
const utils = api.useUtils();
|
const utils = api.useUtils();
|
||||||
const { showPopup } = usePopup();
|
const { showPopup } = usePopup();
|
||||||
const { canCreateComment } = usePermissions();
|
const { canCreateComment } = usePermissions();
|
||||||
@@ -23,10 +30,6 @@ const NewCommentForm = ({ cardPublicId }: { cardPublicId: string }) => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const queryParams = {
|
|
||||||
cardPublicId,
|
|
||||||
};
|
|
||||||
|
|
||||||
const addCommentMutation = api.card.addComment.useMutation({
|
const addCommentMutation = api.card.addComment.useMutation({
|
||||||
onError: (_error, _newList) => {
|
onError: (_error, _newList) => {
|
||||||
showPopup({
|
showPopup({
|
||||||
@@ -57,18 +60,13 @@ const NewCommentForm = ({ cardPublicId }: { cardPublicId: string }) => {
|
|||||||
onSubmit={handleSubmit(onSubmit)}
|
onSubmit={handleSubmit(onSubmit)}
|
||||||
className="flex w-full max-w-[800px] flex-col rounded-xl border border-light-600 bg-light-100 p-4 text-light-900 focus-visible:outline-none dark:border-dark-400 dark:bg-dark-100 dark:text-dark-1000 sm:text-sm sm:leading-6"
|
className="flex w-full max-w-[800px] flex-col rounded-xl border border-light-600 bg-light-100 p-4 text-light-900 focus-visible:outline-none dark:border-dark-400 dark:bg-dark-100 dark:text-dark-1000 sm:text-sm sm:leading-6"
|
||||||
>
|
>
|
||||||
<ContentEditable
|
<Editor
|
||||||
placeholder={t`Add a comment...`}
|
content={watch("comment")}
|
||||||
html={watch("comment")}
|
onChange={(value) => setValue("comment", value)}
|
||||||
disabled={false}
|
workspaceMembers={workspaceMembers}
|
||||||
onChange={(e) => setValue("comment", e.target.value)}
|
enableYouTubeEmbed={false}
|
||||||
className="block w-full border-0 bg-transparent py-1.5 text-light-900 focus-visible:outline-none dark:text-dark-1000 sm:text-sm sm:leading-6"
|
placeholder={t`Add comment... (type '/' to open commands or '@' to mention)`}
|
||||||
onKeyDown={async (e) => {
|
disableHeadings={true}
|
||||||
if (e.key === "Enter" && e.shiftKey) {
|
|
||||||
e.preventDefault();
|
|
||||||
await handleSubmit(onSubmit)();
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
<div className="flex justify-end">
|
<div className="flex justify-end">
|
||||||
<button
|
<button
|
||||||
|
|||||||
@@ -167,7 +167,6 @@ export default function CardPage({ isTemplate }: { isTemplate?: boolean }) {
|
|||||||
const {
|
const {
|
||||||
modalContentType,
|
modalContentType,
|
||||||
entityId,
|
entityId,
|
||||||
openModal,
|
|
||||||
getModalState,
|
getModalState,
|
||||||
clearModalState,
|
clearModalState,
|
||||||
isOpen,
|
isOpen,
|
||||||
@@ -198,8 +197,24 @@ export default function CardPage({ isTemplate }: { isTemplate?: boolean }) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const board = card?.list.board;
|
const board = card?.list.board;
|
||||||
|
const workspaceMembers = board?.workspace.members;
|
||||||
const boardId = board?.publicId;
|
const boardId = board?.publicId;
|
||||||
|
|
||||||
|
const editorWorkspaceMembers =
|
||||||
|
workspaceMembers
|
||||||
|
?.filter((member) => member.email)
|
||||||
|
.map((member) => ({
|
||||||
|
publicId: member.publicId,
|
||||||
|
email: member.email,
|
||||||
|
user: member.user
|
||||||
|
? {
|
||||||
|
id: member.user.id,
|
||||||
|
name: member.user.name ?? null,
|
||||||
|
image: member.user.image ?? null,
|
||||||
|
}
|
||||||
|
: null,
|
||||||
|
})) ?? [];
|
||||||
|
|
||||||
const updateCard = api.card.update.useMutation({
|
const updateCard = api.card.update.useMutation({
|
||||||
onError: () => {
|
onError: () => {
|
||||||
showPopup({
|
showPopup({
|
||||||
@@ -286,6 +301,7 @@ export default function CardPage({ isTemplate }: { isTemplate?: boolean }) {
|
|||||||
|
|
||||||
if (!cardId) return <></>;
|
if (!cardId) return <></>;
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<PageHead
|
<PageHead
|
||||||
@@ -387,7 +403,7 @@ export default function CardPage({ isTemplate }: { isTemplate?: boolean }) {
|
|||||||
onBlur={
|
onBlur={
|
||||||
canEdit ? () => handleSubmit(onSubmit)() : undefined
|
canEdit ? () => handleSubmit(onSubmit)() : undefined
|
||||||
}
|
}
|
||||||
workspaceMembers={board?.workspace.members ?? []}
|
workspaceMembers={workspaceMembers ?? []}
|
||||||
readOnly={!canEdit}
|
readOnly={!canEdit}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@@ -431,7 +447,10 @@ export default function CardPage({ isTemplate }: { isTemplate?: boolean }) {
|
|||||||
</div>
|
</div>
|
||||||
{!isTemplate && (
|
{!isTemplate && (
|
||||||
<div className="mt-6">
|
<div className="mt-6">
|
||||||
<NewCommentForm cardPublicId={cardId} />
|
<NewCommentForm
|
||||||
|
cardPublicId={cardId}
|
||||||
|
workspaceMembers={editorWorkspaceMembers}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import * as workspaceRepo from "@kan/db/repository/workspace.repo";
|
|||||||
|
|
||||||
import { createTRPCRouter, protectedProcedure, publicProcedure } from "../trpc";
|
import { createTRPCRouter, protectedProcedure, publicProcedure } from "../trpc";
|
||||||
import { mergeActivities } from "../utils/activities";
|
import { mergeActivities } from "../utils/activities";
|
||||||
|
import { sendMentionEmails } from "../utils/notifications";
|
||||||
import { assertCanDelete, assertCanEdit, assertPermission } from "../utils/permissions";
|
import { assertCanDelete, assertCanEdit, assertPermission } from "../utils/permissions";
|
||||||
import { generateAttachmentUrl, generateAvatarUrl } from "@kan/shared/utils";
|
import { generateAttachmentUrl, generateAvatarUrl } from "@kan/shared/utils";
|
||||||
|
|
||||||
@@ -153,6 +154,17 @@ export const cardRouter = createTRPCRouter({
|
|||||||
await cardActivityRepo.bulkCreate(ctx.db, cardActivitesInsert);
|
await cardActivityRepo.bulkCreate(ctx.db, cardActivitesInsert);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (input.description) {
|
||||||
|
sendMentionEmails({
|
||||||
|
db: ctx.db,
|
||||||
|
cardPublicId: newCard.publicId,
|
||||||
|
commentHtml: input.description,
|
||||||
|
commenterUserId: userId,
|
||||||
|
}).catch((error) => {
|
||||||
|
console.error("Failed to send mention emails:", error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return newCard;
|
return newCard;
|
||||||
}),
|
}),
|
||||||
addComment: protectedProcedure
|
addComment: protectedProcedure
|
||||||
@@ -215,6 +227,16 @@ export const cardRouter = createTRPCRouter({
|
|||||||
createdBy: userId,
|
createdBy: userId,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
sendMentionEmails({
|
||||||
|
db: ctx.db,
|
||||||
|
cardPublicId: input.cardPublicId,
|
||||||
|
commentHtml: input.comment,
|
||||||
|
commenterUserId: userId,
|
||||||
|
commentId: newComment.id,
|
||||||
|
}).catch((error) => {
|
||||||
|
console.error("Failed to send mention emails:", error);
|
||||||
|
});
|
||||||
|
|
||||||
return newComment;
|
return newComment;
|
||||||
}),
|
}),
|
||||||
updateComment: protectedProcedure
|
updateComment: protectedProcedure
|
||||||
@@ -295,6 +317,16 @@ export const cardRouter = createTRPCRouter({
|
|||||||
createdBy: userId,
|
createdBy: userId,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
sendMentionEmails({
|
||||||
|
db: ctx.db,
|
||||||
|
cardPublicId: input.cardPublicId,
|
||||||
|
commentHtml: input.comment,
|
||||||
|
commenterUserId: userId,
|
||||||
|
commentId: updatedComment.id,
|
||||||
|
}).catch((error) => {
|
||||||
|
console.error("Failed to send mention emails:", error);
|
||||||
|
});
|
||||||
|
|
||||||
return updatedComment;
|
return updatedComment;
|
||||||
}),
|
}),
|
||||||
deleteComment: protectedProcedure
|
deleteComment: protectedProcedure
|
||||||
@@ -924,6 +956,15 @@ export const cardRouter = createTRPCRouter({
|
|||||||
fromDescription: existingCard.description ?? undefined,
|
fromDescription: existingCard.description ?? undefined,
|
||||||
toDescription: input.description,
|
toDescription: input.description,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
sendMentionEmails({
|
||||||
|
db: ctx.db,
|
||||||
|
cardPublicId: input.cardPublicId,
|
||||||
|
commentHtml: input.description,
|
||||||
|
commenterUserId: userId,
|
||||||
|
}).catch((error) => {
|
||||||
|
console.error("Failed to send mention emails:", error);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
|
|||||||
133
packages/api/src/utils/notifications.ts
Normal file
133
packages/api/src/utils/notifications.ts
Normal file
@@ -0,0 +1,133 @@
|
|||||||
|
import { env } from "next-runtime-env";
|
||||||
|
|
||||||
|
import type { dbClient } from "@kan/db/client";
|
||||||
|
import * as cardRepo from "@kan/db/repository/card.repo";
|
||||||
|
import * as memberRepo from "@kan/db/repository/member.repo";
|
||||||
|
import * as notificationRepo from "@kan/db/repository/notification.repo";
|
||||||
|
import * as userRepo from "@kan/db/repository/user.repo";
|
||||||
|
import * as workspaceRepo from "@kan/db/repository/workspace.repo";
|
||||||
|
import { sendEmail } from "@kan/email";
|
||||||
|
import { parseMentionsFromHTML } from "@kan/shared/utils";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends mention notification emails to mentioned members
|
||||||
|
* Only sends emails for new mentions (checks notification table to avoid duplicates)
|
||||||
|
*/
|
||||||
|
export async function sendMentionEmails({
|
||||||
|
db,
|
||||||
|
cardPublicId,
|
||||||
|
commentHtml,
|
||||||
|
commenterUserId,
|
||||||
|
commentId,
|
||||||
|
}: {
|
||||||
|
db: dbClient;
|
||||||
|
cardPublicId: string;
|
||||||
|
commentHtml: string;
|
||||||
|
commenterUserId: string;
|
||||||
|
commentId?: number;
|
||||||
|
}) {
|
||||||
|
try {
|
||||||
|
// Parse mentions from HTML
|
||||||
|
const mentionPublicIds = parseMentionsFromHTML(commentHtml);
|
||||||
|
if (mentionPublicIds.length === 0) return;
|
||||||
|
|
||||||
|
// Get card with board information
|
||||||
|
const card = await cardRepo.getWithListAndMembersByPublicId(db, cardPublicId);
|
||||||
|
if (!card?.list.board) return;
|
||||||
|
|
||||||
|
const board = card.list.board;
|
||||||
|
const boardName = board.name;
|
||||||
|
const cardTitle = card.title;
|
||||||
|
const cardId = card.id;
|
||||||
|
|
||||||
|
// Get workspace ID from workspace publicId
|
||||||
|
const workspace = await workspaceRepo.getByPublicId(
|
||||||
|
db,
|
||||||
|
board.workspace.publicId,
|
||||||
|
);
|
||||||
|
if (!workspace?.id) return;
|
||||||
|
|
||||||
|
const workspaceId = workspace.id;
|
||||||
|
|
||||||
|
// Get commenter information
|
||||||
|
const commenter = await userRepo.getById(db, commenterUserId);
|
||||||
|
if (!commenter) return;
|
||||||
|
|
||||||
|
const commenterName = commenter.name ?? commenter.email;
|
||||||
|
|
||||||
|
// Get mentioned members with full details (filtered by workspace)
|
||||||
|
const membersWithDetails = await memberRepo.getByPublicIdsWithUsers(
|
||||||
|
db,
|
||||||
|
mentionPublicIds,
|
||||||
|
workspaceId,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Filter out the commenter
|
||||||
|
const membersToNotify = membersWithDetails.filter(
|
||||||
|
(member) => member.user?.id !== commenterUserId,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (membersToNotify.length === 0) return;
|
||||||
|
|
||||||
|
const baseUrl = env("NEXT_PUBLIC_BASE_URL");
|
||||||
|
const cardUrl = `${baseUrl}/cards/${cardPublicId}`;
|
||||||
|
|
||||||
|
// Send emails to all mentioned members (only if notification doesn't exist)
|
||||||
|
await Promise.all(
|
||||||
|
membersToNotify.map(async (member) => {
|
||||||
|
const userId = member.user?.id;
|
||||||
|
const email = member.user?.email ?? member.email;
|
||||||
|
|
||||||
|
// Skip pending members (no userId) - they can be mentioned but won't receive emails
|
||||||
|
if (!userId || !email) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Check if notification already exists for this mention
|
||||||
|
const notificationExists = await notificationRepo.exists(db, {
|
||||||
|
userId,
|
||||||
|
cardId,
|
||||||
|
type: "mention",
|
||||||
|
});
|
||||||
|
|
||||||
|
// If notification already exists, skip sending email
|
||||||
|
if (notificationExists) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create notification record
|
||||||
|
await notificationRepo.create(db, {
|
||||||
|
type: "mention",
|
||||||
|
userId,
|
||||||
|
cardId,
|
||||||
|
commentId,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Send email
|
||||||
|
await sendEmail(
|
||||||
|
email,
|
||||||
|
`${commenterName} mentioned you in a comment on ${cardTitle}`,
|
||||||
|
"MENTION",
|
||||||
|
{
|
||||||
|
commenterName,
|
||||||
|
boardName,
|
||||||
|
cardTitle,
|
||||||
|
cardUrl,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Failed to send mention email:", {
|
||||||
|
email,
|
||||||
|
cardPublicId,
|
||||||
|
error: error instanceof Error ? error.message : String(error),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error sending mention emails:", {
|
||||||
|
cardPublicId,
|
||||||
|
error: error instanceof Error ? error.message : String(error),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
CREATE TYPE "public"."notification_type" AS ENUM('mention', 'workspace.member.added', 'workspace.member.removed', 'workspace.role.changed');--> statement-breakpoint
|
||||||
|
CREATE TABLE IF NOT EXISTS "notification" (
|
||||||
|
"id" bigserial PRIMARY KEY NOT NULL,
|
||||||
|
"publicId" varchar(12) NOT NULL,
|
||||||
|
"type" "notification_type" NOT NULL,
|
||||||
|
"userId" uuid NOT NULL,
|
||||||
|
"cardId" bigint,
|
||||||
|
"commentId" bigint,
|
||||||
|
"workspaceId" bigint,
|
||||||
|
"metadata" text,
|
||||||
|
"readAt" timestamp,
|
||||||
|
"createdAt" timestamp DEFAULT now() NOT NULL,
|
||||||
|
"deletedAt" timestamp,
|
||||||
|
CONSTRAINT "notification_publicId_unique" UNIQUE("publicId")
|
||||||
|
);
|
||||||
|
--> statement-breakpoint
|
||||||
|
ALTER TABLE "notification" ENABLE ROW LEVEL SECURITY;--> statement-breakpoint
|
||||||
|
DO $$ BEGIN
|
||||||
|
ALTER TABLE "notification" ADD CONSTRAINT "notification_userId_user_id_fk" FOREIGN KEY ("userId") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;
|
||||||
|
EXCEPTION
|
||||||
|
WHEN duplicate_object THEN null;
|
||||||
|
END $$;
|
||||||
|
--> statement-breakpoint
|
||||||
|
DO $$ BEGIN
|
||||||
|
ALTER TABLE "notification" ADD CONSTRAINT "notification_cardId_card_id_fk" FOREIGN KEY ("cardId") REFERENCES "public"."card"("id") ON DELETE cascade ON UPDATE no action;
|
||||||
|
EXCEPTION
|
||||||
|
WHEN duplicate_object THEN null;
|
||||||
|
END $$;
|
||||||
|
--> statement-breakpoint
|
||||||
|
DO $$ BEGIN
|
||||||
|
ALTER TABLE "notification" ADD CONSTRAINT "notification_commentId_card_comments_id_fk" FOREIGN KEY ("commentId") REFERENCES "public"."card_comments"("id") ON DELETE cascade ON UPDATE no action;
|
||||||
|
EXCEPTION
|
||||||
|
WHEN duplicate_object THEN null;
|
||||||
|
END $$;
|
||||||
|
--> statement-breakpoint
|
||||||
|
DO $$ BEGIN
|
||||||
|
ALTER TABLE "notification" ADD CONSTRAINT "notification_workspaceId_workspace_id_fk" FOREIGN KEY ("workspaceId") REFERENCES "public"."workspace"("id") ON DELETE cascade ON UPDATE no action;
|
||||||
|
EXCEPTION
|
||||||
|
WHEN duplicate_object THEN null;
|
||||||
|
END $$;
|
||||||
|
--> statement-breakpoint
|
||||||
|
CREATE INDEX IF NOT EXISTS "notification_user_deleted_idx" ON "notification" USING btree ("userId","deletedAt");--> statement-breakpoint
|
||||||
|
CREATE INDEX IF NOT EXISTS "notification_user_read_deleted_idx" ON "notification" USING btree ("userId","readAt","deletedAt");--> statement-breakpoint
|
||||||
|
CREATE INDEX IF NOT EXISTS "notification_user_type_card_idx" ON "notification" USING btree ("userId","type","cardId");--> statement-breakpoint
|
||||||
|
CREATE INDEX IF NOT EXISTS "notification_user_type_workspace_idx" ON "notification" USING btree ("userId","type","workspaceId");--> statement-breakpoint
|
||||||
|
CREATE INDEX IF NOT EXISTS "notification_user_created_idx" ON "notification" USING btree ("userId","createdAt");
|
||||||
3687
packages/db/migrations/meta/20260207214056_snapshot.json
Normal file
3687
packages/db/migrations/meta/20260207214056_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
@@ -176,6 +176,13 @@
|
|||||||
"when": 1769983198190,
|
"when": 1769983198190,
|
||||||
"tag": "20260201215958_AddUserBoardFavouritesTable",
|
"tag": "20260201215958_AddUserBoardFavouritesTable",
|
||||||
"breakpoints": true
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 25,
|
||||||
|
"version": "7",
|
||||||
|
"when": 1770500457005,
|
||||||
|
"tag": "20260207214056_AddNotificationsTable",
|
||||||
|
"breakpoints": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -212,6 +212,7 @@ export const getByPublicId = async (
|
|||||||
columns: {
|
columns: {
|
||||||
publicId: true,
|
publicId: true,
|
||||||
email: true,
|
email: true,
|
||||||
|
status: true,
|
||||||
},
|
},
|
||||||
with: {
|
with: {
|
||||||
user: {
|
user: {
|
||||||
|
|||||||
@@ -420,6 +420,7 @@ export const getWithListAndMembersByPublicId = async (
|
|||||||
) => {
|
) => {
|
||||||
const card = await db.query.cards.findFirst({
|
const card = await db.query.cards.findFirst({
|
||||||
columns: {
|
columns: {
|
||||||
|
id: true,
|
||||||
publicId: true,
|
publicId: true,
|
||||||
title: true,
|
title: true,
|
||||||
description: true,
|
description: true,
|
||||||
@@ -507,6 +508,7 @@ export const getWithListAndMembersByPublicId = async (
|
|||||||
columns: {
|
columns: {
|
||||||
publicId: true,
|
publicId: true,
|
||||||
email: true,
|
email: true,
|
||||||
|
status: true,
|
||||||
},
|
},
|
||||||
with: {
|
with: {
|
||||||
user: {
|
user: {
|
||||||
|
|||||||
@@ -63,6 +63,36 @@ export const getById = async (db: dbClient, memberId: number) => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getByPublicIdsWithUsers = async (
|
||||||
|
db: dbClient,
|
||||||
|
memberPublicIds: string[],
|
||||||
|
workspaceId?: number,
|
||||||
|
) => {
|
||||||
|
return db.query.workspaceMembers.findMany({
|
||||||
|
where: (members, { inArray: inArrayFn, eq, and, isNull: isNullFn }) => {
|
||||||
|
const conditions = [inArrayFn(members.publicId, memberPublicIds)];
|
||||||
|
|
||||||
|
if (workspaceId) {
|
||||||
|
conditions.push(eq(members.workspaceId, workspaceId));
|
||||||
|
}
|
||||||
|
|
||||||
|
conditions.push(eq(members.status, "active"));
|
||||||
|
conditions.push(isNullFn(members.deletedAt));
|
||||||
|
|
||||||
|
return and(...conditions);
|
||||||
|
},
|
||||||
|
with: {
|
||||||
|
user: {
|
||||||
|
columns: {
|
||||||
|
id: true,
|
||||||
|
name: true,
|
||||||
|
email: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
export const getByEmailAndStatus = async (
|
export const getByEmailAndStatus = async (
|
||||||
db: dbClient,
|
db: dbClient,
|
||||||
email: string,
|
email: string,
|
||||||
|
|||||||
98
packages/db/src/repository/notification.repo.ts
Normal file
98
packages/db/src/repository/notification.repo.ts
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
import { and, count, eq, isNull } from "drizzle-orm";
|
||||||
|
|
||||||
|
import type { dbClient } from "@kan/db/client";
|
||||||
|
import type { NotificationType } from "@kan/db/schema";
|
||||||
|
import { notifications } from "@kan/db/schema";
|
||||||
|
import { generateUID } from "@kan/shared/utils";
|
||||||
|
|
||||||
|
export const create = async (
|
||||||
|
db: dbClient,
|
||||||
|
notificationInput: {
|
||||||
|
type: NotificationType;
|
||||||
|
userId: string;
|
||||||
|
cardId?: number;
|
||||||
|
commentId?: number;
|
||||||
|
workspaceId?: number;
|
||||||
|
metadata?: string;
|
||||||
|
},
|
||||||
|
) => {
|
||||||
|
const [result] = await db
|
||||||
|
.insert(notifications)
|
||||||
|
.values({
|
||||||
|
publicId: generateUID(),
|
||||||
|
type: notificationInput.type,
|
||||||
|
userId: notificationInput.userId,
|
||||||
|
cardId: notificationInput.cardId,
|
||||||
|
commentId: notificationInput.commentId,
|
||||||
|
workspaceId: notificationInput.workspaceId,
|
||||||
|
metadata: notificationInput.metadata,
|
||||||
|
})
|
||||||
|
.returning();
|
||||||
|
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const exists = async (
|
||||||
|
db: dbClient,
|
||||||
|
args: {
|
||||||
|
userId: string;
|
||||||
|
type: NotificationType;
|
||||||
|
cardId?: number;
|
||||||
|
workspaceId?: number;
|
||||||
|
commentId?: number;
|
||||||
|
},
|
||||||
|
) => {
|
||||||
|
const result = await db.query.notifications.findFirst({
|
||||||
|
where: (notifications, { eq, and, isNull: isNullFn }) => {
|
||||||
|
const conditions = [
|
||||||
|
eq(notifications.userId, args.userId),
|
||||||
|
eq(notifications.type, args.type),
|
||||||
|
isNullFn(notifications.deletedAt),
|
||||||
|
];
|
||||||
|
|
||||||
|
if (args.cardId) {
|
||||||
|
conditions.push(eq(notifications.cardId, args.cardId));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (args.workspaceId) {
|
||||||
|
conditions.push(eq(notifications.workspaceId, args.workspaceId));
|
||||||
|
}
|
||||||
|
|
||||||
|
return and(...conditions);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return !!result;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const markAsRead = async (
|
||||||
|
db: dbClient,
|
||||||
|
notificationId: number,
|
||||||
|
) => {
|
||||||
|
const [result] = await db
|
||||||
|
.update(notifications)
|
||||||
|
.set({ readAt: new Date() })
|
||||||
|
.where(eq(notifications.id, notificationId))
|
||||||
|
.returning();
|
||||||
|
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getUnreadCount = async (
|
||||||
|
db: dbClient,
|
||||||
|
userId: string,
|
||||||
|
) => {
|
||||||
|
const result = await db
|
||||||
|
.select({ count: count() })
|
||||||
|
.from(notifications)
|
||||||
|
.where(
|
||||||
|
and(
|
||||||
|
eq(notifications.userId, userId),
|
||||||
|
isNull(notifications.readAt),
|
||||||
|
isNull(notifications.deletedAt),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
return result[0]?.count ?? 0;
|
||||||
|
};
|
||||||
|
|
||||||
@@ -13,3 +13,4 @@ export * from "./workspaces";
|
|||||||
export * from "./subscriptions";
|
export * from "./subscriptions";
|
||||||
export * from "./workspaceInviteLinks";
|
export * from "./workspaceInviteLinks";
|
||||||
export * from "./permissions";
|
export * from "./permissions";
|
||||||
|
export * from "./notifications";
|
||||||
|
|||||||
98
packages/db/src/schema/notifications.ts
Normal file
98
packages/db/src/schema/notifications.ts
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
import { relations } from "drizzle-orm";
|
||||||
|
import {
|
||||||
|
bigint,
|
||||||
|
bigserial,
|
||||||
|
index,
|
||||||
|
pgEnum,
|
||||||
|
pgTable,
|
||||||
|
text,
|
||||||
|
timestamp,
|
||||||
|
uuid,
|
||||||
|
varchar,
|
||||||
|
} from "drizzle-orm/pg-core";
|
||||||
|
|
||||||
|
import { cards } from "./cards";
|
||||||
|
import { comments } from "./cards";
|
||||||
|
import { users } from "./users";
|
||||||
|
import { workspaces } from "./workspaces";
|
||||||
|
|
||||||
|
export const notificationTypes = [
|
||||||
|
"mention",
|
||||||
|
"workspace.member.added",
|
||||||
|
"workspace.member.removed",
|
||||||
|
"workspace.role.changed",
|
||||||
|
] as const;
|
||||||
|
|
||||||
|
export type NotificationType = (typeof notificationTypes)[number];
|
||||||
|
|
||||||
|
export const notificationTypeEnum = pgEnum("notification_type", notificationTypes);
|
||||||
|
|
||||||
|
export const notifications = pgTable(
|
||||||
|
"notification",
|
||||||
|
{
|
||||||
|
id: bigserial("id", { mode: "number" }).primaryKey(),
|
||||||
|
publicId: varchar("publicId", { length: 12 }).notNull().unique(),
|
||||||
|
type: notificationTypeEnum("type").notNull(),
|
||||||
|
userId: uuid("userId")
|
||||||
|
.notNull()
|
||||||
|
.references(() => users.id, { onDelete: "cascade" }),
|
||||||
|
cardId: bigint("cardId", { mode: "number" }).references(() => cards.id, {
|
||||||
|
onDelete: "cascade",
|
||||||
|
}),
|
||||||
|
commentId: bigint("commentId", { mode: "number" }).references(
|
||||||
|
() => comments.id,
|
||||||
|
{ onDelete: "cascade" },
|
||||||
|
),
|
||||||
|
workspaceId: bigint("workspaceId", { mode: "number" }).references(
|
||||||
|
() => workspaces.id,
|
||||||
|
{ onDelete: "cascade" },
|
||||||
|
),
|
||||||
|
metadata: text("metadata"),
|
||||||
|
readAt: timestamp("readAt"),
|
||||||
|
createdAt: timestamp("createdAt").defaultNow().notNull(),
|
||||||
|
deletedAt: timestamp("deletedAt"),
|
||||||
|
},
|
||||||
|
(table) => [
|
||||||
|
index("notification_user_deleted_idx").on(table.userId, table.deletedAt),
|
||||||
|
index("notification_user_read_deleted_idx").on(
|
||||||
|
table.userId,
|
||||||
|
table.readAt,
|
||||||
|
table.deletedAt,
|
||||||
|
),
|
||||||
|
index("notification_user_type_card_idx").on(
|
||||||
|
table.userId,
|
||||||
|
table.type,
|
||||||
|
table.cardId,
|
||||||
|
),
|
||||||
|
index("notification_user_type_workspace_idx").on(
|
||||||
|
table.userId,
|
||||||
|
table.type,
|
||||||
|
table.workspaceId,
|
||||||
|
),
|
||||||
|
index("notification_user_created_idx").on(table.userId, table.createdAt),
|
||||||
|
],
|
||||||
|
).enableRLS();
|
||||||
|
|
||||||
|
export const notificationsRelations = relations(notifications, ({ one }) => ({
|
||||||
|
user: one(users, {
|
||||||
|
fields: [notifications.userId],
|
||||||
|
references: [users.id],
|
||||||
|
relationName: "notificationsUser",
|
||||||
|
}),
|
||||||
|
card: one(cards, {
|
||||||
|
fields: [notifications.cardId],
|
||||||
|
references: [cards.id],
|
||||||
|
relationName: "notificationsCard",
|
||||||
|
}),
|
||||||
|
comment: one(comments, {
|
||||||
|
fields: [notifications.commentId],
|
||||||
|
references: [comments.id],
|
||||||
|
relationName: "notificationsComment",
|
||||||
|
}),
|
||||||
|
workspace: one(workspaces, {
|
||||||
|
fields: [notifications.workspaceId],
|
||||||
|
references: [workspaces.id],
|
||||||
|
relationName: "notificationsWorkspace",
|
||||||
|
}),
|
||||||
|
}));
|
||||||
|
|
||||||
@@ -3,14 +3,16 @@ import nodemailer from "nodemailer";
|
|||||||
|
|
||||||
import JoinWorkspaceTemplate from "./templates/join-workspace";
|
import JoinWorkspaceTemplate from "./templates/join-workspace";
|
||||||
import MagicLinkTemplate from "./templates/magic-link";
|
import MagicLinkTemplate from "./templates/magic-link";
|
||||||
|
import MentionTemplate from "./templates/mention";
|
||||||
import ResetPasswordTemplate from "./templates/reset-password";
|
import ResetPasswordTemplate from "./templates/reset-password";
|
||||||
|
|
||||||
type Templates = "MAGIC_LINK" | "JOIN_WORKSPACE" | "RESET_PASSWORD";
|
type Templates = "MAGIC_LINK" | "JOIN_WORKSPACE" | "RESET_PASSWORD" | "MENTION";
|
||||||
|
|
||||||
const emailTemplates: Record<Templates, React.FC> = {
|
const emailTemplates: Record<Templates, React.ComponentType<any>> = {
|
||||||
MAGIC_LINK: MagicLinkTemplate,
|
MAGIC_LINK: MagicLinkTemplate,
|
||||||
JOIN_WORKSPACE: JoinWorkspaceTemplate,
|
JOIN_WORKSPACE: JoinWorkspaceTemplate,
|
||||||
RESET_PASSWORD: ResetPasswordTemplate,
|
RESET_PASSWORD: ResetPasswordTemplate,
|
||||||
|
MENTION: MentionTemplate,
|
||||||
};
|
};
|
||||||
|
|
||||||
const transporter = nodemailer.createTransport({
|
const transporter = nodemailer.createTransport({
|
||||||
|
|||||||
108
packages/email/src/templates/mention.tsx
Normal file
108
packages/email/src/templates/mention.tsx
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
import { Body } from "@react-email/body";
|
||||||
|
import { Button } from "@react-email/button";
|
||||||
|
import { Container } from "@react-email/container";
|
||||||
|
import { Head } from "@react-email/head";
|
||||||
|
import { Heading } from "@react-email/heading";
|
||||||
|
import { Hr } from "@react-email/hr";
|
||||||
|
import { Html } from "@react-email/html";
|
||||||
|
import { Link } from "@react-email/link";
|
||||||
|
import { Preview } from "@react-email/preview";
|
||||||
|
import { Text } from "@react-email/text";
|
||||||
|
import { env } from "next-runtime-env";
|
||||||
|
import * as React from "react";
|
||||||
|
|
||||||
|
export const MentionTemplate = ({
|
||||||
|
commenterName,
|
||||||
|
boardName,
|
||||||
|
cardTitle,
|
||||||
|
cardUrl,
|
||||||
|
}: {
|
||||||
|
commenterName: string;
|
||||||
|
boardName: string;
|
||||||
|
cardTitle: string;
|
||||||
|
cardUrl: string;
|
||||||
|
}) => (
|
||||||
|
<Html>
|
||||||
|
<Head />
|
||||||
|
<Preview>
|
||||||
|
{commenterName} mentioned you in a comment on {cardTitle}
|
||||||
|
</Preview>
|
||||||
|
<Body style={{ backgroundColor: "white" }}>
|
||||||
|
<Container
|
||||||
|
style={{
|
||||||
|
fontFamily:
|
||||||
|
'-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif',
|
||||||
|
margin: "auto",
|
||||||
|
paddingLeft: "0.75rem",
|
||||||
|
paddingRight: "0.75rem",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Heading
|
||||||
|
style={{
|
||||||
|
marginTop: "2.5rem",
|
||||||
|
marginBottom: "2.5rem",
|
||||||
|
fontSize: "24px",
|
||||||
|
fontWeight: "bold",
|
||||||
|
color: "#232323",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
kan.bn
|
||||||
|
</Heading>
|
||||||
|
<Heading
|
||||||
|
style={{ fontSize: "24px", fontWeight: "bold", color: "#232323" }}
|
||||||
|
>
|
||||||
|
You were mentioned in a comment
|
||||||
|
</Heading>
|
||||||
|
<Text
|
||||||
|
style={{
|
||||||
|
fontSize: "0.875rem",
|
||||||
|
marginBottom: "1rem",
|
||||||
|
color: "#232323",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<strong>{commenterName}</strong> mentioned you in a comment on the
|
||||||
|
card <strong>{cardTitle}</strong> in the board <strong>{boardName}</strong>.
|
||||||
|
</Text>
|
||||||
|
<Button
|
||||||
|
target="_blank"
|
||||||
|
href={cardUrl}
|
||||||
|
style={{
|
||||||
|
marginBottom: "2rem",
|
||||||
|
borderRadius: "0.375rem",
|
||||||
|
backgroundColor: "#282828",
|
||||||
|
paddingLeft: "1.5rem",
|
||||||
|
paddingRight: "1.5rem",
|
||||||
|
paddingTop: "1rem",
|
||||||
|
paddingBottom: "1rem",
|
||||||
|
fontSize: "0.875rem",
|
||||||
|
fontWeight: "500",
|
||||||
|
lineHeight: "1",
|
||||||
|
color: "white",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
View Card
|
||||||
|
</Button>
|
||||||
|
<Hr
|
||||||
|
style={{
|
||||||
|
marginTop: "2.5rem",
|
||||||
|
marginBottom: "2rem",
|
||||||
|
borderWidth: "1px",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Text style={{ color: "#7e7e7e" }}>
|
||||||
|
<Link
|
||||||
|
href={env("NEXT_PUBLIC_BASE_URL")}
|
||||||
|
target="_blank"
|
||||||
|
style={{ color: "#7e7e7e", textDecoration: "underline" }}
|
||||||
|
>
|
||||||
|
Kan
|
||||||
|
</Link>
|
||||||
|
, the open source Trello alternative.
|
||||||
|
</Text>
|
||||||
|
</Container>
|
||||||
|
</Body>
|
||||||
|
</Html>
|
||||||
|
);
|
||||||
|
|
||||||
|
export default MentionTemplate;
|
||||||
|
|
||||||
@@ -4,3 +4,4 @@ export * from "./subscriptions";
|
|||||||
export * from "./email";
|
export * from "./email";
|
||||||
export * from "./dueDateFilters";
|
export * from "./dueDateFilters";
|
||||||
export * from "./s3";
|
export * from "./s3";
|
||||||
|
export * from "./mentions";
|
||||||
|
|||||||
22
packages/shared/src/utils/mentions.ts
Normal file
22
packages/shared/src/utils/mentions.ts
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
/**
|
||||||
|
* Parses mention data-id attributes from HTML content
|
||||||
|
* Mentions are stored as: <span data-type="mention" data-id="..." data-label="...">@label</span>
|
||||||
|
* @param htmlContent - The HTML content to parse
|
||||||
|
* @returns Array of unique mention public IDs
|
||||||
|
*/
|
||||||
|
export function parseMentionsFromHTML(htmlContent: string): string[] {
|
||||||
|
if (!htmlContent) return [];
|
||||||
|
|
||||||
|
// Match all mention spans with data-id attributes
|
||||||
|
const mentionRegex = /<span[^>]*data-type="mention"[^>]*data-id="([^"]+)"[^>]*>/gi;
|
||||||
|
const matches = Array.from(htmlContent.matchAll(mentionRegex));
|
||||||
|
|
||||||
|
// Extract unique mention IDs
|
||||||
|
const mentionIds = matches
|
||||||
|
.map((match) => match[1])
|
||||||
|
.filter((id): id is string => !!id && id.length >= 12);
|
||||||
|
|
||||||
|
// Return unique IDs
|
||||||
|
return Array.from(new Set(mentionIds));
|
||||||
|
}
|
||||||
|
|
||||||
304
pnpm-lock.yaml
generated
304
pnpm-lock.yaml
generated
@@ -82,9 +82,6 @@ importers:
|
|||||||
'@aws-sdk/client-s3':
|
'@aws-sdk/client-s3':
|
||||||
specifier: ^3.802.0
|
specifier: ^3.802.0
|
||||||
version: 3.879.0
|
version: 3.879.0
|
||||||
'@aws-sdk/lib-storage':
|
|
||||||
specifier: ^3.802.0
|
|
||||||
version: 3.985.0(@aws-sdk/client-s3@3.879.0)
|
|
||||||
'@aws-sdk/s3-request-presigner':
|
'@aws-sdk/s3-request-presigner':
|
||||||
specifier: ^3.812.0
|
specifier: ^3.812.0
|
||||||
version: 3.879.0
|
version: 3.879.0
|
||||||
@@ -299,9 +296,6 @@ importers:
|
|||||||
|
|
||||||
packages/api:
|
packages/api:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@aws-sdk/lib-storage':
|
|
||||||
specifier: ^3.802.0
|
|
||||||
version: 3.985.0(@aws-sdk/client-s3@3.879.0)
|
|
||||||
'@kan/auth':
|
'@kan/auth':
|
||||||
specifier: workspace:*
|
specifier: workspace:*
|
||||||
version: link:../auth
|
version: link:../auth
|
||||||
@@ -743,12 +737,6 @@ packages:
|
|||||||
resolution: {integrity: sha512-Jy4uPFfGzHk1Mxy+/Wr43vuw9yXsE2yiF4e4598vc3aJfO0YtA2nSfbKD3PNKRORwXbeKqWPfph9SCKQpWoxEg==}
|
resolution: {integrity: sha512-Jy4uPFfGzHk1Mxy+/Wr43vuw9yXsE2yiF4e4598vc3aJfO0YtA2nSfbKD3PNKRORwXbeKqWPfph9SCKQpWoxEg==}
|
||||||
engines: {node: '>=18.0.0'}
|
engines: {node: '>=18.0.0'}
|
||||||
|
|
||||||
'@aws-sdk/lib-storage@3.985.0':
|
|
||||||
resolution: {integrity: sha512-EnqXf2E+5+7e5zuz8mPl+3Dk/DI0ObSL8s7Tsf6H8FL/p2BJw2LhgtxPnFZUmpanpoMO0hC9/qjXNd+aGPV0/w==}
|
|
||||||
engines: {node: '>=20.0.0'}
|
|
||||||
peerDependencies:
|
|
||||||
'@aws-sdk/client-s3': ^3.985.0
|
|
||||||
|
|
||||||
'@aws-sdk/middleware-bucket-endpoint@3.873.0':
|
'@aws-sdk/middleware-bucket-endpoint@3.873.0':
|
||||||
resolution: {integrity: sha512-b4bvr0QdADeTUs+lPc9Z48kXzbKHXQKgTvxx/jXDgSW9tv4KmYPO1gIj6Z9dcrBkRWQuUtSW3Tu2S5n6pe+zeg==}
|
resolution: {integrity: sha512-b4bvr0QdADeTUs+lPc9Z48kXzbKHXQKgTvxx/jXDgSW9tv4KmYPO1gIj6Z9dcrBkRWQuUtSW3Tu2S5n6pe+zeg==}
|
||||||
engines: {node: '>=18.0.0'}
|
engines: {node: '>=18.0.0'}
|
||||||
@@ -3315,10 +3303,6 @@ packages:
|
|||||||
resolution: {integrity: sha512-jcrqdTQurIrBbUm4W2YdLVMQDoL0sA9DTxYd2s+R/y+2U9NLOP7Xf/YqfSg1FZhlZIYEnvk2mwbyvIfdLEPo8g==}
|
resolution: {integrity: sha512-jcrqdTQurIrBbUm4W2YdLVMQDoL0sA9DTxYd2s+R/y+2U9NLOP7Xf/YqfSg1FZhlZIYEnvk2mwbyvIfdLEPo8g==}
|
||||||
engines: {node: '>=18.0.0'}
|
engines: {node: '>=18.0.0'}
|
||||||
|
|
||||||
'@smithy/abort-controller@4.2.8':
|
|
||||||
resolution: {integrity: sha512-peuVfkYHAmS5ybKxWcfraK7WBBP0J+rkfUcbHJJKQ4ir3UAUNQI+Y4Vt/PqSzGqgloJ5O1dk7+WzNL8wcCSXbw==}
|
|
||||||
engines: {node: '>=18.0.0'}
|
|
||||||
|
|
||||||
'@smithy/chunked-blob-reader-native@4.0.0':
|
'@smithy/chunked-blob-reader-native@4.0.0':
|
||||||
resolution: {integrity: sha512-R9wM2yPmfEMsUmlMlIgSzOyICs0x9uu7UTHoccMyt7BWw8shcGM8HqB355+BZCPBcySvbTYMs62EgEQkNxz2ig==}
|
resolution: {integrity: sha512-R9wM2yPmfEMsUmlMlIgSzOyICs0x9uu7UTHoccMyt7BWw8shcGM8HqB355+BZCPBcySvbTYMs62EgEQkNxz2ig==}
|
||||||
engines: {node: '>=18.0.0'}
|
engines: {node: '>=18.0.0'}
|
||||||
@@ -3331,10 +3315,6 @@ packages:
|
|||||||
resolution: {integrity: sha512-viuHMxBAqydkB0AfWwHIdwf/PRH2z5KHGUzqyRtS/Wv+n3IHI993Sk76VCA7dD/+GzgGOmlJDITfPcJC1nIVIw==}
|
resolution: {integrity: sha512-viuHMxBAqydkB0AfWwHIdwf/PRH2z5KHGUzqyRtS/Wv+n3IHI993Sk76VCA7dD/+GzgGOmlJDITfPcJC1nIVIw==}
|
||||||
engines: {node: '>=18.0.0'}
|
engines: {node: '>=18.0.0'}
|
||||||
|
|
||||||
'@smithy/core@3.22.1':
|
|
||||||
resolution: {integrity: sha512-x3ie6Crr58MWrm4viHqqy2Du2rHYZjwu8BekasrQx4ca+Y24dzVAwq3yErdqIbc2G3I0kLQA13PQ+/rde+u65g==}
|
|
||||||
engines: {node: '>=18.0.0'}
|
|
||||||
|
|
||||||
'@smithy/core@3.9.0':
|
'@smithy/core@3.9.0':
|
||||||
resolution: {integrity: sha512-B/GknvCfS3llXd/b++hcrwIuqnEozQDnRL4sBmOac5/z/dr0/yG1PURNPOyU4Lsiy1IyTj8scPxVqRs5dYWf6A==}
|
resolution: {integrity: sha512-B/GknvCfS3llXd/b++hcrwIuqnEozQDnRL4sBmOac5/z/dr0/yG1PURNPOyU4Lsiy1IyTj8scPxVqRs5dYWf6A==}
|
||||||
engines: {node: '>=18.0.0'}
|
engines: {node: '>=18.0.0'}
|
||||||
@@ -3367,10 +3347,6 @@ packages:
|
|||||||
resolution: {integrity: sha512-61WjM0PWmZJR+SnmzaKI7t7G0UkkNFboDpzIdzSoy7TByUzlxo18Qlh9s71qug4AY4hlH/CwXdubMtkcNEb/sQ==}
|
resolution: {integrity: sha512-61WjM0PWmZJR+SnmzaKI7t7G0UkkNFboDpzIdzSoy7TByUzlxo18Qlh9s71qug4AY4hlH/CwXdubMtkcNEb/sQ==}
|
||||||
engines: {node: '>=18.0.0'}
|
engines: {node: '>=18.0.0'}
|
||||||
|
|
||||||
'@smithy/fetch-http-handler@5.3.9':
|
|
||||||
resolution: {integrity: sha512-I4UhmcTYXBrct03rwzQX1Y/iqQlzVQaPxWjCjula++5EmWq9YGBrx6bbGqluGc1f0XEfhSkiY4jhLgbsJUMKRA==}
|
|
||||||
engines: {node: '>=18.0.0'}
|
|
||||||
|
|
||||||
'@smithy/hash-blob-browser@4.0.5':
|
'@smithy/hash-blob-browser@4.0.5':
|
||||||
resolution: {integrity: sha512-F7MmCd3FH/Q2edhcKd+qulWkwfChHbc9nhguBlVjSUE6hVHhec3q6uPQ+0u69S6ppvLtR3eStfCuEKMXBXhvvA==}
|
resolution: {integrity: sha512-F7MmCd3FH/Q2edhcKd+qulWkwfChHbc9nhguBlVjSUE6hVHhec3q6uPQ+0u69S6ppvLtR3eStfCuEKMXBXhvvA==}
|
||||||
engines: {node: '>=18.0.0'}
|
engines: {node: '>=18.0.0'}
|
||||||
@@ -3395,10 +3371,6 @@ packages:
|
|||||||
resolution: {integrity: sha512-saYhF8ZZNoJDTvJBEWgeBccCg+yvp1CX+ed12yORU3NilJScfc6gfch2oVb4QgxZrGUx3/ZJlb+c/dJbyupxlw==}
|
resolution: {integrity: sha512-saYhF8ZZNoJDTvJBEWgeBccCg+yvp1CX+ed12yORU3NilJScfc6gfch2oVb4QgxZrGUx3/ZJlb+c/dJbyupxlw==}
|
||||||
engines: {node: '>=18.0.0'}
|
engines: {node: '>=18.0.0'}
|
||||||
|
|
||||||
'@smithy/is-array-buffer@4.2.0':
|
|
||||||
resolution: {integrity: sha512-DZZZBvC7sjcYh4MazJSGiWMI2L7E0oCiRHREDzIxi/M2LY79/21iXt6aPLHge82wi5LsuRF5A06Ds3+0mlh6CQ==}
|
|
||||||
engines: {node: '>=18.0.0'}
|
|
||||||
|
|
||||||
'@smithy/md5-js@4.0.5':
|
'@smithy/md5-js@4.0.5':
|
||||||
resolution: {integrity: sha512-8n2XCwdUbGr8W/XhMTaxILkVlw2QebkVTn5tm3HOcbPbOpWg89zr6dPXsH8xbeTsbTXlJvlJNTQsKAIoqQGbdA==}
|
resolution: {integrity: sha512-8n2XCwdUbGr8W/XhMTaxILkVlw2QebkVTn5tm3HOcbPbOpWg89zr6dPXsH8xbeTsbTXlJvlJNTQsKAIoqQGbdA==}
|
||||||
engines: {node: '>=18.0.0'}
|
engines: {node: '>=18.0.0'}
|
||||||
@@ -3411,10 +3383,6 @@ packages:
|
|||||||
resolution: {integrity: sha512-EAlEPncqo03siNZJ9Tm6adKCQ+sw5fNU8ncxWwaH0zTCwMPsgmERTi6CEKaermZdgJb+4Yvh0NFm36HeO4PGgQ==}
|
resolution: {integrity: sha512-EAlEPncqo03siNZJ9Tm6adKCQ+sw5fNU8ncxWwaH0zTCwMPsgmERTi6CEKaermZdgJb+4Yvh0NFm36HeO4PGgQ==}
|
||||||
engines: {node: '>=18.0.0'}
|
engines: {node: '>=18.0.0'}
|
||||||
|
|
||||||
'@smithy/middleware-endpoint@4.4.13':
|
|
||||||
resolution: {integrity: sha512-x6vn0PjYmGdNuKh/juUJJewZh7MoQ46jYaJ2mvekF4EesMuFfrl4LaW/k97Zjf8PTCPQmPgMvwewg7eNoH9n5w==}
|
|
||||||
engines: {node: '>=18.0.0'}
|
|
||||||
|
|
||||||
'@smithy/middleware-retry@4.1.20':
|
'@smithy/middleware-retry@4.1.20':
|
||||||
resolution: {integrity: sha512-T3maNEm3Masae99eFdx1Q7PIqBBEVOvRd5hralqKZNeIivnoGNx5OFtI3DiZ5gCjUkl0mNondlzSXeVxkinh7Q==}
|
resolution: {integrity: sha512-T3maNEm3Masae99eFdx1Q7PIqBBEVOvRd5hralqKZNeIivnoGNx5OFtI3DiZ5gCjUkl0mNondlzSXeVxkinh7Q==}
|
||||||
engines: {node: '>=18.0.0'}
|
engines: {node: '>=18.0.0'}
|
||||||
@@ -3423,66 +3391,34 @@ packages:
|
|||||||
resolution: {integrity: sha512-uAFFR4dpeoJPGz8x9mhxp+RPjo5wW0QEEIPPPbLXiRRWeCATf/Km3gKIVR5vaP8bN1kgsPhcEeh+IZvUlBv6Xg==}
|
resolution: {integrity: sha512-uAFFR4dpeoJPGz8x9mhxp+RPjo5wW0QEEIPPPbLXiRRWeCATf/Km3gKIVR5vaP8bN1kgsPhcEeh+IZvUlBv6Xg==}
|
||||||
engines: {node: '>=18.0.0'}
|
engines: {node: '>=18.0.0'}
|
||||||
|
|
||||||
'@smithy/middleware-serde@4.2.9':
|
|
||||||
resolution: {integrity: sha512-eMNiej0u/snzDvlqRGSN3Vl0ESn3838+nKyVfF2FKNXFbi4SERYT6PR392D39iczngbqqGG0Jl1DlCnp7tBbXQ==}
|
|
||||||
engines: {node: '>=18.0.0'}
|
|
||||||
|
|
||||||
'@smithy/middleware-stack@4.0.5':
|
'@smithy/middleware-stack@4.0.5':
|
||||||
resolution: {integrity: sha512-/yoHDXZPh3ocRVyeWQFvC44u8seu3eYzZRveCMfgMOBcNKnAmOvjbL9+Cp5XKSIi9iYA9PECUuW2teDAk8T+OQ==}
|
resolution: {integrity: sha512-/yoHDXZPh3ocRVyeWQFvC44u8seu3eYzZRveCMfgMOBcNKnAmOvjbL9+Cp5XKSIi9iYA9PECUuW2teDAk8T+OQ==}
|
||||||
engines: {node: '>=18.0.0'}
|
engines: {node: '>=18.0.0'}
|
||||||
|
|
||||||
'@smithy/middleware-stack@4.2.8':
|
|
||||||
resolution: {integrity: sha512-w6LCfOviTYQjBctOKSwy6A8FIkQy7ICvglrZFl6Bw4FmcQ1Z420fUtIhxaUZZshRe0VCq4kvDiPiXrPZAe8oRA==}
|
|
||||||
engines: {node: '>=18.0.0'}
|
|
||||||
|
|
||||||
'@smithy/node-config-provider@4.1.4':
|
'@smithy/node-config-provider@4.1.4':
|
||||||
resolution: {integrity: sha512-+UDQV/k42jLEPPHSn39l0Bmc4sB1xtdI9Gd47fzo/0PbXzJ7ylgaOByVjF5EeQIumkepnrJyfx86dPa9p47Y+w==}
|
resolution: {integrity: sha512-+UDQV/k42jLEPPHSn39l0Bmc4sB1xtdI9Gd47fzo/0PbXzJ7ylgaOByVjF5EeQIumkepnrJyfx86dPa9p47Y+w==}
|
||||||
engines: {node: '>=18.0.0'}
|
engines: {node: '>=18.0.0'}
|
||||||
|
|
||||||
'@smithy/node-config-provider@4.3.8':
|
|
||||||
resolution: {integrity: sha512-aFP1ai4lrbVlWjfpAfRSL8KFcnJQYfTl5QxLJXY32vghJrDuFyPZ6LtUL+JEGYiFRG1PfPLHLoxj107ulncLIg==}
|
|
||||||
engines: {node: '>=18.0.0'}
|
|
||||||
|
|
||||||
'@smithy/node-http-handler@4.1.1':
|
'@smithy/node-http-handler@4.1.1':
|
||||||
resolution: {integrity: sha512-RHnlHqFpoVdjSPPiYy/t40Zovf3BBHc2oemgD7VsVTFFZrU5erFFe0n52OANZZ/5sbshgD93sOh5r6I35Xmpaw==}
|
resolution: {integrity: sha512-RHnlHqFpoVdjSPPiYy/t40Zovf3BBHc2oemgD7VsVTFFZrU5erFFe0n52OANZZ/5sbshgD93sOh5r6I35Xmpaw==}
|
||||||
engines: {node: '>=18.0.0'}
|
engines: {node: '>=18.0.0'}
|
||||||
|
|
||||||
'@smithy/node-http-handler@4.4.9':
|
|
||||||
resolution: {integrity: sha512-KX5Wml5mF+luxm1szW4QDz32e3NObgJ4Fyw+irhph4I/2geXwUy4jkIMUs5ZPGflRBeR6BUkC2wqIab4Llgm3w==}
|
|
||||||
engines: {node: '>=18.0.0'}
|
|
||||||
|
|
||||||
'@smithy/property-provider@4.0.5':
|
'@smithy/property-provider@4.0.5':
|
||||||
resolution: {integrity: sha512-R/bswf59T/n9ZgfgUICAZoWYKBHcsVDurAGX88zsiUtOTA/xUAPyiT+qkNCPwFn43pZqN84M4MiUsbSGQmgFIQ==}
|
resolution: {integrity: sha512-R/bswf59T/n9ZgfgUICAZoWYKBHcsVDurAGX88zsiUtOTA/xUAPyiT+qkNCPwFn43pZqN84M4MiUsbSGQmgFIQ==}
|
||||||
engines: {node: '>=18.0.0'}
|
engines: {node: '>=18.0.0'}
|
||||||
|
|
||||||
'@smithy/property-provider@4.2.8':
|
|
||||||
resolution: {integrity: sha512-EtCTbyIveCKeOXDSWSdze3k612yCPq1YbXsbqX3UHhkOSW8zKsM9NOJG5gTIya0vbY2DIaieG8pKo1rITHYL0w==}
|
|
||||||
engines: {node: '>=18.0.0'}
|
|
||||||
|
|
||||||
'@smithy/protocol-http@5.1.3':
|
'@smithy/protocol-http@5.1.3':
|
||||||
resolution: {integrity: sha512-fCJd2ZR7D22XhDY0l+92pUag/7je2BztPRQ01gU5bMChcyI0rlly7QFibnYHzcxDvccMjlpM/Q1ev8ceRIb48w==}
|
resolution: {integrity: sha512-fCJd2ZR7D22XhDY0l+92pUag/7je2BztPRQ01gU5bMChcyI0rlly7QFibnYHzcxDvccMjlpM/Q1ev8ceRIb48w==}
|
||||||
engines: {node: '>=18.0.0'}
|
engines: {node: '>=18.0.0'}
|
||||||
|
|
||||||
'@smithy/protocol-http@5.3.8':
|
|
||||||
resolution: {integrity: sha512-QNINVDhxpZ5QnP3aviNHQFlRogQZDfYlCkQT+7tJnErPQbDhysondEjhikuANxgMsZrkGeiAxXy4jguEGsDrWQ==}
|
|
||||||
engines: {node: '>=18.0.0'}
|
|
||||||
|
|
||||||
'@smithy/querystring-builder@4.0.5':
|
'@smithy/querystring-builder@4.0.5':
|
||||||
resolution: {integrity: sha512-NJeSCU57piZ56c+/wY+AbAw6rxCCAOZLCIniRE7wqvndqxcKKDOXzwWjrY7wGKEISfhL9gBbAaWWgHsUGedk+A==}
|
resolution: {integrity: sha512-NJeSCU57piZ56c+/wY+AbAw6rxCCAOZLCIniRE7wqvndqxcKKDOXzwWjrY7wGKEISfhL9gBbAaWWgHsUGedk+A==}
|
||||||
engines: {node: '>=18.0.0'}
|
engines: {node: '>=18.0.0'}
|
||||||
|
|
||||||
'@smithy/querystring-builder@4.2.8':
|
|
||||||
resolution: {integrity: sha512-Xr83r31+DrE8CP3MqPgMJl+pQlLLmOfiEUnoyAlGzzJIrEsbKsPy1hqH0qySaQm4oWrCBlUqRt+idEgunKB+iw==}
|
|
||||||
engines: {node: '>=18.0.0'}
|
|
||||||
|
|
||||||
'@smithy/querystring-parser@4.0.5':
|
'@smithy/querystring-parser@4.0.5':
|
||||||
resolution: {integrity: sha512-6SV7md2CzNG/WUeTjVe6Dj8noH32r4MnUeFKZrnVYsQxpGSIcphAanQMayi8jJLZAWm6pdM9ZXvKCpWOsIGg0w==}
|
resolution: {integrity: sha512-6SV7md2CzNG/WUeTjVe6Dj8noH32r4MnUeFKZrnVYsQxpGSIcphAanQMayi8jJLZAWm6pdM9ZXvKCpWOsIGg0w==}
|
||||||
engines: {node: '>=18.0.0'}
|
engines: {node: '>=18.0.0'}
|
||||||
|
|
||||||
'@smithy/querystring-parser@4.2.8':
|
|
||||||
resolution: {integrity: sha512-vUurovluVy50CUlazOiXkPq40KGvGWSdmusa3130MwrR1UNnNgKAlj58wlOe61XSHRpUfIIh6cE0zZ8mzKaDPA==}
|
|
||||||
engines: {node: '>=18.0.0'}
|
|
||||||
|
|
||||||
'@smithy/service-error-classification@4.0.7':
|
'@smithy/service-error-classification@4.0.7':
|
||||||
resolution: {integrity: sha512-XvRHOipqpwNhEjDf2L5gJowZEm5nsxC16pAZOeEcsygdjv9A2jdOh3YoDQvOXBGTsaJk6mNWtzWalOB9976Wlg==}
|
resolution: {integrity: sha512-XvRHOipqpwNhEjDf2L5gJowZEm5nsxC16pAZOeEcsygdjv9A2jdOh3YoDQvOXBGTsaJk6mNWtzWalOB9976Wlg==}
|
||||||
engines: {node: '>=18.0.0'}
|
engines: {node: '>=18.0.0'}
|
||||||
@@ -3491,26 +3427,14 @@ packages:
|
|||||||
resolution: {integrity: sha512-YVVwehRDuehgoXdEL4r1tAAzdaDgaC9EQvhK0lEbfnbrd0bd5+CTQumbdPryX3J2shT7ZqQE+jPW4lmNBAB8JQ==}
|
resolution: {integrity: sha512-YVVwehRDuehgoXdEL4r1tAAzdaDgaC9EQvhK0lEbfnbrd0bd5+CTQumbdPryX3J2shT7ZqQE+jPW4lmNBAB8JQ==}
|
||||||
engines: {node: '>=18.0.0'}
|
engines: {node: '>=18.0.0'}
|
||||||
|
|
||||||
'@smithy/shared-ini-file-loader@4.4.3':
|
|
||||||
resolution: {integrity: sha512-DfQjxXQnzC5UbCUPeC3Ie8u+rIWZTvuDPAGU/BxzrOGhRvgUanaP68kDZA+jaT3ZI+djOf+4dERGlm9mWfFDrg==}
|
|
||||||
engines: {node: '>=18.0.0'}
|
|
||||||
|
|
||||||
'@smithy/signature-v4@5.1.3':
|
'@smithy/signature-v4@5.1.3':
|
||||||
resolution: {integrity: sha512-mARDSXSEgllNzMw6N+mC+r1AQlEBO3meEAkR/UlfAgnMzJUB3goRBWgip1EAMG99wh36MDqzo86SfIX5Y+VEaw==}
|
resolution: {integrity: sha512-mARDSXSEgllNzMw6N+mC+r1AQlEBO3meEAkR/UlfAgnMzJUB3goRBWgip1EAMG99wh36MDqzo86SfIX5Y+VEaw==}
|
||||||
engines: {node: '>=18.0.0'}
|
engines: {node: '>=18.0.0'}
|
||||||
|
|
||||||
'@smithy/smithy-client@4.11.2':
|
|
||||||
resolution: {integrity: sha512-SCkGmFak/xC1n7hKRsUr6wOnBTJ3L22Qd4e8H1fQIuKTAjntwgU8lrdMe7uHdiT2mJAOWA/60qaW9tiMu69n1A==}
|
|
||||||
engines: {node: '>=18.0.0'}
|
|
||||||
|
|
||||||
'@smithy/smithy-client@4.5.0':
|
'@smithy/smithy-client@4.5.0':
|
||||||
resolution: {integrity: sha512-ZSdE3vl0MuVbEwJBxSftm0J5nL/gw76xp5WF13zW9cN18MFuFXD5/LV0QD8P+sCU5bSWGyy6CTgUupE1HhOo1A==}
|
resolution: {integrity: sha512-ZSdE3vl0MuVbEwJBxSftm0J5nL/gw76xp5WF13zW9cN18MFuFXD5/LV0QD8P+sCU5bSWGyy6CTgUupE1HhOo1A==}
|
||||||
engines: {node: '>=18.0.0'}
|
engines: {node: '>=18.0.0'}
|
||||||
|
|
||||||
'@smithy/types@4.12.0':
|
|
||||||
resolution: {integrity: sha512-9YcuJVTOBDjg9LWo23Qp0lTQ3D7fQsQtwle0jVfpbUHy9qBwCEgKuVH4FqFB3VYu0nwdHKiEMA+oXz7oV8X1kw==}
|
|
||||||
engines: {node: '>=18.0.0'}
|
|
||||||
|
|
||||||
'@smithy/types@4.3.2':
|
'@smithy/types@4.3.2':
|
||||||
resolution: {integrity: sha512-QO4zghLxiQ5W9UZmX2Lo0nta2PuE1sSrXUYDoaB6HMR762C0P7v/HEPHf6ZdglTVssJG1bsrSBxdc3quvDSihw==}
|
resolution: {integrity: sha512-QO4zghLxiQ5W9UZmX2Lo0nta2PuE1sSrXUYDoaB6HMR762C0P7v/HEPHf6ZdglTVssJG1bsrSBxdc3quvDSihw==}
|
||||||
engines: {node: '>=18.0.0'}
|
engines: {node: '>=18.0.0'}
|
||||||
@@ -3519,26 +3443,14 @@ packages:
|
|||||||
resolution: {integrity: sha512-j+733Um7f1/DXjYhCbvNXABV53NyCRRA54C7bNEIxNPs0YjfRxeMKjjgm2jvTYrciZyCjsicHwQ6Q0ylo+NAUw==}
|
resolution: {integrity: sha512-j+733Um7f1/DXjYhCbvNXABV53NyCRRA54C7bNEIxNPs0YjfRxeMKjjgm2jvTYrciZyCjsicHwQ6Q0ylo+NAUw==}
|
||||||
engines: {node: '>=18.0.0'}
|
engines: {node: '>=18.0.0'}
|
||||||
|
|
||||||
'@smithy/url-parser@4.2.8':
|
|
||||||
resolution: {integrity: sha512-NQho9U68TGMEU639YkXnVMV3GEFFULmmaWdlu1E9qzyIePOHsoSnagTGSDv1Zi8DCNN6btxOSdgmy5E/hsZwhA==}
|
|
||||||
engines: {node: '>=18.0.0'}
|
|
||||||
|
|
||||||
'@smithy/util-base64@4.0.0':
|
'@smithy/util-base64@4.0.0':
|
||||||
resolution: {integrity: sha512-CvHfCmO2mchox9kjrtzoHkWHxjHZzaFojLc8quxXY7WAAMAg43nuxwv95tATVgQFNDwd4M9S1qFzj40Ul41Kmg==}
|
resolution: {integrity: sha512-CvHfCmO2mchox9kjrtzoHkWHxjHZzaFojLc8quxXY7WAAMAg43nuxwv95tATVgQFNDwd4M9S1qFzj40Ul41Kmg==}
|
||||||
engines: {node: '>=18.0.0'}
|
engines: {node: '>=18.0.0'}
|
||||||
|
|
||||||
'@smithy/util-base64@4.3.0':
|
|
||||||
resolution: {integrity: sha512-GkXZ59JfyxsIwNTWFnjmFEI8kZpRNIBfxKjv09+nkAWPt/4aGaEWMM04m4sxgNVWkbt2MdSvE3KF/PfX4nFedQ==}
|
|
||||||
engines: {node: '>=18.0.0'}
|
|
||||||
|
|
||||||
'@smithy/util-body-length-browser@4.0.0':
|
'@smithy/util-body-length-browser@4.0.0':
|
||||||
resolution: {integrity: sha512-sNi3DL0/k64/LO3A256M+m3CDdG6V7WKWHdAiBBMUN8S3hK3aMPhwnPik2A/a2ONN+9doY9UxaLfgqsIRg69QA==}
|
resolution: {integrity: sha512-sNi3DL0/k64/LO3A256M+m3CDdG6V7WKWHdAiBBMUN8S3hK3aMPhwnPik2A/a2ONN+9doY9UxaLfgqsIRg69QA==}
|
||||||
engines: {node: '>=18.0.0'}
|
engines: {node: '>=18.0.0'}
|
||||||
|
|
||||||
'@smithy/util-body-length-browser@4.2.0':
|
|
||||||
resolution: {integrity: sha512-Fkoh/I76szMKJnBXWPdFkQJl2r9SjPt3cMzLdOB6eJ4Pnpas8hVoWPYemX/peO0yrrvldgCUVJqOAjUrOLjbxg==}
|
|
||||||
engines: {node: '>=18.0.0'}
|
|
||||||
|
|
||||||
'@smithy/util-body-length-node@4.0.0':
|
'@smithy/util-body-length-node@4.0.0':
|
||||||
resolution: {integrity: sha512-q0iDP3VsZzqJyje8xJWEJCNIu3lktUGVoSy1KB0UWym2CL1siV3artm+u1DFYTLejpsrdGyCSWBdGNjJzfDPjg==}
|
resolution: {integrity: sha512-q0iDP3VsZzqJyje8xJWEJCNIu3lktUGVoSy1KB0UWym2CL1siV3artm+u1DFYTLejpsrdGyCSWBdGNjJzfDPjg==}
|
||||||
engines: {node: '>=18.0.0'}
|
engines: {node: '>=18.0.0'}
|
||||||
@@ -3551,10 +3463,6 @@ packages:
|
|||||||
resolution: {integrity: sha512-9TOQ7781sZvddgO8nxueKi3+yGvkY35kotA0Y6BWRajAv8jjmigQ1sBwz0UX47pQMYXJPahSKEKYFgt+rXdcug==}
|
resolution: {integrity: sha512-9TOQ7781sZvddgO8nxueKi3+yGvkY35kotA0Y6BWRajAv8jjmigQ1sBwz0UX47pQMYXJPahSKEKYFgt+rXdcug==}
|
||||||
engines: {node: '>=18.0.0'}
|
engines: {node: '>=18.0.0'}
|
||||||
|
|
||||||
'@smithy/util-buffer-from@4.2.0':
|
|
||||||
resolution: {integrity: sha512-kAY9hTKulTNevM2nlRtxAG2FQ3B2OR6QIrPY3zE5LqJy1oxzmgBGsHLWTcNhWXKchgA0WHW+mZkQrng/pgcCew==}
|
|
||||||
engines: {node: '>=18.0.0'}
|
|
||||||
|
|
||||||
'@smithy/util-config-provider@4.0.0':
|
'@smithy/util-config-provider@4.0.0':
|
||||||
resolution: {integrity: sha512-L1RBVzLyfE8OXH+1hsJ8p+acNUSirQnWQ6/EgpchV88G6zGBTDPdXiiExei6Z1wR2RxYvxY/XLw6AMNCCt8H3w==}
|
resolution: {integrity: sha512-L1RBVzLyfE8OXH+1hsJ8p+acNUSirQnWQ6/EgpchV88G6zGBTDPdXiiExei6Z1wR2RxYvxY/XLw6AMNCCt8H3w==}
|
||||||
engines: {node: '>=18.0.0'}
|
engines: {node: '>=18.0.0'}
|
||||||
@@ -3575,18 +3483,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-Yk5mLhHtfIgW2W2WQZWSg5kuMZCVbvhFmC7rV4IO2QqnZdbEFPmQnCcGMAX2z/8Qj3B9hYYNjZOhWym+RwhePw==}
|
resolution: {integrity: sha512-Yk5mLhHtfIgW2W2WQZWSg5kuMZCVbvhFmC7rV4IO2QqnZdbEFPmQnCcGMAX2z/8Qj3B9hYYNjZOhWym+RwhePw==}
|
||||||
engines: {node: '>=18.0.0'}
|
engines: {node: '>=18.0.0'}
|
||||||
|
|
||||||
'@smithy/util-hex-encoding@4.2.0':
|
|
||||||
resolution: {integrity: sha512-CCQBwJIvXMLKxVbO88IukazJD9a4kQ9ZN7/UMGBjBcJYvatpWk+9g870El4cB8/EJxfe+k+y0GmR9CAzkF+Nbw==}
|
|
||||||
engines: {node: '>=18.0.0'}
|
|
||||||
|
|
||||||
'@smithy/util-middleware@4.0.5':
|
'@smithy/util-middleware@4.0.5':
|
||||||
resolution: {integrity: sha512-N40PfqsZHRSsByGB81HhSo+uvMxEHT+9e255S53pfBw/wI6WKDI7Jw9oyu5tJTLwZzV5DsMha3ji8jk9dsHmQQ==}
|
resolution: {integrity: sha512-N40PfqsZHRSsByGB81HhSo+uvMxEHT+9e255S53pfBw/wI6WKDI7Jw9oyu5tJTLwZzV5DsMha3ji8jk9dsHmQQ==}
|
||||||
engines: {node: '>=18.0.0'}
|
engines: {node: '>=18.0.0'}
|
||||||
|
|
||||||
'@smithy/util-middleware@4.2.8':
|
|
||||||
resolution: {integrity: sha512-PMqfeJxLcNPMDgvPbbLl/2Vpin+luxqTGPpW3NAQVLbRrFRzTa4rNAASYeIGjRV9Ytuhzny39SpyU04EQreF+A==}
|
|
||||||
engines: {node: '>=18.0.0'}
|
|
||||||
|
|
||||||
'@smithy/util-retry@4.0.7':
|
'@smithy/util-retry@4.0.7':
|
||||||
resolution: {integrity: sha512-TTO6rt0ppK70alZpkjwy+3nQlTiqNfoXja+qwuAchIEAIoSZW8Qyd76dvBv3I5bCpE38APafG23Y/u270NspiQ==}
|
resolution: {integrity: sha512-TTO6rt0ppK70alZpkjwy+3nQlTiqNfoXja+qwuAchIEAIoSZW8Qyd76dvBv3I5bCpE38APafG23Y/u270NspiQ==}
|
||||||
engines: {node: '>=18.0.0'}
|
engines: {node: '>=18.0.0'}
|
||||||
@@ -3595,18 +3495,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-vSKnvNZX2BXzl0U2RgCLOwWaAP9x/ddd/XobPK02pCbzRm5s55M53uwb1rl/Ts7RXZvdJZerPkA+en2FDghLuQ==}
|
resolution: {integrity: sha512-vSKnvNZX2BXzl0U2RgCLOwWaAP9x/ddd/XobPK02pCbzRm5s55M53uwb1rl/Ts7RXZvdJZerPkA+en2FDghLuQ==}
|
||||||
engines: {node: '>=18.0.0'}
|
engines: {node: '>=18.0.0'}
|
||||||
|
|
||||||
'@smithy/util-stream@4.5.11':
|
|
||||||
resolution: {integrity: sha512-lKmZ0S/3Qj2OF5H1+VzvDLb6kRxGzZHq6f3rAsoSu5cTLGsn3v3VQBA8czkNNXlLjoFEtVu3OQT2jEeOtOE2CA==}
|
|
||||||
engines: {node: '>=18.0.0'}
|
|
||||||
|
|
||||||
'@smithy/util-uri-escape@4.0.0':
|
'@smithy/util-uri-escape@4.0.0':
|
||||||
resolution: {integrity: sha512-77yfbCbQMtgtTylO9itEAdpPXSog3ZxMe09AEhm0dU0NLTalV70ghDZFR+Nfi1C60jnJoh/Re4090/DuZh2Omg==}
|
resolution: {integrity: sha512-77yfbCbQMtgtTylO9itEAdpPXSog3ZxMe09AEhm0dU0NLTalV70ghDZFR+Nfi1C60jnJoh/Re4090/DuZh2Omg==}
|
||||||
engines: {node: '>=18.0.0'}
|
engines: {node: '>=18.0.0'}
|
||||||
|
|
||||||
'@smithy/util-uri-escape@4.2.0':
|
|
||||||
resolution: {integrity: sha512-igZpCKV9+E/Mzrpq6YacdTQ0qTiLm85gD6N/IrmyDvQFA4UnU3d5g3m8tMT/6zG/vVkWSU+VxeUyGonL62DuxA==}
|
|
||||||
engines: {node: '>=18.0.0'}
|
|
||||||
|
|
||||||
'@smithy/util-utf8@2.3.0':
|
'@smithy/util-utf8@2.3.0':
|
||||||
resolution: {integrity: sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==}
|
resolution: {integrity: sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==}
|
||||||
engines: {node: '>=14.0.0'}
|
engines: {node: '>=14.0.0'}
|
||||||
@@ -3615,18 +3507,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-b+zebfKCfRdgNJDknHCob3O7FpeYQN6ZG6YLExMcasDHsCXlsXCEuiPZeLnJLpwa5dvPetGlnGCiMHuLwGvFow==}
|
resolution: {integrity: sha512-b+zebfKCfRdgNJDknHCob3O7FpeYQN6ZG6YLExMcasDHsCXlsXCEuiPZeLnJLpwa5dvPetGlnGCiMHuLwGvFow==}
|
||||||
engines: {node: '>=18.0.0'}
|
engines: {node: '>=18.0.0'}
|
||||||
|
|
||||||
'@smithy/util-utf8@4.2.0':
|
|
||||||
resolution: {integrity: sha512-zBPfuzoI8xyBtR2P6WQj63Rz8i3AmfAaJLuNG8dWsfvPe8lO4aCPYLn879mEgHndZH1zQ2oXmG8O1GGzzaoZiw==}
|
|
||||||
engines: {node: '>=18.0.0'}
|
|
||||||
|
|
||||||
'@smithy/util-waiter@4.0.7':
|
'@smithy/util-waiter@4.0.7':
|
||||||
resolution: {integrity: sha512-mYqtQXPmrwvUljaHyGxYUIIRI3qjBTEb/f5QFi3A6VlxhpmZd5mWXn9W+qUkf2pVE1Hv3SqxefiZOPGdxmO64A==}
|
resolution: {integrity: sha512-mYqtQXPmrwvUljaHyGxYUIIRI3qjBTEb/f5QFi3A6VlxhpmZd5mWXn9W+qUkf2pVE1Hv3SqxefiZOPGdxmO64A==}
|
||||||
engines: {node: '>=18.0.0'}
|
engines: {node: '>=18.0.0'}
|
||||||
|
|
||||||
'@smithy/uuid@1.1.0':
|
|
||||||
resolution: {integrity: sha512-4aUIteuyxtBUhVdiQqcDhKFitwfd9hqoSDYY2KRXiWtgoWJ9Bmise+KfEPDiVHWeJepvF8xJO9/9+WDIciMFFw==}
|
|
||||||
engines: {node: '>=18.0.0'}
|
|
||||||
|
|
||||||
'@socket.io/component-emitter@3.1.2':
|
'@socket.io/component-emitter@3.1.2':
|
||||||
resolution: {integrity: sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==}
|
resolution: {integrity: sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==}
|
||||||
|
|
||||||
@@ -4602,9 +4486,6 @@ packages:
|
|||||||
buffer-from@1.1.2:
|
buffer-from@1.1.2:
|
||||||
resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==}
|
resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==}
|
||||||
|
|
||||||
buffer@5.6.0:
|
|
||||||
resolution: {integrity: sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==}
|
|
||||||
|
|
||||||
buffer@5.7.1:
|
buffer@5.7.1:
|
||||||
resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==}
|
resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==}
|
||||||
|
|
||||||
@@ -7879,9 +7760,6 @@ packages:
|
|||||||
resolution: {integrity: sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==}
|
resolution: {integrity: sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
|
|
||||||
stream-browserify@3.0.0:
|
|
||||||
resolution: {integrity: sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==}
|
|
||||||
|
|
||||||
string-width@4.2.3:
|
string-width@4.2.3:
|
||||||
resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==}
|
resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
@@ -9024,17 +8902,6 @@ snapshots:
|
|||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- aws-crt
|
- aws-crt
|
||||||
|
|
||||||
'@aws-sdk/lib-storage@3.985.0(@aws-sdk/client-s3@3.879.0)':
|
|
||||||
dependencies:
|
|
||||||
'@aws-sdk/client-s3': 3.879.0
|
|
||||||
'@smithy/abort-controller': 4.2.8
|
|
||||||
'@smithy/middleware-endpoint': 4.4.13
|
|
||||||
'@smithy/smithy-client': 4.11.2
|
|
||||||
buffer: 5.6.0
|
|
||||||
events: 3.3.0
|
|
||||||
stream-browserify: 3.0.0
|
|
||||||
tslib: 2.8.1
|
|
||||||
|
|
||||||
'@aws-sdk/middleware-bucket-endpoint@3.873.0':
|
'@aws-sdk/middleware-bucket-endpoint@3.873.0':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@aws-sdk/types': 3.862.0
|
'@aws-sdk/types': 3.862.0
|
||||||
@@ -11469,11 +11336,6 @@ snapshots:
|
|||||||
'@smithy/types': 4.3.2
|
'@smithy/types': 4.3.2
|
||||||
tslib: 2.8.1
|
tslib: 2.8.1
|
||||||
|
|
||||||
'@smithy/abort-controller@4.2.8':
|
|
||||||
dependencies:
|
|
||||||
'@smithy/types': 4.12.0
|
|
||||||
tslib: 2.8.1
|
|
||||||
|
|
||||||
'@smithy/chunked-blob-reader-native@4.0.0':
|
'@smithy/chunked-blob-reader-native@4.0.0':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@smithy/util-base64': 4.0.0
|
'@smithy/util-base64': 4.0.0
|
||||||
@@ -11491,19 +11353,6 @@ snapshots:
|
|||||||
'@smithy/util-middleware': 4.0.5
|
'@smithy/util-middleware': 4.0.5
|
||||||
tslib: 2.8.1
|
tslib: 2.8.1
|
||||||
|
|
||||||
'@smithy/core@3.22.1':
|
|
||||||
dependencies:
|
|
||||||
'@smithy/middleware-serde': 4.2.9
|
|
||||||
'@smithy/protocol-http': 5.3.8
|
|
||||||
'@smithy/types': 4.12.0
|
|
||||||
'@smithy/util-base64': 4.3.0
|
|
||||||
'@smithy/util-body-length-browser': 4.2.0
|
|
||||||
'@smithy/util-middleware': 4.2.8
|
|
||||||
'@smithy/util-stream': 4.5.11
|
|
||||||
'@smithy/util-utf8': 4.2.0
|
|
||||||
'@smithy/uuid': 1.1.0
|
|
||||||
tslib: 2.8.1
|
|
||||||
|
|
||||||
'@smithy/core@3.9.0':
|
'@smithy/core@3.9.0':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@smithy/middleware-serde': 4.0.9
|
'@smithy/middleware-serde': 4.0.9
|
||||||
@@ -11564,14 +11413,6 @@ snapshots:
|
|||||||
'@smithy/util-base64': 4.0.0
|
'@smithy/util-base64': 4.0.0
|
||||||
tslib: 2.8.1
|
tslib: 2.8.1
|
||||||
|
|
||||||
'@smithy/fetch-http-handler@5.3.9':
|
|
||||||
dependencies:
|
|
||||||
'@smithy/protocol-http': 5.3.8
|
|
||||||
'@smithy/querystring-builder': 4.2.8
|
|
||||||
'@smithy/types': 4.12.0
|
|
||||||
'@smithy/util-base64': 4.3.0
|
|
||||||
tslib: 2.8.1
|
|
||||||
|
|
||||||
'@smithy/hash-blob-browser@4.0.5':
|
'@smithy/hash-blob-browser@4.0.5':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@smithy/chunked-blob-reader': 5.0.0
|
'@smithy/chunked-blob-reader': 5.0.0
|
||||||
@@ -11605,10 +11446,6 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
tslib: 2.8.1
|
tslib: 2.8.1
|
||||||
|
|
||||||
'@smithy/is-array-buffer@4.2.0':
|
|
||||||
dependencies:
|
|
||||||
tslib: 2.8.1
|
|
||||||
|
|
||||||
'@smithy/md5-js@4.0.5':
|
'@smithy/md5-js@4.0.5':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@smithy/types': 4.3.2
|
'@smithy/types': 4.3.2
|
||||||
@@ -11632,17 +11469,6 @@ snapshots:
|
|||||||
'@smithy/util-middleware': 4.0.5
|
'@smithy/util-middleware': 4.0.5
|
||||||
tslib: 2.8.1
|
tslib: 2.8.1
|
||||||
|
|
||||||
'@smithy/middleware-endpoint@4.4.13':
|
|
||||||
dependencies:
|
|
||||||
'@smithy/core': 3.22.1
|
|
||||||
'@smithy/middleware-serde': 4.2.9
|
|
||||||
'@smithy/node-config-provider': 4.3.8
|
|
||||||
'@smithy/shared-ini-file-loader': 4.4.3
|
|
||||||
'@smithy/types': 4.12.0
|
|
||||||
'@smithy/url-parser': 4.2.8
|
|
||||||
'@smithy/util-middleware': 4.2.8
|
|
||||||
tslib: 2.8.1
|
|
||||||
|
|
||||||
'@smithy/middleware-retry@4.1.20':
|
'@smithy/middleware-retry@4.1.20':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@smithy/node-config-provider': 4.1.4
|
'@smithy/node-config-provider': 4.1.4
|
||||||
@@ -11662,22 +11488,11 @@ snapshots:
|
|||||||
'@smithy/types': 4.3.2
|
'@smithy/types': 4.3.2
|
||||||
tslib: 2.8.1
|
tslib: 2.8.1
|
||||||
|
|
||||||
'@smithy/middleware-serde@4.2.9':
|
|
||||||
dependencies:
|
|
||||||
'@smithy/protocol-http': 5.3.8
|
|
||||||
'@smithy/types': 4.12.0
|
|
||||||
tslib: 2.8.1
|
|
||||||
|
|
||||||
'@smithy/middleware-stack@4.0.5':
|
'@smithy/middleware-stack@4.0.5':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@smithy/types': 4.3.2
|
'@smithy/types': 4.3.2
|
||||||
tslib: 2.8.1
|
tslib: 2.8.1
|
||||||
|
|
||||||
'@smithy/middleware-stack@4.2.8':
|
|
||||||
dependencies:
|
|
||||||
'@smithy/types': 4.12.0
|
|
||||||
tslib: 2.8.1
|
|
||||||
|
|
||||||
'@smithy/node-config-provider@4.1.4':
|
'@smithy/node-config-provider@4.1.4':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@smithy/property-provider': 4.0.5
|
'@smithy/property-provider': 4.0.5
|
||||||
@@ -11685,13 +11500,6 @@ snapshots:
|
|||||||
'@smithy/types': 4.3.2
|
'@smithy/types': 4.3.2
|
||||||
tslib: 2.8.1
|
tslib: 2.8.1
|
||||||
|
|
||||||
'@smithy/node-config-provider@4.3.8':
|
|
||||||
dependencies:
|
|
||||||
'@smithy/property-provider': 4.2.8
|
|
||||||
'@smithy/shared-ini-file-loader': 4.4.3
|
|
||||||
'@smithy/types': 4.12.0
|
|
||||||
tslib: 2.8.1
|
|
||||||
|
|
||||||
'@smithy/node-http-handler@4.1.1':
|
'@smithy/node-http-handler@4.1.1':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@smithy/abort-controller': 4.0.5
|
'@smithy/abort-controller': 4.0.5
|
||||||
@@ -11700,56 +11508,27 @@ snapshots:
|
|||||||
'@smithy/types': 4.3.2
|
'@smithy/types': 4.3.2
|
||||||
tslib: 2.8.1
|
tslib: 2.8.1
|
||||||
|
|
||||||
'@smithy/node-http-handler@4.4.9':
|
|
||||||
dependencies:
|
|
||||||
'@smithy/abort-controller': 4.2.8
|
|
||||||
'@smithy/protocol-http': 5.3.8
|
|
||||||
'@smithy/querystring-builder': 4.2.8
|
|
||||||
'@smithy/types': 4.12.0
|
|
||||||
tslib: 2.8.1
|
|
||||||
|
|
||||||
'@smithy/property-provider@4.0.5':
|
'@smithy/property-provider@4.0.5':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@smithy/types': 4.3.2
|
'@smithy/types': 4.3.2
|
||||||
tslib: 2.8.1
|
tslib: 2.8.1
|
||||||
|
|
||||||
'@smithy/property-provider@4.2.8':
|
|
||||||
dependencies:
|
|
||||||
'@smithy/types': 4.12.0
|
|
||||||
tslib: 2.8.1
|
|
||||||
|
|
||||||
'@smithy/protocol-http@5.1.3':
|
'@smithy/protocol-http@5.1.3':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@smithy/types': 4.3.2
|
'@smithy/types': 4.3.2
|
||||||
tslib: 2.8.1
|
tslib: 2.8.1
|
||||||
|
|
||||||
'@smithy/protocol-http@5.3.8':
|
|
||||||
dependencies:
|
|
||||||
'@smithy/types': 4.12.0
|
|
||||||
tslib: 2.8.1
|
|
||||||
|
|
||||||
'@smithy/querystring-builder@4.0.5':
|
'@smithy/querystring-builder@4.0.5':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@smithy/types': 4.3.2
|
'@smithy/types': 4.3.2
|
||||||
'@smithy/util-uri-escape': 4.0.0
|
'@smithy/util-uri-escape': 4.0.0
|
||||||
tslib: 2.8.1
|
tslib: 2.8.1
|
||||||
|
|
||||||
'@smithy/querystring-builder@4.2.8':
|
|
||||||
dependencies:
|
|
||||||
'@smithy/types': 4.12.0
|
|
||||||
'@smithy/util-uri-escape': 4.2.0
|
|
||||||
tslib: 2.8.1
|
|
||||||
|
|
||||||
'@smithy/querystring-parser@4.0.5':
|
'@smithy/querystring-parser@4.0.5':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@smithy/types': 4.3.2
|
'@smithy/types': 4.3.2
|
||||||
tslib: 2.8.1
|
tslib: 2.8.1
|
||||||
|
|
||||||
'@smithy/querystring-parser@4.2.8':
|
|
||||||
dependencies:
|
|
||||||
'@smithy/types': 4.12.0
|
|
||||||
tslib: 2.8.1
|
|
||||||
|
|
||||||
'@smithy/service-error-classification@4.0.7':
|
'@smithy/service-error-classification@4.0.7':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@smithy/types': 4.3.2
|
'@smithy/types': 4.3.2
|
||||||
@@ -11759,11 +11538,6 @@ snapshots:
|
|||||||
'@smithy/types': 4.3.2
|
'@smithy/types': 4.3.2
|
||||||
tslib: 2.8.1
|
tslib: 2.8.1
|
||||||
|
|
||||||
'@smithy/shared-ini-file-loader@4.4.3':
|
|
||||||
dependencies:
|
|
||||||
'@smithy/types': 4.12.0
|
|
||||||
tslib: 2.8.1
|
|
||||||
|
|
||||||
'@smithy/signature-v4@5.1.3':
|
'@smithy/signature-v4@5.1.3':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@smithy/is-array-buffer': 4.0.0
|
'@smithy/is-array-buffer': 4.0.0
|
||||||
@@ -11775,16 +11549,6 @@ snapshots:
|
|||||||
'@smithy/util-utf8': 4.0.0
|
'@smithy/util-utf8': 4.0.0
|
||||||
tslib: 2.8.1
|
tslib: 2.8.1
|
||||||
|
|
||||||
'@smithy/smithy-client@4.11.2':
|
|
||||||
dependencies:
|
|
||||||
'@smithy/core': 3.22.1
|
|
||||||
'@smithy/middleware-endpoint': 4.4.13
|
|
||||||
'@smithy/middleware-stack': 4.2.8
|
|
||||||
'@smithy/protocol-http': 5.3.8
|
|
||||||
'@smithy/types': 4.12.0
|
|
||||||
'@smithy/util-stream': 4.5.11
|
|
||||||
tslib: 2.8.1
|
|
||||||
|
|
||||||
'@smithy/smithy-client@4.5.0':
|
'@smithy/smithy-client@4.5.0':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@smithy/core': 3.9.0
|
'@smithy/core': 3.9.0
|
||||||
@@ -11795,10 +11559,6 @@ snapshots:
|
|||||||
'@smithy/util-stream': 4.2.4
|
'@smithy/util-stream': 4.2.4
|
||||||
tslib: 2.8.1
|
tslib: 2.8.1
|
||||||
|
|
||||||
'@smithy/types@4.12.0':
|
|
||||||
dependencies:
|
|
||||||
tslib: 2.8.1
|
|
||||||
|
|
||||||
'@smithy/types@4.3.2':
|
'@smithy/types@4.3.2':
|
||||||
dependencies:
|
dependencies:
|
||||||
tslib: 2.8.1
|
tslib: 2.8.1
|
||||||
@@ -11809,32 +11569,16 @@ snapshots:
|
|||||||
'@smithy/types': 4.3.2
|
'@smithy/types': 4.3.2
|
||||||
tslib: 2.8.1
|
tslib: 2.8.1
|
||||||
|
|
||||||
'@smithy/url-parser@4.2.8':
|
|
||||||
dependencies:
|
|
||||||
'@smithy/querystring-parser': 4.2.8
|
|
||||||
'@smithy/types': 4.12.0
|
|
||||||
tslib: 2.8.1
|
|
||||||
|
|
||||||
'@smithy/util-base64@4.0.0':
|
'@smithy/util-base64@4.0.0':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@smithy/util-buffer-from': 4.0.0
|
'@smithy/util-buffer-from': 4.0.0
|
||||||
'@smithy/util-utf8': 4.0.0
|
'@smithy/util-utf8': 4.0.0
|
||||||
tslib: 2.8.1
|
tslib: 2.8.1
|
||||||
|
|
||||||
'@smithy/util-base64@4.3.0':
|
|
||||||
dependencies:
|
|
||||||
'@smithy/util-buffer-from': 4.2.0
|
|
||||||
'@smithy/util-utf8': 4.2.0
|
|
||||||
tslib: 2.8.1
|
|
||||||
|
|
||||||
'@smithy/util-body-length-browser@4.0.0':
|
'@smithy/util-body-length-browser@4.0.0':
|
||||||
dependencies:
|
dependencies:
|
||||||
tslib: 2.8.1
|
tslib: 2.8.1
|
||||||
|
|
||||||
'@smithy/util-body-length-browser@4.2.0':
|
|
||||||
dependencies:
|
|
||||||
tslib: 2.8.1
|
|
||||||
|
|
||||||
'@smithy/util-body-length-node@4.0.0':
|
'@smithy/util-body-length-node@4.0.0':
|
||||||
dependencies:
|
dependencies:
|
||||||
tslib: 2.8.1
|
tslib: 2.8.1
|
||||||
@@ -11849,11 +11593,6 @@ snapshots:
|
|||||||
'@smithy/is-array-buffer': 4.0.0
|
'@smithy/is-array-buffer': 4.0.0
|
||||||
tslib: 2.8.1
|
tslib: 2.8.1
|
||||||
|
|
||||||
'@smithy/util-buffer-from@4.2.0':
|
|
||||||
dependencies:
|
|
||||||
'@smithy/is-array-buffer': 4.2.0
|
|
||||||
tslib: 2.8.1
|
|
||||||
|
|
||||||
'@smithy/util-config-provider@4.0.0':
|
'@smithy/util-config-provider@4.0.0':
|
||||||
dependencies:
|
dependencies:
|
||||||
tslib: 2.8.1
|
tslib: 2.8.1
|
||||||
@@ -11886,20 +11625,11 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
tslib: 2.8.1
|
tslib: 2.8.1
|
||||||
|
|
||||||
'@smithy/util-hex-encoding@4.2.0':
|
|
||||||
dependencies:
|
|
||||||
tslib: 2.8.1
|
|
||||||
|
|
||||||
'@smithy/util-middleware@4.0.5':
|
'@smithy/util-middleware@4.0.5':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@smithy/types': 4.3.2
|
'@smithy/types': 4.3.2
|
||||||
tslib: 2.8.1
|
tslib: 2.8.1
|
||||||
|
|
||||||
'@smithy/util-middleware@4.2.8':
|
|
||||||
dependencies:
|
|
||||||
'@smithy/types': 4.12.0
|
|
||||||
tslib: 2.8.1
|
|
||||||
|
|
||||||
'@smithy/util-retry@4.0.7':
|
'@smithy/util-retry@4.0.7':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@smithy/service-error-classification': 4.0.7
|
'@smithy/service-error-classification': 4.0.7
|
||||||
@@ -11917,25 +11647,10 @@ snapshots:
|
|||||||
'@smithy/util-utf8': 4.0.0
|
'@smithy/util-utf8': 4.0.0
|
||||||
tslib: 2.8.1
|
tslib: 2.8.1
|
||||||
|
|
||||||
'@smithy/util-stream@4.5.11':
|
|
||||||
dependencies:
|
|
||||||
'@smithy/fetch-http-handler': 5.3.9
|
|
||||||
'@smithy/node-http-handler': 4.4.9
|
|
||||||
'@smithy/types': 4.12.0
|
|
||||||
'@smithy/util-base64': 4.3.0
|
|
||||||
'@smithy/util-buffer-from': 4.2.0
|
|
||||||
'@smithy/util-hex-encoding': 4.2.0
|
|
||||||
'@smithy/util-utf8': 4.2.0
|
|
||||||
tslib: 2.8.1
|
|
||||||
|
|
||||||
'@smithy/util-uri-escape@4.0.0':
|
'@smithy/util-uri-escape@4.0.0':
|
||||||
dependencies:
|
dependencies:
|
||||||
tslib: 2.8.1
|
tslib: 2.8.1
|
||||||
|
|
||||||
'@smithy/util-uri-escape@4.2.0':
|
|
||||||
dependencies:
|
|
||||||
tslib: 2.8.1
|
|
||||||
|
|
||||||
'@smithy/util-utf8@2.3.0':
|
'@smithy/util-utf8@2.3.0':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@smithy/util-buffer-from': 2.2.0
|
'@smithy/util-buffer-from': 2.2.0
|
||||||
@@ -11946,21 +11661,12 @@ snapshots:
|
|||||||
'@smithy/util-buffer-from': 4.0.0
|
'@smithy/util-buffer-from': 4.0.0
|
||||||
tslib: 2.8.1
|
tslib: 2.8.1
|
||||||
|
|
||||||
'@smithy/util-utf8@4.2.0':
|
|
||||||
dependencies:
|
|
||||||
'@smithy/util-buffer-from': 4.2.0
|
|
||||||
tslib: 2.8.1
|
|
||||||
|
|
||||||
'@smithy/util-waiter@4.0.7':
|
'@smithy/util-waiter@4.0.7':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@smithy/abort-controller': 4.0.5
|
'@smithy/abort-controller': 4.0.5
|
||||||
'@smithy/types': 4.3.2
|
'@smithy/types': 4.3.2
|
||||||
tslib: 2.8.1
|
tslib: 2.8.1
|
||||||
|
|
||||||
'@smithy/uuid@1.1.0':
|
|
||||||
dependencies:
|
|
||||||
tslib: 2.8.1
|
|
||||||
|
|
||||||
'@socket.io/component-emitter@3.1.2': {}
|
'@socket.io/component-emitter@3.1.2': {}
|
||||||
|
|
||||||
'@standard-schema/spec@1.0.0': {}
|
'@standard-schema/spec@1.0.0': {}
|
||||||
@@ -13084,11 +12790,6 @@ snapshots:
|
|||||||
|
|
||||||
buffer-from@1.1.2: {}
|
buffer-from@1.1.2: {}
|
||||||
|
|
||||||
buffer@5.6.0:
|
|
||||||
dependencies:
|
|
||||||
base64-js: 1.5.1
|
|
||||||
ieee754: 1.2.1
|
|
||||||
|
|
||||||
buffer@5.7.1:
|
buffer@5.7.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
base64-js: 1.5.1
|
base64-js: 1.5.1
|
||||||
@@ -17209,11 +16910,6 @@ snapshots:
|
|||||||
es-errors: 1.3.0
|
es-errors: 1.3.0
|
||||||
internal-slot: 1.1.0
|
internal-slot: 1.1.0
|
||||||
|
|
||||||
stream-browserify@3.0.0:
|
|
||||||
dependencies:
|
|
||||||
inherits: 2.0.4
|
|
||||||
readable-stream: 3.6.2
|
|
||||||
|
|
||||||
string-width@4.2.3:
|
string-width@4.2.3:
|
||||||
dependencies:
|
dependencies:
|
||||||
emoji-regex: 8.0.0
|
emoji-regex: 8.0.0
|
||||||
|
|||||||
Reference in New Issue
Block a user