mirror of
https://github.com/outline/outline.git
synced 2026-06-13 19:35:02 +03:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 2228df4054 |
+5
-1
@@ -205,10 +205,14 @@ SENTRY_TUNNEL=
|
||||
|
||||
# To support sending outgoing transactional emails such as "document updated" or
|
||||
# "you've been invited" you'll need to provide authentication for an SMTP server
|
||||
SMTP_SERVICE=
|
||||
SMTP_HOST=
|
||||
SMTP_PORT=
|
||||
SMTP_USERNAME=
|
||||
SMTP_PASSWORD=
|
||||
SMTP_FROM_EMAIL=
|
||||
SMTP_REPLY_EMAIL=
|
||||
SMTP_TLS_CIPHERS=
|
||||
SMTP_SECURE=true
|
||||
|
||||
# The default interface language. See translate.getoutline.com for a list of
|
||||
# available language codes and their rough percentage translated.
|
||||
|
||||
@@ -15,8 +15,6 @@ requestInfoDefaultTitles:
|
||||
|
||||
requestInfoLabelToAdd: more information needed
|
||||
|
||||
requestInfoUserstoExclude:
|
||||
- tommoor
|
||||
|
||||
# Configuration for new-pr-welcome - https://github.com/behaviorbot/new-pr-welcome
|
||||
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
name: Lint
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches: [ main ]
|
||||
|
||||
jobs:
|
||||
run-linters:
|
||||
if: startsWith(github.actor, 'codegen-sh')
|
||||
name: Run linters
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
permissions:
|
||||
# Give the default GITHUB_TOKEN write permission to commit and push the
|
||||
# added or changed files to the repository.
|
||||
contents: write
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20.x
|
||||
cache: 'yarn'
|
||||
- run: yarn install --frozen-lockfile
|
||||
- run: yarn lint --fix
|
||||
|
||||
- name: Commit changes
|
||||
uses: stefanzweifel/git-auto-commit-action@v5
|
||||
with:
|
||||
commit_message: 'Applied automatic fixes'
|
||||
@@ -171,10 +171,6 @@
|
||||
"description": "smtp.example.com (optional)",
|
||||
"required": false
|
||||
},
|
||||
"SMTP_SERVICE": {
|
||||
"description": "Well-known SMTP service name for nodemailer (optional, e.g. 'gmail', 'SES')",
|
||||
"required": false
|
||||
},
|
||||
"SMTP_PORT": {
|
||||
"description": "1234 (optional)",
|
||||
"required": false
|
||||
|
||||
@@ -7,43 +7,17 @@ import User from "~/models/User";
|
||||
import Tooltip from "~/components/Tooltip";
|
||||
import Avatar, { AvatarSize } from "./Avatar";
|
||||
|
||||
/**
|
||||
* Props for the AvatarWithPresence component
|
||||
*/
|
||||
type Props = {
|
||||
/** The user to display the avatar for */
|
||||
user: User;
|
||||
/** Whether the user is currently present in the document */
|
||||
isPresent: boolean;
|
||||
/** Whether the user is currently editing the document */
|
||||
isEditing: boolean;
|
||||
/** Whether the user is currently observing the document */
|
||||
isObserving: boolean;
|
||||
/** Whether this avatar represents the current user */
|
||||
isCurrentUser: boolean;
|
||||
/** Optional click handler for the avatar */
|
||||
onClick?: React.MouseEventHandler<HTMLImageElement>;
|
||||
/** Size of the avatar, defaults to AvatarSize.Large */
|
||||
size?: AvatarSize;
|
||||
/** Optional inline styles to apply to the avatar wrapper */
|
||||
style?: React.CSSProperties;
|
||||
};
|
||||
|
||||
/**
|
||||
* AvatarWithPresence component displays a user's avatar with visual indicators
|
||||
* for their current status (present, editing, observing).
|
||||
*
|
||||
* The component shows different visual states:
|
||||
* - Present users have full opacity
|
||||
* - Non-present users have reduced opacity
|
||||
* - Observing users have a colored border matching their user color
|
||||
* - Hovering shows a colored border
|
||||
*
|
||||
* A tooltip displays the user's name and current status.
|
||||
*
|
||||
* @param props - Component properties
|
||||
* @returns React component
|
||||
*/
|
||||
function AvatarWithPresence({
|
||||
onClick,
|
||||
user,
|
||||
@@ -90,33 +64,16 @@ function AvatarWithPresence({
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Centered container for tooltip content
|
||||
*/
|
||||
const Centered = styled.div`
|
||||
text-align: center;
|
||||
`;
|
||||
|
||||
/**
|
||||
* Props for the AvatarPresence styled component
|
||||
*/
|
||||
type AvatarWrapperProps = {
|
||||
/** Whether the user is currently present */
|
||||
$isPresent: boolean;
|
||||
/** Whether the user is currently observing */
|
||||
$isObserving: boolean;
|
||||
/** The user's color for border highlighting */
|
||||
$color: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* Styled component that wraps the Avatar and provides visual indicators
|
||||
* for the user's presence status.
|
||||
*
|
||||
* - Adjusts opacity based on presence
|
||||
* - Adds colored borders for observing users
|
||||
* - Handles hover effects
|
||||
*/
|
||||
const AvatarPresence = styled.div<AvatarWrapperProps>`
|
||||
opacity: ${(props) => (props.$isPresent ? 1 : 0.5)};
|
||||
transition: opacity 250ms ease-in-out;
|
||||
|
||||
@@ -2,11 +2,6 @@ import React from "react";
|
||||
import styled from "styled-components";
|
||||
import { fadeIn } from "~/styles/animations";
|
||||
|
||||
/**
|
||||
* Fade in animation for a component.
|
||||
*
|
||||
* @param timing - The duration of the fade in animation, default is 250ms.
|
||||
*/
|
||||
const Fade = styled.span<{ timing?: number | string }>`
|
||||
animation: ${fadeIn} ${(props) => props.timing || "250ms"} ease-in-out;
|
||||
`;
|
||||
@@ -22,6 +17,7 @@ type Props = {
|
||||
*/
|
||||
export const ConditionalFade = ({ animate, children }: Props) => {
|
||||
const [isAnimated] = React.useState(animate);
|
||||
|
||||
return isAnimated ? <Fade>{children}</Fade> : <>{children}</>;
|
||||
};
|
||||
|
||||
|
||||
@@ -645,11 +645,12 @@ function SuggestionsMenu<T extends MenuItem>(props: Props<T>) {
|
||||
"section" in item ? item.section?.({ t }) : undefined;
|
||||
|
||||
const response = (
|
||||
<React.Fragment key={`${index}-${item.name}`}>
|
||||
<>
|
||||
{currentHeading !== previousHeading && (
|
||||
<Header key={currentHeading}>{currentHeading}</Header>
|
||||
)}
|
||||
<ListItem
|
||||
key={index}
|
||||
onPointerMove={handlePointerMove}
|
||||
onPointerDown={handlePointerDown}
|
||||
>
|
||||
@@ -658,7 +659,7 @@ function SuggestionsMenu<T extends MenuItem>(props: Props<T>) {
|
||||
onClick: () => handleClickItem(item),
|
||||
})}
|
||||
</ListItem>
|
||||
</React.Fragment>
|
||||
</>
|
||||
);
|
||||
|
||||
previousHeading = currentHeading;
|
||||
|
||||
@@ -10,8 +10,8 @@ import {
|
||||
import { Decoration, DecorationSet } from "prosemirror-view";
|
||||
import * as React from "react";
|
||||
import { v4 } from "uuid";
|
||||
import { LANGUAGES } from "@shared/editor/extensions/Prism";
|
||||
import Extension, { WidgetProps } from "@shared/editor/lib/Extension";
|
||||
import { codeLanguages } from "@shared/editor/lib/code";
|
||||
import isMarkdown from "@shared/editor/lib/isMarkdown";
|
||||
import normalizePastedMarkdown from "@shared/editor/lib/markdown/normalize";
|
||||
import { isRemoteTransaction } from "@shared/editor/lib/multiplayer";
|
||||
@@ -88,7 +88,7 @@ export default class PasteHandler extends Extension {
|
||||
|
||||
// If the users selection is currently in a code block then paste
|
||||
// as plain text, ignore all formatting and HTML content.
|
||||
if (isInCode(state, { inclusive: true })) {
|
||||
if (isInCode(state)) {
|
||||
event.preventDefault();
|
||||
view.dispatch(state.tr.insertText(text));
|
||||
return true;
|
||||
@@ -228,7 +228,7 @@ export default class PasteHandler extends Extension {
|
||||
state.tr
|
||||
.replaceSelectionWith(
|
||||
state.schema.nodes.code_block.create({
|
||||
language: Object.keys(codeLanguages).includes(
|
||||
language: Object.keys(LANGUAGES).includes(
|
||||
vscodeMeta.mode
|
||||
)
|
||||
? vscodeMeta.mode
|
||||
|
||||
+12
-13
@@ -2,11 +2,8 @@ import { CopyIcon, ExpandedIcon } from "outline-icons";
|
||||
import { Node as ProseMirrorNode } from "prosemirror-model";
|
||||
import { EditorState } from "prosemirror-state";
|
||||
import * as React from "react";
|
||||
import {
|
||||
getFrequentCodeLanguages,
|
||||
codeLanguages,
|
||||
getLabelForLanguage,
|
||||
} from "@shared/editor/lib/code";
|
||||
import { LANGUAGES } from "@shared/editor/extensions/Prism";
|
||||
import { getFrequentCodeLanguages } from "@shared/editor/lib/code";
|
||||
import { MenuItem } from "@shared/editor/types";
|
||||
import { Dictionary } from "~/hooks/useDictionary";
|
||||
|
||||
@@ -17,19 +14,20 @@ export default function codeMenuItems(
|
||||
): MenuItem[] {
|
||||
const node = state.selection.$from.node();
|
||||
|
||||
const allLanguages = Object.entries(LANGUAGES) as [
|
||||
keyof typeof LANGUAGES,
|
||||
string
|
||||
][];
|
||||
const frequentLanguages = getFrequentCodeLanguages();
|
||||
|
||||
const frequentLangMenuItems = frequentLanguages.map((value) => {
|
||||
const label = codeLanguages[value]?.label;
|
||||
const label = LANGUAGES[value];
|
||||
return langToMenuItem({ node, value, label });
|
||||
});
|
||||
|
||||
const remainingLangMenuItems = Object.entries(codeLanguages)
|
||||
.filter(
|
||||
([value]) =>
|
||||
!frequentLanguages.includes(value as keyof typeof codeLanguages)
|
||||
)
|
||||
.map(([value, item]) => langToMenuItem({ node, value, label: item.label }));
|
||||
const remainingLangMenuItems = allLanguages
|
||||
.filter(([value]) => !frequentLanguages.includes(value))
|
||||
.map(([value, label]) => langToMenuItem({ node, value, label }));
|
||||
|
||||
const languageMenuItems = frequentLangMenuItems.length
|
||||
? [
|
||||
@@ -54,7 +52,8 @@ export default function codeMenuItems(
|
||||
visible: !readOnly,
|
||||
name: "code_block",
|
||||
icon: <ExpandedIcon />,
|
||||
label: getLabelForLanguage(node.attrs.language ?? "none"),
|
||||
// @ts-expect-error We have a fallback for incorrect mapping
|
||||
label: LANGUAGES[node.attrs.language ?? "none"],
|
||||
children: languageMenuItems,
|
||||
},
|
||||
];
|
||||
|
||||
@@ -1,11 +1,6 @@
|
||||
import * as React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
/**
|
||||
* Hook that provides a dictionary of translated UI strings.
|
||||
*
|
||||
* @returns An object containing all translated UI strings used throughout the application
|
||||
*/
|
||||
export default function useDictionary() {
|
||||
const { t } = useTranslation();
|
||||
|
||||
|
||||
@@ -1,15 +1,6 @@
|
||||
import * as React from "react";
|
||||
import useWindowSize from "./useWindowSize";
|
||||
|
||||
/**
|
||||
* Hook to calculate the maximum height for an element based on its position and viewport size.
|
||||
*
|
||||
* @param options Configuration options
|
||||
* @param options.elementRef A ref pointing to the element to calculate max height for
|
||||
* @param options.maxViewportPercentage The maximum height of the element as a percentage of the viewport
|
||||
* @param options.margin The margin to apply to the positioning
|
||||
* @returns Object containing the calculated maxHeight and a function to recalculate it
|
||||
*/
|
||||
const useMaxHeight = ({
|
||||
elementRef,
|
||||
maxViewportPercentage = 90,
|
||||
|
||||
@@ -1,11 +1,5 @@
|
||||
import { useState, useEffect } from "react";
|
||||
|
||||
/**
|
||||
* Hook to check if a media query matches the current viewport.
|
||||
*
|
||||
* @param query The CSS media query to check against
|
||||
* @returns boolean indicating whether the media query matches
|
||||
*/
|
||||
export default function useMediaQuery(query: string): boolean {
|
||||
const [matches, setMatches] = useState<boolean>(false);
|
||||
|
||||
|
||||
@@ -1,11 +1,6 @@
|
||||
import { breakpoints } from "@shared/styles";
|
||||
import useMediaQuery from "~/hooks/useMediaQuery";
|
||||
|
||||
/**
|
||||
* Hook to detect if the current viewport is mobile-sized.
|
||||
*
|
||||
* @returns boolean indicating whether the current viewport is mobile-sized
|
||||
*/
|
||||
export default function useMobile(): boolean {
|
||||
return useMediaQuery(`(max-width: ${breakpoints.tablet - 1}px)`);
|
||||
}
|
||||
|
||||
@@ -1,11 +1,6 @@
|
||||
import React from "react";
|
||||
import { useLocation } from "react-router-dom";
|
||||
|
||||
/**
|
||||
* Hook to access URL query parameters from the current location.
|
||||
*
|
||||
* @returns URLSearchParams object containing the current URL query parameters
|
||||
*/
|
||||
export default function useQuery() {
|
||||
const location = useLocation();
|
||||
|
||||
|
||||
@@ -2,11 +2,6 @@ import { MobXProviderContext } from "mobx-react";
|
||||
import * as React from "react";
|
||||
import RootStore from "~/stores";
|
||||
|
||||
/**
|
||||
* Hook to access the MobX stores from the React context.
|
||||
*
|
||||
* @returns The root store containing all application stores
|
||||
*/
|
||||
export default function useStores() {
|
||||
return React.useContext(MobXProviderContext) as typeof RootStore;
|
||||
}
|
||||
|
||||
@@ -1,10 +1,5 @@
|
||||
import * as React from "react";
|
||||
|
||||
/**
|
||||
* Hook that executes a callback when the component unmounts.
|
||||
*
|
||||
* @param callback Function to be called on component unmount
|
||||
*/
|
||||
const useUnmount = (callback: (...args: Array<any>) => any) => {
|
||||
const ref = React.useRef(callback);
|
||||
ref.current = callback;
|
||||
|
||||
@@ -1,11 +1,5 @@
|
||||
import { useLayoutEffect, useState } from "react";
|
||||
|
||||
/**
|
||||
* Hook to get the current viewport height, accounting for mobile virtual keyboards.
|
||||
* Uses the VisualViewport API when available, falling back to window.innerHeight.
|
||||
*
|
||||
* @returns The current viewport height in pixels
|
||||
*/
|
||||
export default function useViewportHeight(): number | void {
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/VisualViewport#browser_compatibility
|
||||
// Note: No support in Firefox at time of writing, however this mainly exists
|
||||
|
||||
@@ -13,13 +13,6 @@ const defaultOptions = {
|
||||
throttle: 100,
|
||||
};
|
||||
|
||||
/**
|
||||
* Hook to track the window's scroll position.
|
||||
*
|
||||
* @param options Configuration options
|
||||
* @param options.throttle Time in milliseconds to throttle the scroll event
|
||||
* @returns Object containing the current scroll position (x, y coordinates)
|
||||
*/
|
||||
export default function useWindowScrollPosition(options: {
|
||||
throttle: number;
|
||||
}): {
|
||||
|
||||
@@ -15,9 +15,6 @@ class Import extends Model {
|
||||
/** The name of the import. */
|
||||
name: string;
|
||||
|
||||
/** Descriptive error message when the import errors out. */
|
||||
error: string | null;
|
||||
|
||||
/** The current state of the import. */
|
||||
@Field
|
||||
@observable
|
||||
|
||||
@@ -16,7 +16,6 @@ import { useDocumentContext } from "~/components/DocumentContext";
|
||||
import Facepile from "~/components/Facepile";
|
||||
import Fade from "~/components/Fade";
|
||||
import { ResizingHeightContainer } from "~/components/ResizingHeightContainer";
|
||||
import useBoolean from "~/hooks/useBoolean";
|
||||
import { useLocationSidebarContext } from "~/hooks/useLocationSidebarContext";
|
||||
import useOnClickOutside from "~/hooks/useOnClickOutside";
|
||||
import usePersistedState from "~/hooks/usePersistedState";
|
||||
@@ -64,7 +63,7 @@ function CommentThread({
|
||||
const history = useHistory();
|
||||
const location = useLocation();
|
||||
const sidebarContext = useLocationSidebarContext();
|
||||
const [autoFocus, setAutoFocusOn, setAutoFocusOff] = useBoolean(thread.isNew);
|
||||
const [autoFocus, setAutoFocus] = React.useState(thread.isNew);
|
||||
|
||||
const can = usePolicy(document);
|
||||
|
||||
@@ -157,9 +156,9 @@ function CommentThread({
|
||||
|
||||
React.useEffect(() => {
|
||||
if (!focused && autoFocus) {
|
||||
setAutoFocusOff();
|
||||
setAutoFocus(false);
|
||||
}
|
||||
}, [focused, autoFocus, setAutoFocusOff]);
|
||||
}, [focused, autoFocus]);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (focused) {
|
||||
@@ -274,7 +273,7 @@ function CommentThread({
|
||||
)}
|
||||
</ResizingHeightContainer>
|
||||
{!focused && !recessed && !draft && canReply && (
|
||||
<Reply onClick={setAutoFocusOn}>{t("Reply")}…</Reply>
|
||||
<Reply onClick={() => setAutoFocus(true)}>{t("Reply")}…</Reply>
|
||||
)}
|
||||
</Thread>
|
||||
);
|
||||
|
||||
@@ -15,7 +15,6 @@ import Time from "~/components/Time";
|
||||
import useCurrentUser from "~/hooks/useCurrentUser";
|
||||
import useStores from "~/hooks/useStores";
|
||||
import { ImportMenu } from "~/menus/ImportMenu";
|
||||
import isCloudHosted from "~/utils/isCloudHosted";
|
||||
|
||||
type Props = {
|
||||
/** Import that's displayed as list item. */
|
||||
@@ -30,10 +29,6 @@ export const ImportListItem = observer(({ importModel }: Props) => {
|
||||
const showProgress =
|
||||
importModel.state !== ImportState.Canceled &&
|
||||
importModel.state !== ImportState.Errored;
|
||||
const showErrorInfo =
|
||||
!isCloudHosted &&
|
||||
importModel.state === ImportState.Errored &&
|
||||
!!importModel.error;
|
||||
|
||||
const stateMap = React.useMemo(
|
||||
() => ({
|
||||
@@ -119,12 +114,6 @@ export const ImportListItem = observer(({ importModel }: Props) => {
|
||||
subtitle={
|
||||
<>
|
||||
{stateMap[importModel.state]} •
|
||||
{showErrorInfo && (
|
||||
<>
|
||||
{importModel.error}
|
||||
{`. ${t("Check server logs for more details.")}`} •
|
||||
</>
|
||||
)}
|
||||
{t(`{{userName}} requested`, {
|
||||
userName:
|
||||
user.id === importModel.createdBy.id
|
||||
|
||||
+18
-19
@@ -48,16 +48,16 @@
|
||||
"> 0.25%, not dead"
|
||||
],
|
||||
"dependencies": {
|
||||
"@aws-sdk/client-s3": "3.774.0",
|
||||
"@aws-sdk/lib-storage": "3.774.0",
|
||||
"@aws-sdk/s3-presigned-post": "3.774.0",
|
||||
"@aws-sdk/s3-request-presigner": "3.774.0",
|
||||
"@aws-sdk/signature-v4-crt": "^3.774.0",
|
||||
"@babel/core": "^7.26.10",
|
||||
"@aws-sdk/client-s3": "3.758.0",
|
||||
"@aws-sdk/lib-storage": "3.758.0",
|
||||
"@aws-sdk/s3-presigned-post": "3.758.0",
|
||||
"@aws-sdk/s3-request-presigner": "3.758.0",
|
||||
"@aws-sdk/signature-v4-crt": "^3.758.0",
|
||||
"@babel/core": "^7.26.9",
|
||||
"@babel/plugin-proposal-decorators": "^7.25.9",
|
||||
"@babel/plugin-transform-class-properties": "^7.25.9",
|
||||
"@babel/plugin-transform-destructuring": "^7.25.9",
|
||||
"@babel/plugin-transform-regenerator": "^7.27.0",
|
||||
"@babel/plugin-transform-regenerator": "^7.25.9",
|
||||
"@babel/preset-env": "^7.26.9",
|
||||
"@babel/preset-react": "^7.26.3",
|
||||
"@benrbray/prosemirror-math": "^0.2.2",
|
||||
@@ -110,7 +110,7 @@
|
||||
"copy-to-clipboard": "^3.3.3",
|
||||
"core-js": "^3.37.0",
|
||||
"crypto-js": "^4.2.0",
|
||||
"datadog-metrics": "^0.12.1",
|
||||
"datadog-metrics": "^0.11.2",
|
||||
"date-fns": "^3.6.0",
|
||||
"dd-trace": "^5.40.0",
|
||||
"diff": "^5.2.0",
|
||||
@@ -129,12 +129,11 @@
|
||||
"fuzzy-search": "^3.2.1",
|
||||
"glob": "^8.1.0",
|
||||
"http-errors": "2.0.0",
|
||||
"https-proxy-agent": "^7.0.6",
|
||||
"i18next": "^22.5.1",
|
||||
"i18next-fs-backend": "^2.6.0",
|
||||
"i18next-http-backend": "^2.7.3",
|
||||
"invariant": "^2.2.4",
|
||||
"ioredis": "^5.6.0",
|
||||
"ioredis": "^5.4.1",
|
||||
"is-printable-key-event": "^1.0.0",
|
||||
"jsdom": "^22.1.0",
|
||||
"jsonwebtoken": "^9.0.0",
|
||||
@@ -173,13 +172,13 @@
|
||||
"passport-oauth2": "^1.8.0",
|
||||
"passport-slack-oauth2": "^1.2.0",
|
||||
"patch-package": "^7.0.2",
|
||||
"pg": "^8.14.1",
|
||||
"pg": "^8.12.0",
|
||||
"pg-tsquery": "^8.4.2",
|
||||
"pluralize": "^8.0.0",
|
||||
"png-chunks-extract": "^1.0.0",
|
||||
"polished": "^4.3.1",
|
||||
"prosemirror-codemark": "^0.4.2",
|
||||
"prosemirror-commands": "^1.7.0",
|
||||
"prosemirror-commands": "^1.6.2",
|
||||
"prosemirror-dropcursor": "^1.8.1",
|
||||
"prosemirror-gapcursor": "^1.3.2",
|
||||
"prosemirror-history": "^1.4.1",
|
||||
@@ -248,7 +247,7 @@
|
||||
"uuid": "^8.3.2",
|
||||
"validator": "13.12.0",
|
||||
"vaul": "^1.1.2",
|
||||
"vite": "^5.4.15",
|
||||
"vite": "^5.4.14",
|
||||
"vite-plugin-pwa": "^0.20.3",
|
||||
"winston": "^3.17.0",
|
||||
"ws": "^7.5.10",
|
||||
@@ -257,11 +256,11 @@
|
||||
"y-protocols": "^1.0.6",
|
||||
"yauzl": "^2.10.0",
|
||||
"yjs": "^13.6.1",
|
||||
"zod": "^3.24.2"
|
||||
"zod": "^3.23.8"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/cli": "^7.27.0",
|
||||
"@babel/preset-typescript": "^7.27.0",
|
||||
"@babel/cli": "^7.26.4",
|
||||
"@babel/preset-typescript": "^7.26.0",
|
||||
"@faker-js/faker": "^8.4.1",
|
||||
"@relative-ci/agent": "^4.2.14",
|
||||
"@testing-library/react": "^12.0.0",
|
||||
@@ -296,7 +295,7 @@
|
||||
"@types/markdown-it-emoji": "^2.0.4",
|
||||
"@types/mime-types": "^2.1.4",
|
||||
"@types/natural-sort": "^0.0.24",
|
||||
"@types/node": "20.17.27",
|
||||
"@types/node": "20.17.16",
|
||||
"@types/node-fetch": "^2.6.9",
|
||||
"@types/nodemailer": "^6.4.17",
|
||||
"@types/passport-oauth2": "^1.4.17",
|
||||
@@ -360,7 +359,7 @@
|
||||
"prettier": "^2.8.8",
|
||||
"react-refresh": "^0.14.2",
|
||||
"rimraf": "^2.5.4",
|
||||
"rollup-plugin-webpack-stats": "^2.0.3",
|
||||
"rollup-plugin-webpack-stats": "^2.0.1",
|
||||
"terser": "^5.39.0",
|
||||
"typescript": "^5.7.3",
|
||||
"vite-plugin-static-copy": "^0.17.0",
|
||||
@@ -378,4 +377,4 @@
|
||||
"prismjs": "1.30.0"
|
||||
},
|
||||
"version": "0.82.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ import { Hook, PluginManager } from "@server/utils/PluginManager";
|
||||
import config from "../plugin.json";
|
||||
import router from "./auth/email";
|
||||
|
||||
const enabled = !!(env.SMTP_HOST || env.SMTP_SERVICE) || env.isDevelopment;
|
||||
const enabled = !!env.SMTP_HOST || env.isDevelopment;
|
||||
|
||||
if (enabled) {
|
||||
PluginManager.add({
|
||||
|
||||
@@ -81,12 +81,7 @@ export const Notion = observer(() => {
|
||||
}, [t, appName, oauthError]);
|
||||
|
||||
return (
|
||||
<Button
|
||||
type="submit"
|
||||
onClick={() => redirectTo(authUrl)}
|
||||
disabled={!env.NOTION_CLIENT_ID}
|
||||
neutral
|
||||
>
|
||||
<Button type="submit" onClick={() => redirectTo(authUrl)} neutral>
|
||||
{t("Import")}…
|
||||
</Button>
|
||||
);
|
||||
|
||||
@@ -5,8 +5,8 @@ import environment from "@server/utils/environment";
|
||||
import { CannotUseWithout } from "@server/utils/validators";
|
||||
|
||||
class NotionPluginEnvironment extends Environment {
|
||||
@Public
|
||||
@IsOptional()
|
||||
@Public
|
||||
public NOTION_CLIENT_ID = this.toOptionalString(environment.NOTION_CLIENT_ID);
|
||||
|
||||
@IsOptional()
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
import {
|
||||
APIErrorCode,
|
||||
APIResponseError,
|
||||
Client,
|
||||
isFullPage,
|
||||
isFullPageOrDatabase,
|
||||
@@ -249,30 +247,19 @@ export class NotionClient {
|
||||
|
||||
private async fetchUsername(userId: string) {
|
||||
await this.limiter();
|
||||
try {
|
||||
const user = await this.client.users.retrieve({ user_id: userId });
|
||||
const user = await this.client.users.retrieve({ user_id: userId });
|
||||
|
||||
if (user.type === "person" || !user.bot.owner) {
|
||||
return user.name;
|
||||
}
|
||||
|
||||
// bot belongs to a user, get the user's name.
|
||||
if (user.bot.owner.type === "user" && isFullUser(user.bot.owner.user)) {
|
||||
return user.bot.owner.user.name;
|
||||
}
|
||||
|
||||
// bot belongs to a workspace, fallback to bot's name.
|
||||
if (user.type === "person" || !user.bot.owner) {
|
||||
return user.name;
|
||||
} catch (error) {
|
||||
// Handle the case where a user can't be found
|
||||
if (
|
||||
error instanceof APIResponseError &&
|
||||
error.code === APIErrorCode.ObjectNotFound
|
||||
) {
|
||||
return "Unknown";
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
|
||||
// bot belongs to a user, get the user's name.
|
||||
if (user.bot.owner.type === "user" && isFullUser(user.bot.owner.user)) {
|
||||
return user.bot.owner.user.name;
|
||||
}
|
||||
|
||||
// bot belongs to a workspace, fallback to bot's name.
|
||||
return user.name;
|
||||
}
|
||||
|
||||
private parseTitle(item: PageObjectResponse | DatabaseObjectResponse) {
|
||||
|
||||
@@ -1,22 +1,12 @@
|
||||
import { Node } from "prosemirror-model";
|
||||
import { ProsemirrorHelper } from "@server/models/helpers/ProsemirrorHelper";
|
||||
import nodesWithEmptyTextNode from "@server/test/fixtures/notion-page-with-empty-text-nodes.json";
|
||||
import allNodes from "@server/test/fixtures/notion-page.json";
|
||||
import data from "@server/test/fixtures/notion-page.json";
|
||||
import { NotionConverter, NotionPage } from "./NotionConverter";
|
||||
|
||||
describe("NotionConverter", () => {
|
||||
it("converts a page", () => {
|
||||
const response = NotionConverter.page({
|
||||
children: allNodes,
|
||||
} as NotionPage);
|
||||
|
||||
expect(response).toMatchSnapshot();
|
||||
expect(ProsemirrorHelper.toProsemirror(response)).toBeInstanceOf(Node);
|
||||
});
|
||||
|
||||
it("converts a page with empty text nodes", () => {
|
||||
const response = NotionConverter.page({
|
||||
children: nodesWithEmptyTextNode,
|
||||
children: data,
|
||||
} as NotionPage);
|
||||
|
||||
expect(response).toMatchSnapshot();
|
||||
|
||||
@@ -179,15 +179,11 @@ export class NotionConverter {
|
||||
}
|
||||
|
||||
private static bookmark(item: BookmarkBlockObjectResponse) {
|
||||
const caption = item.bookmark.caption
|
||||
.map(this.rich_text_to_plaintext)
|
||||
.join("");
|
||||
|
||||
return {
|
||||
type: "paragraph",
|
||||
content: [
|
||||
{
|
||||
text: caption || item.bookmark.url,
|
||||
text: item.bookmark.caption.map(this.rich_text_to_plaintext).join(""),
|
||||
type: "text",
|
||||
marks: [
|
||||
{
|
||||
@@ -225,14 +221,17 @@ export class NotionConverter {
|
||||
}
|
||||
|
||||
private static code(item: CodeBlockObjectResponse) {
|
||||
const text = item.code.rich_text.map(this.rich_text_to_plaintext).join("");
|
||||
|
||||
return {
|
||||
type: "code_fence",
|
||||
attrs: {
|
||||
language: item.code.language,
|
||||
},
|
||||
content: text ? [{ type: "text", text }] : undefined,
|
||||
content: [
|
||||
{
|
||||
type: "text",
|
||||
text: item.code.rich_text.map(this.rich_text_to_plaintext).join(""),
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
@@ -365,14 +364,12 @@ export class NotionConverter {
|
||||
private static equation(item: EquationBlockObjectResponse) {
|
||||
return {
|
||||
type: "math_block",
|
||||
content: item.equation.expression
|
||||
? [
|
||||
{
|
||||
type: "text",
|
||||
text: item.equation.expression,
|
||||
},
|
||||
]
|
||||
: undefined,
|
||||
content: [
|
||||
{
|
||||
type: "text",
|
||||
text: item.equation.expression,
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -1983,148 +1983,3 @@ exports[`NotionConverter converts a page 1`] = `
|
||||
"type": "doc",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`NotionConverter converts a page with empty text nodes 1`] = `
|
||||
{
|
||||
"content": [
|
||||
{
|
||||
"content": [],
|
||||
"type": "paragraph",
|
||||
},
|
||||
{
|
||||
"attrs": {
|
||||
"language": "javascript",
|
||||
},
|
||||
"content": undefined,
|
||||
"type": "code_fence",
|
||||
},
|
||||
{
|
||||
"content": [],
|
||||
"type": "paragraph",
|
||||
},
|
||||
{
|
||||
"content": [
|
||||
{
|
||||
"content": [
|
||||
{
|
||||
"text": "E",
|
||||
"type": "text",
|
||||
},
|
||||
],
|
||||
"type": "math_inline",
|
||||
},
|
||||
],
|
||||
"type": "paragraph",
|
||||
},
|
||||
{
|
||||
"content": [],
|
||||
"type": "paragraph",
|
||||
},
|
||||
{
|
||||
"content": [
|
||||
{
|
||||
"marks": [
|
||||
{
|
||||
"attrs": {
|
||||
"href": "http://github.com/outline/",
|
||||
},
|
||||
"type": "link",
|
||||
},
|
||||
],
|
||||
"text": "http://github.com/outline/",
|
||||
"type": "text",
|
||||
},
|
||||
],
|
||||
"type": "paragraph",
|
||||
},
|
||||
{
|
||||
"content": [],
|
||||
"type": "paragraph",
|
||||
},
|
||||
{
|
||||
"content": [
|
||||
{
|
||||
"marks": [
|
||||
{
|
||||
"attrs": {
|
||||
"href": "https://github.com/outline/outline",
|
||||
},
|
||||
"type": "link",
|
||||
},
|
||||
],
|
||||
"text": "https://github.com/outline/outline",
|
||||
"type": "text",
|
||||
},
|
||||
],
|
||||
"type": "paragraph",
|
||||
},
|
||||
{
|
||||
"content": [],
|
||||
"type": "paragraph",
|
||||
},
|
||||
{
|
||||
"content": undefined,
|
||||
"type": "math_block",
|
||||
},
|
||||
{
|
||||
"content": [],
|
||||
"type": "paragraph",
|
||||
},
|
||||
{
|
||||
"content": [
|
||||
{
|
||||
"marks": [
|
||||
{
|
||||
"attrs": {
|
||||
"href": "https://google.com",
|
||||
"title": null,
|
||||
},
|
||||
"type": "link",
|
||||
},
|
||||
],
|
||||
"text": "https://google.com",
|
||||
"type": "text",
|
||||
},
|
||||
],
|
||||
"type": "paragraph",
|
||||
},
|
||||
{
|
||||
"content": [],
|
||||
"type": "paragraph",
|
||||
},
|
||||
{
|
||||
"content": [
|
||||
{
|
||||
"marks": [
|
||||
{
|
||||
"attrs": {
|
||||
"href": "https://github.com/outline/outline",
|
||||
},
|
||||
"type": "link",
|
||||
},
|
||||
],
|
||||
"text": "https://github.com/outline/outline",
|
||||
"type": "text",
|
||||
},
|
||||
],
|
||||
"type": "paragraph",
|
||||
},
|
||||
{
|
||||
"content": [],
|
||||
"type": "paragraph",
|
||||
},
|
||||
{
|
||||
"attrs": {
|
||||
"href": "https://prod-files-secure.s3.us-west-2.amazonaws.com/2f3fcad6-fc32-434b-b6b2-a03ca7893c4d/49bfa851-95c1-458b-abb0-88ed591f7712/Empty_pdf.pdf",
|
||||
"title": "",
|
||||
},
|
||||
"type": "attachment",
|
||||
},
|
||||
{
|
||||
"content": [],
|
||||
"type": "paragraph",
|
||||
},
|
||||
],
|
||||
"type": "doc",
|
||||
}
|
||||
`;
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
import { HttpsProxyAgent } from "https-proxy-agent";
|
||||
import OAuth2Strategy, { Strategy } from "passport-oauth2";
|
||||
|
||||
export class OIDCStrategy extends Strategy {
|
||||
constructor(
|
||||
options: OAuth2Strategy.StrategyOptionsWithRequest,
|
||||
verify: OAuth2Strategy.VerifyFunctionWithRequest
|
||||
) {
|
||||
super(options, verify);
|
||||
|
||||
if (process.env.https_proxy) {
|
||||
const httpsProxyAgent = new HttpsProxyAgent(process.env.https_proxy);
|
||||
this._oauth2.setAgent(httpsProxyAgent);
|
||||
}
|
||||
}
|
||||
|
||||
authenticate(req: any, options: any) {
|
||||
options.originalQuery = req.query;
|
||||
super.authenticate(req, options);
|
||||
}
|
||||
|
||||
authorizationParams(options: any) {
|
||||
return {
|
||||
...(options.originalQuery || {}),
|
||||
...(super.authorizationParams?.(options) || {}),
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@ import passport from "@outlinewiki/koa-passport";
|
||||
import type { Context } from "koa";
|
||||
import Router from "koa-router";
|
||||
import get from "lodash/get";
|
||||
import { Strategy } from "passport-oauth2";
|
||||
import { slugifyDomain } from "@shared/utils/domains";
|
||||
import { parseEmail } from "@shared/utils/email";
|
||||
import accountProvisioner from "@server/commands/accountProvisioner";
|
||||
@@ -20,11 +21,24 @@ import {
|
||||
} from "@server/utils/passport";
|
||||
import config from "../../plugin.json";
|
||||
import env from "../env";
|
||||
import { OIDCStrategy } from "./OIDCStrategy";
|
||||
|
||||
const router = new Router();
|
||||
const scopes = env.OIDC_SCOPES.split(" ");
|
||||
|
||||
const authorizationParams = Strategy.prototype.authorizationParams;
|
||||
Strategy.prototype.authorizationParams = function (options) {
|
||||
return {
|
||||
...(options.originalQuery || {}),
|
||||
...(authorizationParams.bind(this)(options) || {}),
|
||||
};
|
||||
};
|
||||
|
||||
const authenticate = Strategy.prototype.authenticate;
|
||||
Strategy.prototype.authenticate = function (req, options) {
|
||||
options.originalQuery = req.query;
|
||||
authenticate.bind(this)(req, options);
|
||||
};
|
||||
|
||||
if (
|
||||
env.OIDC_CLIENT_ID &&
|
||||
env.OIDC_CLIENT_SECRET &&
|
||||
@@ -34,7 +48,7 @@ if (
|
||||
) {
|
||||
passport.use(
|
||||
config.id,
|
||||
new OIDCStrategy(
|
||||
new Strategy(
|
||||
{
|
||||
authorizationURL: env.OIDC_AUTH_URI,
|
||||
tokenURL: env.OIDC_TOKEN_URI,
|
||||
|
||||
@@ -33,7 +33,7 @@ export class Mailer {
|
||||
transporter: Transporter | undefined;
|
||||
|
||||
constructor() {
|
||||
if (env.SMTP_HOST || env.SMTP_SERVICE) {
|
||||
if (env.SMTP_HOST) {
|
||||
this.transporter = nodemailer.createTransport(this.getOptions());
|
||||
}
|
||||
if (useTestEmailService) {
|
||||
@@ -198,17 +198,6 @@ export class Mailer {
|
||||
};
|
||||
|
||||
private getOptions(): SMTPTransport.Options {
|
||||
// nodemailer will use the service config to determine host/port
|
||||
if (env.SMTP_SERVICE) {
|
||||
return {
|
||||
service: env.SMTP_SERVICE,
|
||||
auth: {
|
||||
user: env.SMTP_USERNAME,
|
||||
pass: env.SMTP_PASSWORD,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
name: env.SMTP_NAME,
|
||||
host: env.SMTP_HOST,
|
||||
|
||||
+3
-13
@@ -15,7 +15,7 @@ import {
|
||||
} from "class-validator";
|
||||
import uniq from "lodash/uniq";
|
||||
import { languages } from "@shared/i18n";
|
||||
import { CannotUseWith, CannotUseWithout } from "@server/utils/validators";
|
||||
import { CannotUseWithout } from "@server/utils/validators";
|
||||
import Deprecated from "./models/decorators/Deprecated";
|
||||
import { getArg } from "./utils/args";
|
||||
import { Public, PublicEnvironmentRegister } from "./utils/decorators/Public";
|
||||
@@ -291,19 +291,10 @@ export class Environment {
|
||||
/**
|
||||
* The host of your SMTP server for enabling emails.
|
||||
*/
|
||||
@CannotUseWith("SMTP_SERVICE")
|
||||
public SMTP_HOST = this.toOptionalString(environment.SMTP_HOST);
|
||||
|
||||
/**
|
||||
* The service name of a well-known SMTP service for nodemailer.
|
||||
* See https://community.nodemailer.com/2-0-0-beta/setup-smtp/well-known-services/
|
||||
*/
|
||||
@CannotUseWith("SMTP_HOST")
|
||||
public SMTP_SERVICE = this.toOptionalString(environment.SMTP_SERVICE);
|
||||
public SMTP_HOST = environment.SMTP_HOST;
|
||||
|
||||
@Public
|
||||
public EMAIL_ENABLED =
|
||||
!!(this.SMTP_HOST || this.SMTP_SERVICE) || this.isDevelopment;
|
||||
public EMAIL_ENABLED = !!this.SMTP_HOST || this.isDevelopment;
|
||||
|
||||
/**
|
||||
* Optional hostname of the client, used for identifying to the server
|
||||
@@ -316,7 +307,6 @@ export class Environment {
|
||||
*/
|
||||
@IsNumber()
|
||||
@IsOptional()
|
||||
@CannotUseWith("SMTP_SERVICE")
|
||||
public SMTP_PORT = this.toOptionalNumber(environment.SMTP_PORT);
|
||||
|
||||
/**
|
||||
|
||||
@@ -48,7 +48,9 @@ class Metrics {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
return ddMetrics.flush();
|
||||
return new Promise((resolve, reject) => {
|
||||
ddMetrics.flush(resolve, reject);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
"use strict";
|
||||
|
||||
/** @type {import('sequelize-cli').Migration} */
|
||||
module.exports = {
|
||||
async up(queryInterface, Sequelize) {
|
||||
await queryInterface.sequelize.transaction(async transaction => {
|
||||
await queryInterface.addColumn(
|
||||
"imports",
|
||||
"error",
|
||||
{
|
||||
type: Sequelize.STRING,
|
||||
allowNull: true,
|
||||
},
|
||||
{ transaction }
|
||||
);
|
||||
|
||||
await queryInterface.addColumn(
|
||||
"import_tasks",
|
||||
"error",
|
||||
{
|
||||
type: Sequelize.STRING,
|
||||
allowNull: true,
|
||||
},
|
||||
{ transaction }
|
||||
);
|
||||
});
|
||||
},
|
||||
|
||||
async down(queryInterface, Sequelize) {
|
||||
await queryInterface.sequelize.transaction(async transaction => {
|
||||
await queryInterface.removeColumn("imports", "error", { transaction });
|
||||
await queryInterface.removeColumn("import_tasks", "error", {
|
||||
transaction,
|
||||
});
|
||||
});
|
||||
},
|
||||
};
|
||||
@@ -1,5 +1,4 @@
|
||||
/* eslint-disable lines-between-class-members */
|
||||
import fractionalIndex from "fractional-index";
|
||||
import find from "lodash/find";
|
||||
import findIndex from "lodash/findIndex";
|
||||
import remove from "lodash/remove";
|
||||
@@ -12,8 +11,6 @@ import {
|
||||
InferAttributes,
|
||||
InferCreationAttributes,
|
||||
EmptyResultError,
|
||||
type CreateOptions,
|
||||
type UpdateOptions,
|
||||
} from "sequelize";
|
||||
import {
|
||||
Sequelize,
|
||||
@@ -35,8 +32,6 @@ import {
|
||||
BeforeDestroy,
|
||||
IsDate,
|
||||
AllowNull,
|
||||
BeforeCreate,
|
||||
BeforeUpdate,
|
||||
} from "sequelize-typescript";
|
||||
import isUUID from "validator/lib/isUUID";
|
||||
import type { CollectionSort, ProsemirrorData } from "@shared/types";
|
||||
@@ -46,9 +41,7 @@ import { sortNavigationNodes } from "@shared/utils/collections";
|
||||
import slugify from "@shared/utils/slugify";
|
||||
import { CollectionValidation } from "@shared/validations";
|
||||
import { ValidationError } from "@server/errors";
|
||||
import removeIndexCollision from "@server/utils/removeIndexCollision";
|
||||
import { generateUrlId } from "@server/utils/url";
|
||||
import { ValidateIndex } from "@server/validation";
|
||||
import Document from "./Document";
|
||||
import FileOperation from "./FileOperation";
|
||||
import Group from "./Group";
|
||||
@@ -224,8 +217,8 @@ class Collection extends ParanoidModel<
|
||||
color: string | null;
|
||||
|
||||
@Length({
|
||||
max: ValidateIndex.maxLength,
|
||||
msg: `index must be ${ValidateIndex.maxLength} characters or less`,
|
||||
max: 256,
|
||||
msg: `index must be 256 characters or less`,
|
||||
})
|
||||
@Column
|
||||
index: string | null;
|
||||
@@ -331,30 +324,6 @@ class Collection extends ParanoidModel<
|
||||
}
|
||||
}
|
||||
|
||||
@BeforeCreate
|
||||
static async setIndex(model: Collection, options: CreateOptions<Collection>) {
|
||||
if (model.index) {
|
||||
model.index = await removeIndexCollision(model.teamId, model.index, {
|
||||
transaction: options.transaction,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const firstCollectionForTeam = await this.findOne({
|
||||
where: {
|
||||
teamId: model.teamId,
|
||||
},
|
||||
order: [
|
||||
// using LC_COLLATE:"C" because we need byte order to drive the sorting
|
||||
Sequelize.literal('"collection"."index" collate "C"'),
|
||||
["updatedAt", "DESC"],
|
||||
],
|
||||
...options,
|
||||
});
|
||||
|
||||
model.index = fractionalIndex(null, firstCollectionForTeam?.index ?? null);
|
||||
}
|
||||
|
||||
@AfterCreate
|
||||
static async onAfterCreate(
|
||||
model: Collection,
|
||||
@@ -374,18 +343,6 @@ class Collection extends ParanoidModel<
|
||||
});
|
||||
}
|
||||
|
||||
@BeforeUpdate
|
||||
static async checkIndex(
|
||||
model: Collection,
|
||||
options: UpdateOptions<Collection>
|
||||
) {
|
||||
if (model.index && model.changed("index")) {
|
||||
model.index = await removeIndexCollision(model.teamId, model.index, {
|
||||
transaction: options.transaction,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// associations
|
||||
|
||||
@BelongsTo(() => FileOperation, "importId")
|
||||
|
||||
@@ -60,9 +60,6 @@ class Import<T extends ImportableIntegrationService> extends ParanoidModel<
|
||||
@Column(DataType.INTEGER)
|
||||
documentCount: number;
|
||||
|
||||
@Column
|
||||
error: string | null;
|
||||
|
||||
// associations
|
||||
|
||||
@BelongsTo(() => Integration, "integrationId")
|
||||
|
||||
@@ -45,9 +45,6 @@ class ImportTask<T extends ImportableIntegrationService> extends IdModel<
|
||||
@Column(DataType.JSONB)
|
||||
output: ImportTaskOutput | null;
|
||||
|
||||
@Column
|
||||
error: string | null;
|
||||
|
||||
// associations
|
||||
|
||||
@BelongsTo(() => Import, "importId")
|
||||
|
||||
@@ -190,7 +190,7 @@ class Team extends ParanoidModel<
|
||||
* @return {boolean} Whether to show email login options
|
||||
*/
|
||||
get emailSigninEnabled(): boolean {
|
||||
return this.guestSignin && env.EMAIL_ENABLED;
|
||||
return this.guestSignin && (!!env.SMTP_HOST || env.isDevelopment);
|
||||
}
|
||||
|
||||
get url() {
|
||||
|
||||
@@ -9,7 +9,7 @@ import NotificationHelper from "./NotificationHelper";
|
||||
|
||||
describe("NotificationHelper", () => {
|
||||
describe("getCommentNotificationRecipients", () => {
|
||||
it("should only return users who have notification enabled for comment creation and are subscribed to the document in case of new thread", async () => {
|
||||
it("should return users who have notification enabled for comment creation and are subscribed to the document in case of parent comment", async () => {
|
||||
const documentAuthor = await buildUser();
|
||||
const document = await buildDocument({
|
||||
userId: documentAuthor.id,
|
||||
@@ -54,7 +54,7 @@ describe("NotificationHelper", () => {
|
||||
expect(recipients[0].id).toEqual(notificationEnabledUser.id);
|
||||
});
|
||||
|
||||
it("should only return users who have notification enabled for comment creation and are in the thread in case of child comment", async () => {
|
||||
it("should return users who have notification enabled for comment creation and are in the thread in case of child comment", async () => {
|
||||
const documentAuthor = await buildUser();
|
||||
const document = await buildDocument({
|
||||
userId: documentAuthor.id,
|
||||
@@ -112,104 +112,32 @@ describe("NotificationHelper", () => {
|
||||
expect(recipients.length).toEqual(1);
|
||||
expect(recipients[0].id).toEqual(notificationEnabledUserInThread.id);
|
||||
});
|
||||
|
||||
it("should not return users who have notification disabled for comment creation and are in the thread in case of child comment", async () => {
|
||||
const documentAuthor = await buildUser();
|
||||
const document = await buildDocument({
|
||||
userId: documentAuthor.id,
|
||||
teamId: documentAuthor.teamId,
|
||||
});
|
||||
const notificationEnabledUserInThread = await buildUser({
|
||||
teamId: document.teamId,
|
||||
notificationSettings: { [NotificationEventType.CreateComment]: false },
|
||||
});
|
||||
const notificationEnabledUserNotInThread = await buildUser({
|
||||
teamId: document.teamId,
|
||||
notificationSettings: { [NotificationEventType.CreateComment]: true },
|
||||
});
|
||||
const notificationDisabledUser = await buildUser({
|
||||
teamId: document.teamId,
|
||||
notificationSettings: {
|
||||
[NotificationEventType.CreateComment]: false,
|
||||
},
|
||||
});
|
||||
await Promise.all([
|
||||
buildSubscription({
|
||||
userId: documentAuthor.id,
|
||||
documentId: document.id,
|
||||
}),
|
||||
buildSubscription({
|
||||
userId: notificationEnabledUserInThread.id,
|
||||
documentId: document.id,
|
||||
}),
|
||||
buildSubscription({
|
||||
userId: notificationEnabledUserNotInThread.id,
|
||||
documentId: document.id,
|
||||
}),
|
||||
buildSubscription({
|
||||
userId: notificationDisabledUser.id,
|
||||
documentId: document.id,
|
||||
}),
|
||||
]);
|
||||
const parentComment = await buildComment({
|
||||
documentId: document.id,
|
||||
userId: notificationEnabledUserInThread.id,
|
||||
});
|
||||
const childComment = await buildComment({
|
||||
documentId: document.id,
|
||||
userId: documentAuthor.id,
|
||||
parentCommentId: parentComment.id,
|
||||
});
|
||||
|
||||
const recipients =
|
||||
await NotificationHelper.getCommentNotificationRecipients(
|
||||
document,
|
||||
childComment,
|
||||
childComment.createdById
|
||||
);
|
||||
|
||||
expect(recipients.length).toEqual(0);
|
||||
});
|
||||
|
||||
it("should return users who have notification enabled and are in the thread but not explicitly subscribed to document", async () => {
|
||||
const documentAuthor = await buildUser();
|
||||
const document = await buildDocument({
|
||||
userId: documentAuthor.id,
|
||||
teamId: documentAuthor.teamId,
|
||||
});
|
||||
const notificationEnabledUserInThread = await buildUser({
|
||||
teamId: document.teamId,
|
||||
notificationSettings: { [NotificationEventType.CreateComment]: true },
|
||||
});
|
||||
await buildUser({
|
||||
teamId: document.teamId,
|
||||
notificationSettings: {
|
||||
[NotificationEventType.CreateComment]: false,
|
||||
},
|
||||
});
|
||||
const parentComment = await buildComment({
|
||||
documentId: document.id,
|
||||
userId: notificationEnabledUserInThread.id,
|
||||
});
|
||||
const childComment = await buildComment({
|
||||
documentId: document.id,
|
||||
userId: documentAuthor.id,
|
||||
parentCommentId: parentComment.id,
|
||||
});
|
||||
|
||||
const recipients =
|
||||
await NotificationHelper.getCommentNotificationRecipients(
|
||||
document,
|
||||
childComment,
|
||||
childComment.createdById
|
||||
);
|
||||
|
||||
expect(recipients.length).toEqual(1);
|
||||
expect(recipients[0].id).toEqual(notificationEnabledUserInThread.id);
|
||||
});
|
||||
});
|
||||
|
||||
describe("getDocumentNotificationRecipients", () => {
|
||||
it("should return all users who have notification enabled for the event", async () => {
|
||||
const documentAuthor = await buildUser();
|
||||
const document = await buildDocument({
|
||||
userId: documentAuthor.id,
|
||||
teamId: documentAuthor.teamId,
|
||||
});
|
||||
const notificationEnabledUser = await buildUser({
|
||||
teamId: document.teamId,
|
||||
notificationSettings: { [NotificationEventType.UpdateDocument]: true },
|
||||
});
|
||||
|
||||
const recipients =
|
||||
await NotificationHelper.getDocumentNotificationRecipients({
|
||||
document,
|
||||
notificationType: NotificationEventType.UpdateDocument,
|
||||
onlySubscribers: false,
|
||||
actorId: documentAuthor.id,
|
||||
});
|
||||
|
||||
expect(recipients.length).toEqual(1);
|
||||
expect(recipients[0].id).toEqual(notificationEnabledUser.id);
|
||||
});
|
||||
|
||||
it("should return users who have subscribed to the document", async () => {
|
||||
const documentAuthor = await buildUser();
|
||||
const document = await buildDocument({
|
||||
@@ -222,17 +150,11 @@ describe("NotificationHelper", () => {
|
||||
documentId: document.id,
|
||||
});
|
||||
|
||||
const deletedUser = await buildUser({ teamId: document.teamId });
|
||||
await buildSubscription({
|
||||
userId: deletedUser.id,
|
||||
documentId: document.id,
|
||||
});
|
||||
await deletedUser.destroy();
|
||||
|
||||
const recipients =
|
||||
await NotificationHelper.getDocumentNotificationRecipients({
|
||||
document,
|
||||
notificationType: NotificationEventType.UpdateDocument,
|
||||
onlySubscribers: true,
|
||||
actorId: documentAuthor.id,
|
||||
});
|
||||
|
||||
@@ -256,6 +178,7 @@ describe("NotificationHelper", () => {
|
||||
await NotificationHelper.getDocumentNotificationRecipients({
|
||||
document,
|
||||
notificationType: NotificationEventType.UpdateDocument,
|
||||
onlySubscribers: true,
|
||||
actorId: documentAuthor.id,
|
||||
});
|
||||
|
||||
@@ -293,6 +216,7 @@ describe("NotificationHelper", () => {
|
||||
await NotificationHelper.getDocumentNotificationRecipients({
|
||||
document,
|
||||
notificationType: NotificationEventType.UpdateDocument,
|
||||
onlySubscribers: true,
|
||||
actorId: documentAuthor.id,
|
||||
});
|
||||
|
||||
@@ -311,19 +235,20 @@ describe("NotificationHelper", () => {
|
||||
});
|
||||
const notificationEnabledUser = await buildUser({
|
||||
teamId: document.teamId,
|
||||
notificationSettings: { [NotificationEventType.PublishDocument]: true },
|
||||
notificationSettings: { [NotificationEventType.UpdateDocument]: true },
|
||||
});
|
||||
// suspended user
|
||||
await buildUser({
|
||||
suspendedAt: new Date(),
|
||||
teamId: document.teamId,
|
||||
notificationSettings: { [NotificationEventType.PublishDocument]: true },
|
||||
notificationSettings: { [NotificationEventType.UpdateDocument]: true },
|
||||
});
|
||||
|
||||
const recipients =
|
||||
await NotificationHelper.getDocumentNotificationRecipients({
|
||||
document,
|
||||
notificationType: NotificationEventType.PublishDocument,
|
||||
notificationType: NotificationEventType.UpdateDocument,
|
||||
onlySubscribers: false,
|
||||
actorId: documentAuthor.id,
|
||||
});
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ import {
|
||||
Comment,
|
||||
View,
|
||||
} from "@server/models";
|
||||
import { canUserAccessDocument } from "@server/utils/permissions";
|
||||
import { can } from "@server/policies";
|
||||
import { ProsemirrorHelper } from "./ProsemirrorHelper";
|
||||
|
||||
export default class NotificationHelper {
|
||||
@@ -60,12 +60,18 @@ export default class NotificationHelper {
|
||||
comment: Comment,
|
||||
actorId: string
|
||||
): Promise<User[]> => {
|
||||
let recipients: User[];
|
||||
let recipients = await this.getDocumentNotificationRecipients({
|
||||
document,
|
||||
notificationType: NotificationEventType.CreateComment,
|
||||
onlySubscribers: !comment.parentCommentId,
|
||||
actorId,
|
||||
});
|
||||
|
||||
// If this is a reply to another comment, we want to notify all users
|
||||
// that are involved in the thread of this comment (i.e. the original
|
||||
// comment and all replies to it).
|
||||
if (comment.parentCommentId) {
|
||||
recipients = recipients.filter((recipient) =>
|
||||
recipient.subscribedToEventType(NotificationEventType.CreateComment)
|
||||
);
|
||||
|
||||
if (recipients.length > 0 && comment.parentCommentId) {
|
||||
const contextComments = await Comment.findAll({
|
||||
attributes: ["createdById", "data"],
|
||||
where: {
|
||||
@@ -89,37 +95,13 @@ export default class NotificationHelper {
|
||||
const userIdsInThread = uniq([
|
||||
...createdUserIdsInThread,
|
||||
...mentionedUserIdsInThread,
|
||||
]).filter((userId) => userId !== actorId);
|
||||
|
||||
recipients = await User.findAll({
|
||||
where: {
|
||||
id: {
|
||||
[Op.in]: userIdsInThread,
|
||||
},
|
||||
teamId: document.teamId,
|
||||
},
|
||||
});
|
||||
|
||||
recipients = recipients.filter((recipient) =>
|
||||
recipient.subscribedToEventType(NotificationEventType.CreateComment)
|
||||
);
|
||||
} else {
|
||||
recipients = await this.getDocumentNotificationRecipients({
|
||||
document,
|
||||
notificationType: NotificationEventType.CreateComment,
|
||||
actorId,
|
||||
// We will check below, this just prevents duplicate queries
|
||||
disableAccessCheck: true,
|
||||
});
|
||||
]);
|
||||
recipients = recipients.filter((r) => userIdsInThread.includes(r.id));
|
||||
}
|
||||
|
||||
const filtered: User[] = [];
|
||||
|
||||
for (const recipient of recipients) {
|
||||
if (recipient.isSuspended) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// If this recipient has viewed the document since the comment was made
|
||||
// then we can avoid sending them a useless notification, yay.
|
||||
const view = await View.findOne({
|
||||
@@ -137,13 +119,7 @@ export default class NotificationHelper {
|
||||
"processor",
|
||||
`suppressing notification to ${recipient.id} because doc viewed`
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check the recipient has access to the collection this document is in. Just
|
||||
// because they are subscribed doesn't mean they still have access to read
|
||||
// the document.
|
||||
if (await canUserAccessDocument(recipient, document.id)) {
|
||||
} else {
|
||||
filtered.push(recipient);
|
||||
}
|
||||
}
|
||||
@@ -156,77 +132,74 @@ export default class NotificationHelper {
|
||||
*
|
||||
* @param document The document to get recipients for.
|
||||
* @param notificationType The notification type for which to find the recipients.
|
||||
* @param onlySubscribers Whether to consider only the users who have active subscription to the document.
|
||||
* @param actorId The id of the user that performed the action.
|
||||
* @param disableAccessCheck Whether to disable the access check for the document.
|
||||
* @returns A list of recipients
|
||||
*/
|
||||
public static getDocumentNotificationRecipients = async ({
|
||||
document,
|
||||
notificationType,
|
||||
onlySubscribers,
|
||||
actorId,
|
||||
disableAccessCheck = false,
|
||||
}: {
|
||||
document: Document;
|
||||
notificationType: NotificationEventType;
|
||||
onlySubscribers: boolean;
|
||||
actorId: string;
|
||||
disableAccessCheck?: boolean;
|
||||
}): Promise<User[]> => {
|
||||
let recipients: User[];
|
||||
|
||||
if (notificationType === NotificationEventType.PublishDocument) {
|
||||
recipients = await User.findAll({
|
||||
where: {
|
||||
id: {
|
||||
[Op.ne]: actorId,
|
||||
},
|
||||
teamId: document.teamId,
|
||||
notificationSettings: {
|
||||
[notificationType]: true,
|
||||
},
|
||||
// First find all the users that have notifications enabled for this event
|
||||
// type at all and aren't the one that performed the action.
|
||||
let recipients = await User.findAll({
|
||||
where: {
|
||||
id: {
|
||||
[Op.ne]: actorId,
|
||||
},
|
||||
});
|
||||
} else {
|
||||
teamId: document.teamId,
|
||||
},
|
||||
});
|
||||
|
||||
recipients = recipients.filter((recipient) =>
|
||||
recipient.subscribedToEventType(notificationType)
|
||||
);
|
||||
|
||||
// Filter further to only those that have a subscription to the document…
|
||||
if (onlySubscribers) {
|
||||
const subscriptions = await Subscription.findAll({
|
||||
attributes: ["userId"],
|
||||
where: {
|
||||
userId: {
|
||||
[Op.ne]: actorId,
|
||||
},
|
||||
userId: recipients.map((recipient) => recipient.id),
|
||||
event: SubscriptionType.Document,
|
||||
[Op.or]: [
|
||||
{ collectionId: document.collectionId },
|
||||
{ documentId: document.id },
|
||||
],
|
||||
},
|
||||
include: [
|
||||
{
|
||||
association: "user",
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
recipients = subscriptions.map((s) => s.user);
|
||||
}
|
||||
const subscribedUserIds = subscriptions.map(
|
||||
(subscription) => subscription.userId
|
||||
);
|
||||
|
||||
recipients = recipients.filter((recipient) =>
|
||||
recipient.subscribedToEventType(notificationType)
|
||||
);
|
||||
recipients = recipients.filter((recipient) =>
|
||||
subscribedUserIds.includes(recipient.id)
|
||||
);
|
||||
}
|
||||
|
||||
const filtered = [];
|
||||
|
||||
for (const recipient of recipients) {
|
||||
if (recipient.isSuspended) {
|
||||
if (!recipient.email || recipient.isSuspended) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check the recipient has access to the collection this document is in. Just
|
||||
// because they are subscribed doesn't mean they still have access to read
|
||||
// the document.
|
||||
if (
|
||||
disableAccessCheck ||
|
||||
(await canUserAccessDocument(recipient, document.id))
|
||||
) {
|
||||
const doc = await Document.findByPk(document.id, {
|
||||
userId: recipient.id,
|
||||
});
|
||||
|
||||
if (can(recipient, "read", doc)) {
|
||||
filtered.push(recipient);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,6 @@ export default function presentImport(
|
||||
service: importModel.service,
|
||||
state: importModel.state,
|
||||
documentCount: importModel.documentCount,
|
||||
error: importModel.error,
|
||||
createdBy: presentUser(importModel.createdBy),
|
||||
createdById: importModel.createdById,
|
||||
createdAt: importModel.createdAt,
|
||||
|
||||
@@ -1,85 +1,44 @@
|
||||
import { Op } from "sequelize";
|
||||
import { GroupUser } from "@server/models";
|
||||
import {
|
||||
CollectionGroupEvent,
|
||||
CollectionUserEvent,
|
||||
DocumentGroupEvent,
|
||||
DocumentUserEvent,
|
||||
Event,
|
||||
} from "@server/types";
|
||||
import CollectionSubscriptionRemoveUserTask from "../tasks/CollectionSubscriptionRemoveUserTask";
|
||||
import DocumentSubscriptionRemoveUserTask from "../tasks/DocumentSubscriptionRemoveUserTask";
|
||||
import { DocumentGroupEvent, DocumentUserEvent, Event } from "@server/types";
|
||||
import DocumentSubscriptionTask from "../tasks/DocumentSubscriptionTask";
|
||||
import BaseProcessor from "./BaseProcessor";
|
||||
|
||||
type ReceivedEvent =
|
||||
| CollectionUserEvent
|
||||
| CollectionGroupEvent
|
||||
| DocumentUserEvent
|
||||
| DocumentGroupEvent;
|
||||
|
||||
export default class DocumentSubscriptionProcessor extends BaseProcessor {
|
||||
static applicableEvents: Event["name"][] = [
|
||||
"collections.remove_user",
|
||||
"collections.remove_group",
|
||||
"documents.remove_user",
|
||||
"documents.remove_group",
|
||||
];
|
||||
|
||||
async perform(event: ReceivedEvent) {
|
||||
async perform(event: DocumentUserEvent | DocumentGroupEvent) {
|
||||
switch (event.name) {
|
||||
case "collections.remove_user": {
|
||||
await CollectionSubscriptionRemoveUserTask.schedule(event);
|
||||
return;
|
||||
}
|
||||
|
||||
case "collections.remove_group":
|
||||
return this.handleRemoveGroupFromCollection(event);
|
||||
|
||||
case "documents.remove_user": {
|
||||
await DocumentSubscriptionRemoveUserTask.schedule(event);
|
||||
await DocumentSubscriptionTask.schedule(event);
|
||||
return;
|
||||
}
|
||||
|
||||
case "documents.remove_group":
|
||||
return this.handleRemoveGroupFromDocument(event);
|
||||
return this.handleGroup(event);
|
||||
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
||||
private async handleRemoveGroupFromCollection(event: CollectionGroupEvent) {
|
||||
private async handleGroup(event: DocumentGroupEvent) {
|
||||
await GroupUser.findAllInBatches<GroupUser>(
|
||||
{
|
||||
where: {
|
||||
groupId: event.modelId,
|
||||
userId: {
|
||||
[Op.ne]: event.actorId,
|
||||
},
|
||||
},
|
||||
batchLimit: 10,
|
||||
},
|
||||
async (groupUsers) => {
|
||||
await Promise.all(
|
||||
groupUsers.map((groupUser) =>
|
||||
CollectionSubscriptionRemoveUserTask.schedule({
|
||||
...event,
|
||||
name: "collections.remove_user",
|
||||
userId: groupUser.userId,
|
||||
})
|
||||
)
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
private async handleRemoveGroupFromDocument(event: DocumentGroupEvent) {
|
||||
await GroupUser.findAllInBatches<GroupUser>(
|
||||
{
|
||||
where: {
|
||||
groupId: event.modelId,
|
||||
},
|
||||
batchLimit: 10,
|
||||
},
|
||||
async (groupUsers) => {
|
||||
await Promise.all(
|
||||
groupUsers.map((groupUser) =>
|
||||
DocumentSubscriptionRemoveUserTask.schedule({
|
||||
DocumentSubscriptionTask.schedule({
|
||||
...event,
|
||||
name: "documents.remove_user",
|
||||
userId: groupUser.userId,
|
||||
|
||||
@@ -49,46 +49,33 @@ export default abstract class ImportsProcessor<
|
||||
* @param event The import event
|
||||
*/
|
||||
public async perform(event: ImportEvent) {
|
||||
try {
|
||||
await sequelize.transaction(async (transaction) => {
|
||||
const importModel = await Import.findByPk<Import<T>>(event.modelId, {
|
||||
rejectOnEmpty: true,
|
||||
paranoid: false,
|
||||
transaction,
|
||||
lock: transaction.LOCK.UPDATE,
|
||||
});
|
||||
|
||||
if (
|
||||
!this.canProcess(importModel) ||
|
||||
importModel.state === ImportState.Errored ||
|
||||
importModel.state === ImportState.Canceled
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (event.name) {
|
||||
case "imports.create":
|
||||
return this.onCreation(importModel, transaction);
|
||||
|
||||
case "imports.processed":
|
||||
return this.onProcessed(importModel, transaction);
|
||||
|
||||
case "imports.delete":
|
||||
return this.onDeletion(importModel, event, transaction);
|
||||
}
|
||||
await sequelize.transaction(async (transaction) => {
|
||||
const importModel = await Import.findByPk<Import<T>>(event.modelId, {
|
||||
rejectOnEmpty: true,
|
||||
paranoid: false,
|
||||
transaction,
|
||||
lock: transaction.LOCK.UPDATE,
|
||||
});
|
||||
} catch (err) {
|
||||
if (event.name !== "imports.delete" && err instanceof Error) {
|
||||
const importModel = await Import.findByPk<Import<T>>(event.modelId, {
|
||||
rejectOnEmpty: true,
|
||||
paranoid: false,
|
||||
});
|
||||
importModel.error = truncate(err.message, { length: 255 });
|
||||
await importModel.save();
|
||||
|
||||
if (
|
||||
!this.canProcess(importModel) ||
|
||||
importModel.state === ImportState.Errored ||
|
||||
importModel.state === ImportState.Canceled
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
throw err; // throw error for retry.
|
||||
}
|
||||
switch (event.name) {
|
||||
case "imports.create":
|
||||
return this.onCreation(importModel, transaction);
|
||||
|
||||
case "imports.processed":
|
||||
return this.onProcessed(importModel, transaction);
|
||||
|
||||
case "imports.delete":
|
||||
return this.onDeletion(importModel, event, transaction);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public async onFailed(event: ImportEvent) {
|
||||
@@ -186,7 +173,6 @@ export default abstract class ImportsProcessor<
|
||||
}
|
||||
|
||||
importModel.state = ImportState.Completed;
|
||||
importModel.error = null; // unset any error from previous attempts.
|
||||
await importModel.saveWithCtx(
|
||||
createContext({
|
||||
user: importModel.createdBy,
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { JobOptions } from "bull";
|
||||
import chunk from "lodash/chunk";
|
||||
import truncate from "lodash/truncate";
|
||||
import uniqBy from "lodash/uniqBy";
|
||||
import { Fragment, Node } from "prosemirror-model";
|
||||
import { Transaction, WhereOptions } from "sequelize";
|
||||
@@ -64,29 +63,20 @@ export default abstract class APIImportTask<
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
switch (importTask.state) {
|
||||
case ImportTaskState.Created: {
|
||||
importTask.state = ImportTaskState.InProgress;
|
||||
importTask = await importTask.save();
|
||||
return await this.onProcess(importTask);
|
||||
}
|
||||
|
||||
case ImportTaskState.InProgress:
|
||||
return await this.onProcess(importTask);
|
||||
|
||||
case ImportTaskState.Completed:
|
||||
return await this.onCompletion(importTask);
|
||||
|
||||
default:
|
||||
}
|
||||
} catch (err) {
|
||||
if (err instanceof Error) {
|
||||
importTask.error = truncate(err.message, { length: 255 });
|
||||
await importTask.save();
|
||||
switch (importTask.state) {
|
||||
case ImportTaskState.Created: {
|
||||
importTask.state = ImportTaskState.InProgress;
|
||||
importTask = await importTask.save();
|
||||
return await this.onProcess(importTask);
|
||||
}
|
||||
|
||||
throw err; // throw error for retry.
|
||||
case ImportTaskState.InProgress:
|
||||
return await this.onProcess(importTask);
|
||||
|
||||
case ImportTaskState.Completed:
|
||||
return await this.onCompletion(importTask);
|
||||
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,7 +108,6 @@ export default abstract class APIImportTask<
|
||||
await importTask.save({ transaction });
|
||||
|
||||
const associatedImport = importTask.import;
|
||||
associatedImport.error = importTask.error; // copy error from ImportTask that caused the failure.
|
||||
associatedImport.state = ImportState.Errored;
|
||||
await associatedImport.saveWithCtx(
|
||||
createContext({
|
||||
@@ -166,7 +155,6 @@ export default abstract class APIImportTask<
|
||||
|
||||
importTask.output = taskOutputWithReplacements;
|
||||
importTask.state = ImportTaskState.Completed;
|
||||
importTask.error = null; // unset any error from previous attempts.
|
||||
await importTask.save({ transaction });
|
||||
|
||||
const associatedImport = importTask.import;
|
||||
|
||||
@@ -41,7 +41,6 @@ export default class CleanupOldImportsTask extends BaseTask<Props> {
|
||||
],
|
||||
batchLimit: 50,
|
||||
totalLimit: maxImportsPerTask,
|
||||
paranoid: false,
|
||||
},
|
||||
async (imports) => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
import { Transaction } from "sequelize";
|
||||
import { SubscriptionType } from "@shared/types";
|
||||
import { createContext } from "@server/context";
|
||||
import Logger from "@server/logging/Logger";
|
||||
import { Collection, Subscription, User } from "@server/models";
|
||||
import { can } from "@server/policies";
|
||||
import { sequelize } from "@server/storage/database";
|
||||
import { CollectionUserEvent } from "@server/types";
|
||||
import BaseTask from "./BaseTask";
|
||||
|
||||
export default class CollectionSubscriptionRemoveUserTask extends BaseTask<CollectionUserEvent> {
|
||||
public async perform(event: CollectionUserEvent) {
|
||||
const user = await User.findByPk(event.userId);
|
||||
|
||||
if (!user) {
|
||||
return;
|
||||
}
|
||||
|
||||
const collection = await Collection.scope({
|
||||
method: ["withMembership", user.id],
|
||||
}).findByPk(event.collectionId);
|
||||
|
||||
if (can(user, "read", collection)) {
|
||||
Logger.debug(
|
||||
"task",
|
||||
`Skip unsubscribing user ${user.id} as they have permission to the collection ${event.collectionId} through other means`
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
await sequelize.transaction(async (transaction) => {
|
||||
const subscription = await Subscription.findOne({
|
||||
where: {
|
||||
userId: user.id,
|
||||
collectionId: event.collectionId,
|
||||
event: SubscriptionType.Document,
|
||||
},
|
||||
transaction,
|
||||
lock: Transaction.LOCK.UPDATE,
|
||||
});
|
||||
|
||||
await subscription?.destroyWithCtx(
|
||||
createContext({
|
||||
user,
|
||||
authType: event.authType,
|
||||
ip: event.ip,
|
||||
transaction,
|
||||
})
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -54,6 +54,7 @@ export default class DocumentPublishedNotificationsTask extends BaseTask<Documen
|
||||
await NotificationHelper.getDocumentNotificationRecipients({
|
||||
document,
|
||||
notificationType: NotificationEventType.PublishDocument,
|
||||
onlySubscribers: false,
|
||||
actorId: document.lastModifiedById,
|
||||
})
|
||||
).filter((recipient) => !userIdsMentioned.includes(recipient.id));
|
||||
|
||||
+2
-2
@@ -8,11 +8,11 @@ import { sequelize } from "@server/storage/database";
|
||||
import { DocumentUserEvent } from "@server/types";
|
||||
import BaseTask from "./BaseTask";
|
||||
|
||||
export default class DocumentSubscriptionRemoveUserTask extends BaseTask<DocumentUserEvent> {
|
||||
export default class DocumentSubscriptionTask extends BaseTask<DocumentUserEvent> {
|
||||
public async perform(event: DocumentUserEvent) {
|
||||
const user = await User.findByPk(event.userId);
|
||||
|
||||
if (!user) {
|
||||
if (!user || event.name !== "documents.remove_user") {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -56,13 +56,11 @@ export default class ErrorTimedOutImportsTask extends BaseTask<Props> {
|
||||
|
||||
await sequelize.transaction(async (transaction) => {
|
||||
importTask.state = ImportTaskState.Errored;
|
||||
importTask.error = "Timed out";
|
||||
await importTask.save({ transaction });
|
||||
|
||||
// this import could have been seen before in another import_task.
|
||||
if (!importsErrored[associatedImport.id]) {
|
||||
associatedImport.state = ImportState.Errored;
|
||||
associatedImport.error = "Timed out";
|
||||
await associatedImport.save({ transaction });
|
||||
importsErrored[associatedImport.id] = true;
|
||||
}
|
||||
|
||||
@@ -76,6 +76,7 @@ export default class RevisionCreatedNotificationsTask extends BaseTask<RevisionE
|
||||
await NotificationHelper.getDocumentNotificationRecipients({
|
||||
document,
|
||||
notificationType: NotificationEventType.UpdateDocument,
|
||||
onlySubscribers: true,
|
||||
actorId: document.lastModifiedById,
|
||||
})
|
||||
).filter((recipient) => !userIdsMentioned.includes(recipient.id));
|
||||
|
||||
@@ -1327,32 +1327,6 @@ describe("#collections.create", () => {
|
||||
expect(body.policies[0].abilities.read).toBeTruthy();
|
||||
});
|
||||
|
||||
it("should ensure unique index across the team", async () => {
|
||||
const team = await buildTeam();
|
||||
const [adminA, adminB] = await Promise.all([
|
||||
buildAdmin({ teamId: team.id }),
|
||||
buildAdmin({ teamId: team.id }),
|
||||
]);
|
||||
|
||||
const resA = await server.post("/api/collections.create", {
|
||||
body: {
|
||||
token: adminA.getJwtToken(),
|
||||
name: "Test A",
|
||||
},
|
||||
});
|
||||
const resB = await server.post("/api/collections.create", {
|
||||
body: {
|
||||
token: adminB.getJwtToken(),
|
||||
name: "Test B",
|
||||
},
|
||||
});
|
||||
const [bodyA, bodyB] = await Promise.all([resA.json(), resB.json()]);
|
||||
|
||||
expect(resA.status).toEqual(200);
|
||||
expect(resB.status).toEqual(200);
|
||||
expect(bodyA.data.index).not.toEqual(bodyB.data.index);
|
||||
});
|
||||
|
||||
it("if index collision, should updated index of other collection", async () => {
|
||||
const user = await buildUser();
|
||||
const createdCollectionAResponse = await server.post(
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import fractionalIndex from "fractional-index";
|
||||
import invariant from "invariant";
|
||||
import Router from "koa-router";
|
||||
import { Sequelize, Op, WhereOptions } from "sequelize";
|
||||
@@ -41,6 +42,7 @@ import {
|
||||
import { APIContext } from "@server/types";
|
||||
import { RateLimiterStrategy } from "@server/utils/RateLimiter";
|
||||
import { collectionIndexing } from "@server/utils/indexing";
|
||||
import removeIndexCollision from "@server/utils/removeIndexCollision";
|
||||
import pagination from "../middlewares/pagination";
|
||||
import * as T from "./schema";
|
||||
|
||||
@@ -53,21 +55,23 @@ router.post(
|
||||
transaction(),
|
||||
async (ctx: APIContext<T.CollectionsCreateReq>) => {
|
||||
const { transaction } = ctx.state;
|
||||
const {
|
||||
name,
|
||||
color,
|
||||
description,
|
||||
data,
|
||||
permission,
|
||||
sharing,
|
||||
icon,
|
||||
sort,
|
||||
index,
|
||||
} = ctx.input.body;
|
||||
const { name, color, description, data, permission, sharing, icon, sort } =
|
||||
ctx.input.body;
|
||||
let { index } = ctx.input.body;
|
||||
|
||||
const { user } = ctx.state.auth;
|
||||
authorize(user, "createCollection", user.team);
|
||||
|
||||
if (index) {
|
||||
index = await removeIndexCollision(user.teamId, index, { transaction });
|
||||
} else {
|
||||
const first = await Collection.findFirstCollectionForUser(user, {
|
||||
attributes: ["id", "index"],
|
||||
transaction,
|
||||
});
|
||||
index = fractionalIndex(null, first ? first.index : null);
|
||||
}
|
||||
|
||||
const collection = Collection.build({
|
||||
name,
|
||||
content: data,
|
||||
@@ -955,16 +959,18 @@ router.post(
|
||||
transaction(),
|
||||
async (ctx: APIContext<T.CollectionsMoveReq>) => {
|
||||
const { transaction } = ctx.state;
|
||||
const { id, index } = ctx.input.body;
|
||||
const { id } = ctx.input.body;
|
||||
let { index } = ctx.input.body;
|
||||
const { user } = ctx.state.auth;
|
||||
|
||||
let collection = await Collection.findByPk(id, {
|
||||
const collection = await Collection.findByPk(id, {
|
||||
transaction,
|
||||
lock: transaction.LOCK.UPDATE,
|
||||
});
|
||||
authorize(user, "move", collection);
|
||||
|
||||
collection = await collection.update(
|
||||
index = await removeIndexCollision(user.teamId, index, { transaction });
|
||||
await collection.update(
|
||||
{
|
||||
index,
|
||||
},
|
||||
@@ -976,14 +982,14 @@ router.post(
|
||||
name: "collections.move",
|
||||
collectionId: collection.id,
|
||||
data: {
|
||||
index: collection.index,
|
||||
index,
|
||||
},
|
||||
});
|
||||
|
||||
ctx.body = {
|
||||
success: true,
|
||||
data: {
|
||||
index: collection.index,
|
||||
index,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ import { safeEqual } from "@server/utils/crypto";
|
||||
import * as T from "./schema";
|
||||
|
||||
const router = new Router();
|
||||
const emailEnabled = !!(env.SMTP_HOST || env.isDevelopment);
|
||||
|
||||
const handleTeamUpdate = async (ctx: APIContext<T.TeamsUpdateSchemaReq>) => {
|
||||
const { transaction } = ctx.state;
|
||||
@@ -67,7 +68,7 @@ router.post(
|
||||
rateLimiter(RateLimiterStrategy.FivePerHour),
|
||||
auth(),
|
||||
async (ctx: APIContext) => {
|
||||
if (!env.EMAIL_ENABLED) {
|
||||
if (!emailEnabled) {
|
||||
throw ValidationError("Email support is not setup for this instance");
|
||||
}
|
||||
|
||||
@@ -100,7 +101,7 @@ router.post(
|
||||
|
||||
authorize(user, "delete", team);
|
||||
|
||||
if (env.EMAIL_ENABLED) {
|
||||
if (emailEnabled) {
|
||||
const deleteConfirmationCode = team.getDeleteConfirmationCode(user);
|
||||
|
||||
if (!safeEqual(code, deleteConfirmationCode)) {
|
||||
|
||||
@@ -30,6 +30,7 @@ import pagination from "../middlewares/pagination";
|
||||
import * as T from "./schema";
|
||||
|
||||
const router = new Router();
|
||||
const emailEnabled = !!(env.SMTP_HOST || env.isDevelopment);
|
||||
|
||||
router.post(
|
||||
"users.list",
|
||||
@@ -209,7 +210,7 @@ router.post(
|
||||
auth(),
|
||||
validate(T.UsersUpdateEmailSchema),
|
||||
async (ctx: APIContext<T.UsersUpdateEmailReq>) => {
|
||||
if (!env.EMAIL_ENABLED) {
|
||||
if (!emailEnabled) {
|
||||
throw ValidationError("Email support is not setup for this instance");
|
||||
}
|
||||
|
||||
@@ -251,7 +252,7 @@ router.get(
|
||||
transaction(),
|
||||
validate(T.UsersUpdateEmailConfirmSchema),
|
||||
async (ctx: APIContext<T.UsersUpdateEmailConfirmReq>) => {
|
||||
if (!env.EMAIL_ENABLED) {
|
||||
if (!emailEnabled) {
|
||||
throw ValidationError("Email support is not setup for this instance");
|
||||
}
|
||||
|
||||
@@ -625,7 +626,7 @@ router.post(
|
||||
rateLimiter(RateLimiterStrategy.FivePerHour),
|
||||
auth(),
|
||||
async (ctx: APIContext) => {
|
||||
if (!env.EMAIL_ENABLED) {
|
||||
if (!emailEnabled) {
|
||||
throw ValidationError("Email support is not setup for this instance");
|
||||
}
|
||||
|
||||
@@ -670,7 +671,7 @@ router.post(
|
||||
|
||||
// If we're attempting to delete our own account then a confirmation code
|
||||
// is required. This acts as CSRF protection.
|
||||
if ((!id || id === actor.id) && env.EMAIL_ENABLED) {
|
||||
if ((!id || id === actor.id) && emailEnabled) {
|
||||
const deleteConfirmationCode = user.deleteConfirmationCode;
|
||||
|
||||
if (!safeEqual(code, deleteConfirmationCode)) {
|
||||
|
||||
@@ -1,509 +0,0 @@
|
||||
[
|
||||
{
|
||||
"object": "block",
|
||||
"id": "1c12c2bb-bca8-803b-a8dc-d10fdf86fd60",
|
||||
"parent": {
|
||||
"type": "page_id",
|
||||
"page_id": "1c12c2bb-bca8-8023-ba9a-f8fafab74e48"
|
||||
},
|
||||
"created_time": "2025-03-25T07:49:00.000Z",
|
||||
"last_edited_time": "2025-03-25T07:49:00.000Z",
|
||||
"created_by": {
|
||||
"object": "user",
|
||||
"id": "b69e71d0-c6c2-428c-ae38-5c020343b36b"
|
||||
},
|
||||
"last_edited_by": {
|
||||
"object": "user",
|
||||
"id": "b69e71d0-c6c2-428c-ae38-5c020343b36b"
|
||||
},
|
||||
"has_children": false,
|
||||
"archived": false,
|
||||
"in_trash": false,
|
||||
"type": "paragraph",
|
||||
"paragraph": {
|
||||
"rich_text": [],
|
||||
"color": "default"
|
||||
}
|
||||
},
|
||||
{
|
||||
"object": "block",
|
||||
"id": "1c12c2bb-bca8-809a-a9e5-f33faf274c5f",
|
||||
"parent": {
|
||||
"type": "page_id",
|
||||
"page_id": "1c12c2bb-bca8-8023-ba9a-f8fafab74e48"
|
||||
},
|
||||
"created_time": "2025-03-25T07:56:00.000Z",
|
||||
"last_edited_time": "2025-03-25T08:09:00.000Z",
|
||||
"created_by": {
|
||||
"object": "user",
|
||||
"id": "b69e71d0-c6c2-428c-ae38-5c020343b36b"
|
||||
},
|
||||
"last_edited_by": {
|
||||
"object": "user",
|
||||
"id": "b69e71d0-c6c2-428c-ae38-5c020343b36b"
|
||||
},
|
||||
"has_children": false,
|
||||
"archived": false,
|
||||
"in_trash": false,
|
||||
"type": "code",
|
||||
"code": {
|
||||
"caption": [],
|
||||
"rich_text": [],
|
||||
"language": "javascript"
|
||||
}
|
||||
},
|
||||
{
|
||||
"object": "block",
|
||||
"id": "1c12c2bb-bca8-80c2-986a-ef8ae792a0f9",
|
||||
"parent": {
|
||||
"type": "page_id",
|
||||
"page_id": "1c12c2bb-bca8-8023-ba9a-f8fafab74e48"
|
||||
},
|
||||
"created_time": "2025-03-25T08:04:00.000Z",
|
||||
"last_edited_time": "2025-03-25T08:04:00.000Z",
|
||||
"created_by": {
|
||||
"object": "user",
|
||||
"id": "b69e71d0-c6c2-428c-ae38-5c020343b36b"
|
||||
},
|
||||
"last_edited_by": {
|
||||
"object": "user",
|
||||
"id": "b69e71d0-c6c2-428c-ae38-5c020343b36b"
|
||||
},
|
||||
"has_children": false,
|
||||
"archived": false,
|
||||
"in_trash": false,
|
||||
"type": "paragraph",
|
||||
"paragraph": {
|
||||
"rich_text": [],
|
||||
"color": "default"
|
||||
}
|
||||
},
|
||||
{
|
||||
"object": "block",
|
||||
"id": "1c12c2bb-bca8-80b3-9180-c6bc089c00fc",
|
||||
"parent": {
|
||||
"type": "page_id",
|
||||
"page_id": "1c12c2bb-bca8-8023-ba9a-f8fafab74e48"
|
||||
},
|
||||
"created_time": "2025-03-25T07:56:00.000Z",
|
||||
"last_edited_time": "2025-03-25T08:05:00.000Z",
|
||||
"created_by": {
|
||||
"object": "user",
|
||||
"id": "b69e71d0-c6c2-428c-ae38-5c020343b36b"
|
||||
},
|
||||
"last_edited_by": {
|
||||
"object": "user",
|
||||
"id": "b69e71d0-c6c2-428c-ae38-5c020343b36b"
|
||||
},
|
||||
"has_children": false,
|
||||
"archived": false,
|
||||
"in_trash": false,
|
||||
"type": "paragraph",
|
||||
"paragraph": {
|
||||
"rich_text": [
|
||||
{
|
||||
"type": "equation",
|
||||
"equation": {
|
||||
"expression": "E"
|
||||
},
|
||||
"annotations": {
|
||||
"bold": false,
|
||||
"italic": false,
|
||||
"strikethrough": false,
|
||||
"underline": false,
|
||||
"code": false,
|
||||
"color": "default"
|
||||
},
|
||||
"plain_text": "E",
|
||||
"href": null
|
||||
}
|
||||
],
|
||||
"color": "default"
|
||||
}
|
||||
},
|
||||
{
|
||||
"object": "block",
|
||||
"id": "1c12c2bb-bca8-80ca-974e-c226a1a1ae76",
|
||||
"parent": {
|
||||
"type": "page_id",
|
||||
"page_id": "1c12c2bb-bca8-8023-ba9a-f8fafab74e48"
|
||||
},
|
||||
"created_time": "2025-03-25T08:10:00.000Z",
|
||||
"last_edited_time": "2025-03-25T08:10:00.000Z",
|
||||
"created_by": {
|
||||
"object": "user",
|
||||
"id": "b69e71d0-c6c2-428c-ae38-5c020343b36b"
|
||||
},
|
||||
"last_edited_by": {
|
||||
"object": "user",
|
||||
"id": "b69e71d0-c6c2-428c-ae38-5c020343b36b"
|
||||
},
|
||||
"has_children": false,
|
||||
"archived": false,
|
||||
"in_trash": false,
|
||||
"type": "paragraph",
|
||||
"paragraph": {
|
||||
"rich_text": [],
|
||||
"color": "default"
|
||||
}
|
||||
},
|
||||
{
|
||||
"object": "block",
|
||||
"id": "1c12c2bb-bca8-8028-944b-e2593f20e09a",
|
||||
"parent": {
|
||||
"type": "page_id",
|
||||
"page_id": "1c12c2bb-bca8-8023-ba9a-f8fafab74e48"
|
||||
},
|
||||
"created_time": "2025-03-25T08:09:00.000Z",
|
||||
"last_edited_time": "2025-03-25T08:10:00.000Z",
|
||||
"created_by": {
|
||||
"object": "user",
|
||||
"id": "b69e71d0-c6c2-428c-ae38-5c020343b36b"
|
||||
},
|
||||
"last_edited_by": {
|
||||
"object": "user",
|
||||
"id": "b69e71d0-c6c2-428c-ae38-5c020343b36b"
|
||||
},
|
||||
"has_children": false,
|
||||
"archived": false,
|
||||
"in_trash": false,
|
||||
"type": "paragraph",
|
||||
"paragraph": {
|
||||
"rich_text": [
|
||||
{
|
||||
"type": "mention",
|
||||
"mention": {
|
||||
"type": "link_mention",
|
||||
"link_mention": {
|
||||
"href": "http://github.com/outline/",
|
||||
"title": "Outline",
|
||||
"icon_url": "https://github.com/fluidicon.png",
|
||||
"description": "We're building an open source collaborative knowledge base for modern teams - Outline",
|
||||
"link_provider": "GitHub",
|
||||
"thumbnail_url": "https://avatars.githubusercontent.com/u/1765001?s=280&v=4"
|
||||
}
|
||||
},
|
||||
"annotations": {
|
||||
"bold": false,
|
||||
"italic": false,
|
||||
"strikethrough": false,
|
||||
"underline": false,
|
||||
"code": false,
|
||||
"color": "default"
|
||||
},
|
||||
"plain_text": "http://github.com/outline/",
|
||||
"href": "http://github.com/outline/"
|
||||
}
|
||||
],
|
||||
"color": "default"
|
||||
}
|
||||
},
|
||||
{
|
||||
"object": "block",
|
||||
"id": "1c12c2bb-bca8-80f8-a272-c519ce56de27",
|
||||
"parent": {
|
||||
"type": "page_id",
|
||||
"page_id": "1c12c2bb-bca8-8023-ba9a-f8fafab74e48"
|
||||
},
|
||||
"created_time": "2025-03-25T08:12:00.000Z",
|
||||
"last_edited_time": "2025-03-25T08:12:00.000Z",
|
||||
"created_by": {
|
||||
"object": "user",
|
||||
"id": "b69e71d0-c6c2-428c-ae38-5c020343b36b"
|
||||
},
|
||||
"last_edited_by": {
|
||||
"object": "user",
|
||||
"id": "b69e71d0-c6c2-428c-ae38-5c020343b36b"
|
||||
},
|
||||
"has_children": false,
|
||||
"archived": false,
|
||||
"in_trash": false,
|
||||
"type": "paragraph",
|
||||
"paragraph": {
|
||||
"rich_text": [],
|
||||
"color": "default"
|
||||
}
|
||||
},
|
||||
{
|
||||
"object": "block",
|
||||
"id": "1c12c2bb-bca8-8096-8a94-e44b32127e73",
|
||||
"parent": {
|
||||
"type": "page_id",
|
||||
"page_id": "1c12c2bb-bca8-8023-ba9a-f8fafab74e48"
|
||||
},
|
||||
"created_time": "2025-03-25T08:12:00.000Z",
|
||||
"last_edited_time": "2025-03-25T08:12:00.000Z",
|
||||
"created_by": {
|
||||
"object": "user",
|
||||
"id": "b69e71d0-c6c2-428c-ae38-5c020343b36b"
|
||||
},
|
||||
"last_edited_by": {
|
||||
"object": "user",
|
||||
"id": "b69e71d0-c6c2-428c-ae38-5c020343b36b"
|
||||
},
|
||||
"has_children": false,
|
||||
"archived": false,
|
||||
"in_trash": false,
|
||||
"type": "paragraph",
|
||||
"paragraph": {
|
||||
"rich_text": [
|
||||
{
|
||||
"type": "mention",
|
||||
"mention": {
|
||||
"type": "link_preview",
|
||||
"link_preview": {
|
||||
"url": "https://github.com/outline/outline"
|
||||
}
|
||||
},
|
||||
"annotations": {
|
||||
"bold": false,
|
||||
"italic": false,
|
||||
"strikethrough": false,
|
||||
"underline": false,
|
||||
"code": false,
|
||||
"color": "default"
|
||||
},
|
||||
"plain_text": "https://github.com/outline/outline",
|
||||
"href": "https://github.com/outline/outline"
|
||||
}
|
||||
],
|
||||
"color": "default"
|
||||
}
|
||||
},
|
||||
{
|
||||
"object": "block",
|
||||
"id": "1c12c2bb-bca8-807b-98de-ff2c1d0080f2",
|
||||
"parent": {
|
||||
"type": "page_id",
|
||||
"page_id": "1c12c2bb-bca8-8023-ba9a-f8fafab74e48"
|
||||
},
|
||||
"created_time": "2025-03-25T08:13:00.000Z",
|
||||
"last_edited_time": "2025-03-25T08:13:00.000Z",
|
||||
"created_by": {
|
||||
"object": "user",
|
||||
"id": "b69e71d0-c6c2-428c-ae38-5c020343b36b"
|
||||
},
|
||||
"last_edited_by": {
|
||||
"object": "user",
|
||||
"id": "b69e71d0-c6c2-428c-ae38-5c020343b36b"
|
||||
},
|
||||
"has_children": false,
|
||||
"archived": false,
|
||||
"in_trash": false,
|
||||
"type": "paragraph",
|
||||
"paragraph": {
|
||||
"rich_text": [],
|
||||
"color": "default"
|
||||
}
|
||||
},
|
||||
{
|
||||
"object": "block",
|
||||
"id": "1c12c2bb-bca8-80dd-b816-cb4dd04d4f46",
|
||||
"parent": {
|
||||
"type": "page_id",
|
||||
"page_id": "1c12c2bb-bca8-8023-ba9a-f8fafab74e48"
|
||||
},
|
||||
"created_time": "2025-03-25T08:13:00.000Z",
|
||||
"last_edited_time": "2025-03-25T08:13:00.000Z",
|
||||
"created_by": {
|
||||
"object": "user",
|
||||
"id": "b69e71d0-c6c2-428c-ae38-5c020343b36b"
|
||||
},
|
||||
"last_edited_by": {
|
||||
"object": "user",
|
||||
"id": "b69e71d0-c6c2-428c-ae38-5c020343b36b"
|
||||
},
|
||||
"has_children": false,
|
||||
"archived": false,
|
||||
"in_trash": false,
|
||||
"type": "equation",
|
||||
"equation": {
|
||||
"expression": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"object": "block",
|
||||
"id": "1c12c2bb-bca8-8074-a5e0-f0ba30bd0510",
|
||||
"parent": {
|
||||
"type": "page_id",
|
||||
"page_id": "1c12c2bb-bca8-8023-ba9a-f8fafab74e48"
|
||||
},
|
||||
"created_time": "2025-03-25T08:18:00.000Z",
|
||||
"last_edited_time": "2025-03-25T08:18:00.000Z",
|
||||
"created_by": {
|
||||
"object": "user",
|
||||
"id": "b69e71d0-c6c2-428c-ae38-5c020343b36b"
|
||||
},
|
||||
"last_edited_by": {
|
||||
"object": "user",
|
||||
"id": "b69e71d0-c6c2-428c-ae38-5c020343b36b"
|
||||
},
|
||||
"has_children": false,
|
||||
"archived": false,
|
||||
"in_trash": false,
|
||||
"type": "paragraph",
|
||||
"paragraph": {
|
||||
"rich_text": [],
|
||||
"color": "default"
|
||||
}
|
||||
},
|
||||
{
|
||||
"object": "block",
|
||||
"id": "1c12c2bb-bca8-80dc-8a14-db8b714450f6",
|
||||
"parent": {
|
||||
"type": "page_id",
|
||||
"page_id": "1c12c2bb-bca8-8023-ba9a-f8fafab74e48"
|
||||
},
|
||||
"created_time": "2025-03-25T08:18:00.000Z",
|
||||
"last_edited_time": "2025-03-25T08:30:00.000Z",
|
||||
"created_by": {
|
||||
"object": "user",
|
||||
"id": "b69e71d0-c6c2-428c-ae38-5c020343b36b"
|
||||
},
|
||||
"last_edited_by": {
|
||||
"object": "user",
|
||||
"id": "b69e71d0-c6c2-428c-ae38-5c020343b36b"
|
||||
},
|
||||
"has_children": false,
|
||||
"archived": false,
|
||||
"in_trash": false,
|
||||
"type": "bookmark",
|
||||
"bookmark": {
|
||||
"caption": [],
|
||||
"url": "https://google.com"
|
||||
}
|
||||
},
|
||||
{
|
||||
"object": "block",
|
||||
"id": "1c12c2bb-bca8-80f2-94b4-df422d9cd18e",
|
||||
"parent": {
|
||||
"type": "page_id",
|
||||
"page_id": "1c12c2bb-bca8-8023-ba9a-f8fafab74e48"
|
||||
},
|
||||
"created_time": "2025-03-25T08:24:00.000Z",
|
||||
"last_edited_time": "2025-03-25T08:24:00.000Z",
|
||||
"created_by": {
|
||||
"object": "user",
|
||||
"id": "b69e71d0-c6c2-428c-ae38-5c020343b36b"
|
||||
},
|
||||
"last_edited_by": {
|
||||
"object": "user",
|
||||
"id": "b69e71d0-c6c2-428c-ae38-5c020343b36b"
|
||||
},
|
||||
"has_children": false,
|
||||
"archived": false,
|
||||
"in_trash": false,
|
||||
"type": "paragraph",
|
||||
"paragraph": {
|
||||
"rich_text": [],
|
||||
"color": "default"
|
||||
}
|
||||
},
|
||||
{
|
||||
"object": "block",
|
||||
"id": "1c12c2bb-bca8-8046-946c-d89c2bc7827c",
|
||||
"parent": {
|
||||
"type": "page_id",
|
||||
"page_id": "1c12c2bb-bca8-8023-ba9a-f8fafab74e48"
|
||||
},
|
||||
"created_time": "2025-03-25T08:24:00.000Z",
|
||||
"last_edited_time": "2025-03-25T08:24:00.000Z",
|
||||
"created_by": {
|
||||
"object": "user",
|
||||
"id": "b69e71d0-c6c2-428c-ae38-5c020343b36b"
|
||||
},
|
||||
"last_edited_by": {
|
||||
"object": "user",
|
||||
"id": "1b32c2bb-bca8-816a-99c0-0027ab5c4cb0"
|
||||
},
|
||||
"has_children": false,
|
||||
"archived": false,
|
||||
"in_trash": false,
|
||||
"type": "link_preview",
|
||||
"link_preview": {
|
||||
"url": "https://github.com/outline/outline"
|
||||
}
|
||||
},
|
||||
{
|
||||
"object": "block",
|
||||
"id": "1c12c2bb-bca8-80e6-80d3-f9501fc1a6fb",
|
||||
"parent": {
|
||||
"type": "page_id",
|
||||
"page_id": "1c12c2bb-bca8-8023-ba9a-f8fafab74e48"
|
||||
},
|
||||
"created_time": "2025-03-25T08:24:00.000Z",
|
||||
"last_edited_time": "2025-03-25T08:24:00.000Z",
|
||||
"created_by": {
|
||||
"object": "user",
|
||||
"id": "b69e71d0-c6c2-428c-ae38-5c020343b36b"
|
||||
},
|
||||
"last_edited_by": {
|
||||
"object": "user",
|
||||
"id": "b69e71d0-c6c2-428c-ae38-5c020343b36b"
|
||||
},
|
||||
"has_children": false,
|
||||
"archived": false,
|
||||
"in_trash": false,
|
||||
"type": "paragraph",
|
||||
"paragraph": {
|
||||
"rich_text": [],
|
||||
"color": "default"
|
||||
}
|
||||
},
|
||||
{
|
||||
"object": "block",
|
||||
"id": "1c12c2bb-bca8-8070-9c41-ca4c3aa1a419",
|
||||
"parent": {
|
||||
"type": "page_id",
|
||||
"page_id": "1c12c2bb-bca8-8023-ba9a-f8fafab74e48"
|
||||
},
|
||||
"created_time": "2025-03-25T08:24:00.000Z",
|
||||
"last_edited_time": "2025-03-25T08:30:00.000Z",
|
||||
"created_by": {
|
||||
"object": "user",
|
||||
"id": "b69e71d0-c6c2-428c-ae38-5c020343b36b"
|
||||
},
|
||||
"last_edited_by": {
|
||||
"object": "user",
|
||||
"id": "b69e71d0-c6c2-428c-ae38-5c020343b36b"
|
||||
},
|
||||
"has_children": false,
|
||||
"archived": false,
|
||||
"in_trash": false,
|
||||
"type": "pdf",
|
||||
"pdf": {
|
||||
"caption": [],
|
||||
"type": "file",
|
||||
"file": {
|
||||
"url": "https://prod-files-secure.s3.us-west-2.amazonaws.com/2f3fcad6-fc32-434b-b6b2-a03ca7893c4d/49bfa851-95c1-458b-abb0-88ed591f7712/Empty_pdf.pdf",
|
||||
"expiry_time": "2025-03-25T09:32:41.690Z"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"object": "block",
|
||||
"id": "1c12c2bb-bca8-800c-8857-eca03207279f",
|
||||
"parent": {
|
||||
"type": "page_id",
|
||||
"page_id": "1c12c2bb-bca8-8023-ba9a-f8fafab74e48"
|
||||
},
|
||||
"created_time": "2025-03-25T08:26:00.000Z",
|
||||
"last_edited_time": "2025-03-25T08:26:00.000Z",
|
||||
"created_by": {
|
||||
"object": "user",
|
||||
"id": "b69e71d0-c6c2-428c-ae38-5c020343b36b"
|
||||
},
|
||||
"last_edited_by": {
|
||||
"object": "user",
|
||||
"id": "b69e71d0-c6c2-428c-ae38-5c020343b36b"
|
||||
},
|
||||
"has_children": false,
|
||||
"archived": false,
|
||||
"in_trash": false,
|
||||
"type": "paragraph",
|
||||
"paragraph": {
|
||||
"rich_text": [],
|
||||
"color": "default"
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -54,9 +54,7 @@ export class CacheHelper {
|
||||
}
|
||||
return value;
|
||||
} finally {
|
||||
if (lock && lock.expiration > new Date().getTime()) {
|
||||
await lock.release();
|
||||
}
|
||||
await lock?.release();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import crypto from "crypto";
|
||||
import { addMinutes, subMinutes } from "date-fns";
|
||||
import type { Context } from "koa";
|
||||
// Allowed for trusted server<->server connections
|
||||
// eslint-disable-next-line no-restricted-imports
|
||||
import fetch from "node-fetch";
|
||||
import {
|
||||
StateStoreStoreCallback,
|
||||
StateStoreVerifyCallback,
|
||||
@@ -10,7 +13,6 @@ import { getCookieDomain, parseDomain } from "@shared/utils/domains";
|
||||
import env from "@server/env";
|
||||
import { Team } from "@server/models";
|
||||
import { InternalError, OAuthStateMismatchError } from "../errors";
|
||||
import fetch from "./fetch";
|
||||
|
||||
export class StateStore {
|
||||
key = "state";
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import fractionalIndex from "fractional-index";
|
||||
import { Sequelize, type FindOptions } from "sequelize";
|
||||
import { Op, Sequelize, type FindOptions } from "sequelize";
|
||||
import Collection from "@server/models/Collection";
|
||||
|
||||
/**
|
||||
@@ -31,7 +31,9 @@ export default async function removeIndexCollision(
|
||||
where: {
|
||||
teamId,
|
||||
deletedAt: null,
|
||||
index: Sequelize.literal(`"collection"."index" collate "C" > '${index}'`),
|
||||
index: {
|
||||
[Op.gt]: index,
|
||||
},
|
||||
},
|
||||
attributes: ["id", "index"],
|
||||
limit: 1,
|
||||
|
||||
@@ -29,31 +29,3 @@ export function CannotUseWithout(
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
export function CannotUseWith(
|
||||
property: string,
|
||||
validationOptions?: ValidationOptions
|
||||
) {
|
||||
return function (object: Object, propertyName: string) {
|
||||
registerDecorator({
|
||||
name: "cannotUseWith",
|
||||
target: object.constructor,
|
||||
propertyName,
|
||||
constraints: [property],
|
||||
options: validationOptions,
|
||||
validator: {
|
||||
validate<T>(value: T, args: ValidationArguments) {
|
||||
if (value === undefined) {
|
||||
return true;
|
||||
}
|
||||
const obj = args.object as unknown as T;
|
||||
const forbidden = args.constraints[0] as keyof T;
|
||||
return obj[forbidden] === undefined;
|
||||
},
|
||||
defaultMessage(args: ValidationArguments) {
|
||||
return `${propertyName} cannot be used with ${args.constraints[0]}.`;
|
||||
},
|
||||
},
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
@@ -232,7 +232,7 @@ export class ValidateDocumentId {
|
||||
export class ValidateIndex {
|
||||
public static regex = new RegExp("^[\x20-\x7E]+$");
|
||||
public static message = "Must be between x20 to x7E ASCII";
|
||||
public static maxLength = 256;
|
||||
public static maxLength = 100;
|
||||
}
|
||||
|
||||
export class ValidateURL {
|
||||
|
||||
@@ -10,10 +10,6 @@ type Props = {
|
||||
captureEvents?: "all" | "pointer" | "click";
|
||||
};
|
||||
|
||||
/**
|
||||
* EventBoundary is a component that prevents events from propagating to parent elements.
|
||||
* This is useful for preventing clicks or other interactions from bubbling up the DOM tree.
|
||||
*/
|
||||
const EventBoundary: React.FC<Props> = ({
|
||||
children,
|
||||
className,
|
||||
|
||||
@@ -5,26 +5,14 @@ type JustifyValues = CSSProperties["justifyContent"];
|
||||
|
||||
type AlignValues = CSSProperties["alignItems"];
|
||||
|
||||
/**
|
||||
* Flex is a styled component that provides a flexible box layout with convenient props.
|
||||
* It simplifies the use of flexbox CSS properties with a clean, declarative API.
|
||||
*/
|
||||
const Flex = styled.div<{
|
||||
/** Makes the component grow to fill available space */
|
||||
auto?: boolean;
|
||||
/** Changes flex direction to column */
|
||||
column?: boolean;
|
||||
/** Sets the align-items CSS property */
|
||||
align?: AlignValues;
|
||||
/** Sets the justify-content CSS property */
|
||||
justify?: JustifyValues;
|
||||
/** Enables flex-wrap */
|
||||
wrap?: boolean;
|
||||
/** Controls flex-shrink behavior */
|
||||
shrink?: boolean;
|
||||
/** Reverses the direction (row-reverse or column-reverse) */
|
||||
reverse?: boolean;
|
||||
/** Sets gap between flex items in pixels */
|
||||
gap?: number;
|
||||
}>`
|
||||
display: flex;
|
||||
|
||||
@@ -11,11 +11,6 @@ type Props = {
|
||||
className?: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* Squircle is a component that renders a square with rounded corners (squircle shape).
|
||||
* It's commonly used for app icons, avatars, and other UI elements where a softer
|
||||
* square shape is desired.
|
||||
*/
|
||||
const Squircle: React.FC<Props> = ({
|
||||
color,
|
||||
size = 28,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { NodeType } from "prosemirror-model";
|
||||
import { liftListItem, wrapInList } from "prosemirror-schema-list";
|
||||
import { wrapInList, liftListItem } from "prosemirror-schema-list";
|
||||
import { Command } from "prosemirror-state";
|
||||
import { chainTransactions } from "../lib/chainTransactions";
|
||||
import { findParentNode } from "../queries/findParentNode";
|
||||
@@ -29,14 +29,6 @@ export default function toggleList(
|
||||
return liftListItem(itemType)(state, dispatch);
|
||||
}
|
||||
|
||||
const currentItemType = parentList.node.content.firstChild?.type;
|
||||
if (currentItemType && currentItemType !== itemType) {
|
||||
return chainTransactions(clearNodes(), wrapInList(listType))(
|
||||
state,
|
||||
dispatch
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
isList(parentList.node, schema) &&
|
||||
listType.validContent(parentList.node.content)
|
||||
|
||||
@@ -313,10 +313,6 @@ width: 100%;
|
||||
background: ${props.theme.mentionHoverBackground};
|
||||
}
|
||||
|
||||
&[data-type="user"] {
|
||||
gap: 0;
|
||||
}
|
||||
|
||||
&.mention-user::before {
|
||||
content: "@";
|
||||
}
|
||||
|
||||
@@ -4,10 +4,62 @@ import { Node } from "prosemirror-model";
|
||||
import { Plugin, PluginKey, Transaction } from "prosemirror-state";
|
||||
import { Decoration, DecorationSet } from "prosemirror-view";
|
||||
import refractor from "refractor/core";
|
||||
import { getPrismLangForLanguage } from "../lib/code";
|
||||
import { isRemoteTransaction } from "../lib/multiplayer";
|
||||
import { findBlockNodes } from "../queries/findChildren";
|
||||
|
||||
export const LANGUAGES = {
|
||||
none: "Plain text", // additional entry to disable highlighting
|
||||
bash: "Bash",
|
||||
clike: "C",
|
||||
cpp: "C++",
|
||||
csharp: "C#",
|
||||
css: "CSS",
|
||||
docker: "Docker",
|
||||
elixir: "Elixir",
|
||||
erlang: "Erlang",
|
||||
go: "Go",
|
||||
graphql: "GraphQL",
|
||||
groovy: "Groovy",
|
||||
haskell: "Haskell",
|
||||
hcl: "HCL",
|
||||
markup: "HTML",
|
||||
ini: "INI",
|
||||
java: "Java",
|
||||
javascript: "JavaScript",
|
||||
json: "JSON",
|
||||
jsx: "JSX",
|
||||
kotlin: "Kotlin",
|
||||
lisp: "Lisp",
|
||||
lua: "Lua",
|
||||
mermaidjs: "Mermaid Diagram",
|
||||
nginx: "Nginx",
|
||||
nix: "Nix",
|
||||
objectivec: "Objective-C",
|
||||
ocaml: "OCaml",
|
||||
perl: "Perl",
|
||||
php: "PHP",
|
||||
powershell: "Powershell",
|
||||
protobuf: "Protobuf",
|
||||
python: "Python",
|
||||
r: "R",
|
||||
ruby: "Ruby",
|
||||
rust: "Rust",
|
||||
scala: "Scala",
|
||||
sass: "Sass",
|
||||
scss: "SCSS",
|
||||
sql: "SQL",
|
||||
solidity: "Solidity",
|
||||
swift: "Swift",
|
||||
toml: "TOML",
|
||||
tsx: "TSX",
|
||||
typescript: "TypeScript",
|
||||
vb: "Visual Basic",
|
||||
verilog: "Verilog",
|
||||
vhdl: "VHDL",
|
||||
yaml: "YAML",
|
||||
zig: "Zig",
|
||||
};
|
||||
|
||||
type ParsedNode = {
|
||||
text: string;
|
||||
classes: string[];
|
||||
@@ -57,9 +109,12 @@ function getDecorations({
|
||||
|
||||
blocks.forEach((block) => {
|
||||
let startPos = block.pos + 1;
|
||||
const language = getPrismLangForLanguage(block.node.attrs.language);
|
||||
|
||||
if (!language || !refractor.registered(language)) {
|
||||
const language = (
|
||||
block.node.attrs.language === "mermaidjs"
|
||||
? "mermaid"
|
||||
: block.node.attrs.language
|
||||
) as string;
|
||||
if (!language || language === "none" || !refractor.registered(language)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
import { getPrismLangForLanguage, getLabelForLanguage } from "./code";
|
||||
|
||||
describe("getPrismLangForLanguage", () => {
|
||||
it("should return the correct Prism language identifier for a given language", () => {
|
||||
expect(getPrismLangForLanguage("javascript")).toBe("javascript");
|
||||
expect(getPrismLangForLanguage("mermaidjs")).toBe("mermaid");
|
||||
expect(getPrismLangForLanguage("xml")).toBe("markup");
|
||||
expect(getPrismLangForLanguage("unknown")).toBeUndefined();
|
||||
expect(getPrismLangForLanguage("")).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe("getLabelForLanguage", () => {
|
||||
it("should return the correct human-readable label for a given language", () => {
|
||||
expect(getLabelForLanguage("javascript")).toBe("JavaScript");
|
||||
expect(getLabelForLanguage("mermaidjs")).toBe("Mermaid Diagram");
|
||||
expect(getLabelForLanguage("xml")).toBe("XML");
|
||||
expect(getLabelForLanguage("unknown")).toBe("Plain text");
|
||||
expect(getLabelForLanguage("none")).toBe("Plain text");
|
||||
expect(getLabelForLanguage("")).toBe("Plain text");
|
||||
});
|
||||
});
|
||||
+11
-105
@@ -1,97 +1,14 @@
|
||||
import Storage from "../../utils/Storage";
|
||||
import { LANGUAGES } from "../extensions/Prism";
|
||||
|
||||
const RecentStorageKey = "rme-code-language";
|
||||
const StorageKey = "frequent-code-languages";
|
||||
const frequentLanguagesToGet = 5;
|
||||
const frequentLanguagesToTrack = 10;
|
||||
|
||||
/**
|
||||
* List of supported code languages.
|
||||
*
|
||||
* Object key is the language identifier used in the editor, lang is the
|
||||
* language identifier used by Prism. Note mismatches such as `markup` and
|
||||
* `mermaid`.
|
||||
*/
|
||||
export const codeLanguages = {
|
||||
none: { lang: "", label: "Plain text" },
|
||||
bash: { lang: "bash", label: "Bash" },
|
||||
clike: { lang: "clike", label: "C" },
|
||||
cpp: { lang: "cpp", label: "C++" },
|
||||
csharp: { lang: "csharp", label: "C#" },
|
||||
css: { lang: "css", label: "CSS" },
|
||||
docker: { lang: "docker", label: "Docker" },
|
||||
elixir: { lang: "elixir", label: "Elixir" },
|
||||
erlang: { lang: "erlang", label: "Erlang" },
|
||||
go: { lang: "go", label: "Go" },
|
||||
graphql: { lang: "graphql", label: "GraphQL" },
|
||||
groovy: { lang: "groovy", label: "Groovy" },
|
||||
haskell: { lang: "haskell", label: "Haskell" },
|
||||
hcl: { lang: "hcl", label: "HCL" },
|
||||
markup: { lang: "markup", label: "HTML" },
|
||||
ini: { lang: "ini", label: "INI" },
|
||||
java: { lang: "java", label: "Java" },
|
||||
javascript: { lang: "javascript", label: "JavaScript" },
|
||||
json: { lang: "json", label: "JSON" },
|
||||
jsx: { lang: "jsx", label: "JSX" },
|
||||
kotlin: { lang: "kotlin", label: "Kotlin" },
|
||||
lisp: { lang: "lisp", label: "Lisp" },
|
||||
lua: { lang: "lua", label: "Lua" },
|
||||
mermaidjs: { lang: "mermaid", label: "Mermaid Diagram" },
|
||||
nginx: { lang: "nginx", label: "Nginx" },
|
||||
nix: { lang: "nix", label: "Nix" },
|
||||
objectivec: { lang: "objectivec", label: "Objective-C" },
|
||||
ocaml: { lang: "ocaml", label: "OCaml" },
|
||||
perl: { lang: "perl", label: "Perl" },
|
||||
php: { lang: "php", label: "PHP" },
|
||||
powershell: { lang: "powershell", label: "Powershell" },
|
||||
protobuf: { lang: "protobuf", label: "Protobuf" },
|
||||
python: { lang: "python", label: "Python" },
|
||||
r: { lang: "r", label: "R" },
|
||||
ruby: { lang: "ruby", label: "Ruby" },
|
||||
rust: { lang: "rust", label: "Rust" },
|
||||
scala: { lang: "scala", label: "Scala" },
|
||||
sass: { lang: "sass", label: "Sass" },
|
||||
scss: { lang: "scss", label: "SCSS" },
|
||||
sql: { lang: "sql", label: "SQL" },
|
||||
solidity: { lang: "solidity", label: "Solidity" },
|
||||
swift: { lang: "swift", label: "Swift" },
|
||||
toml: { lang: "toml", label: "TOML" },
|
||||
tsx: { lang: "tsx", label: "TSX" },
|
||||
typescript: { lang: "typescript", label: "TypeScript" },
|
||||
vb: { lang: "vb", label: "Visual Basic" },
|
||||
verilog: { lang: "verilog", label: "Verilog" },
|
||||
vhdl: { lang: "vhdl", label: "VHDL" },
|
||||
yaml: { lang: "yaml", label: "YAML" },
|
||||
xml: { lang: "markup", label: "XML" },
|
||||
zig: { lang: "zig", label: "Zig" },
|
||||
export const FrequentlyUsedCount = {
|
||||
Get: 5,
|
||||
Track: 10,
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the human-readable label for a given language.
|
||||
*
|
||||
* @param language The language identifier.
|
||||
* @returns The human-readable label for the language.
|
||||
*/
|
||||
export const getLabelForLanguage = (language: string) => {
|
||||
const lang =
|
||||
codeLanguages[language as keyof typeof codeLanguages] ?? codeLanguages.none;
|
||||
return lang.label;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the Prism language identifier for a given language.
|
||||
*
|
||||
* @param language The language identifier.
|
||||
* @returns The Prism language identifier for the language.
|
||||
*/
|
||||
export const getPrismLangForLanguage = (language: string): string | undefined =>
|
||||
codeLanguages[language as keyof typeof codeLanguages]?.lang;
|
||||
|
||||
/**
|
||||
* Set the most recent code language used.
|
||||
*
|
||||
* @param language The language identifier.
|
||||
*/
|
||||
export const setRecentCodeLanguage = (language: string) => {
|
||||
const frequentLangs = (Storage.get(StorageKey) ?? {}) as Record<
|
||||
string,
|
||||
@@ -109,14 +26,14 @@ export const setRecentCodeLanguage = (language: string) => {
|
||||
|
||||
const frequentLangEntries = Object.entries(frequentLangs);
|
||||
|
||||
if (frequentLangEntries.length > frequentLanguagesToTrack) {
|
||||
if (frequentLangEntries.length > FrequentlyUsedCount.Track) {
|
||||
sortFrequencies(frequentLangEntries);
|
||||
|
||||
const lastEntry = frequentLangEntries[frequentLanguagesToTrack];
|
||||
const lastEntry = frequentLangEntries[FrequentlyUsedCount.Track];
|
||||
if (lastEntry[0] === language) {
|
||||
frequentLangEntries.splice(frequentLanguagesToTrack - 1, 1);
|
||||
frequentLangEntries.splice(FrequentlyUsedCount.Track - 1, 1);
|
||||
} else {
|
||||
frequentLangEntries.splice(frequentLanguagesToTrack);
|
||||
frequentLangEntries.splice(FrequentlyUsedCount.Track);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -124,28 +41,17 @@ export const setRecentCodeLanguage = (language: string) => {
|
||||
Storage.set(RecentStorageKey, language);
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the most recent code language used.
|
||||
*
|
||||
* @returns The most recent code language used, or undefined if none is set.
|
||||
*/
|
||||
export const getRecentCodeLanguage = () =>
|
||||
Storage.get(RecentStorageKey) as keyof typeof codeLanguages | undefined;
|
||||
export const getRecentCodeLanguage = () => Storage.get(RecentStorageKey);
|
||||
|
||||
/**
|
||||
* Get the most frequent code languages used.
|
||||
*
|
||||
* @returns An array of the most frequent code languages used.
|
||||
*/
|
||||
export const getFrequentCodeLanguages = () => {
|
||||
const recentLang = Storage.get(RecentStorageKey);
|
||||
const frequentLangEntries = Object.entries(Storage.get(StorageKey) ?? {}) as [
|
||||
keyof typeof codeLanguages,
|
||||
keyof typeof LANGUAGES,
|
||||
number
|
||||
][];
|
||||
|
||||
const frequentLangs = sortFrequencies(frequentLangEntries)
|
||||
.slice(0, frequentLanguagesToGet)
|
||||
.slice(0, FrequentlyUsedCount.Get)
|
||||
.map(([lang]) => lang);
|
||||
|
||||
const isRecentLangPresent = frequentLangs.includes(recentLang);
|
||||
|
||||
@@ -21,7 +21,7 @@ export default class Code extends Mark {
|
||||
|
||||
get schema(): MarkSpec {
|
||||
return {
|
||||
excludes: "mention placeholder highlight",
|
||||
excludes: "mention placeholder highlight em strong",
|
||||
parseDOM: [{ tag: "code", preserveWhitespace: true }],
|
||||
toDOM: () => ["code", { class: "inline", spellCheck: "false" }],
|
||||
};
|
||||
|
||||
@@ -32,11 +32,6 @@ export default class Mention extends Node {
|
||||
}
|
||||
|
||||
get schema(): NodeSpec {
|
||||
const toPlainText = (node: ProsemirrorNode) =>
|
||||
node.attrs.type === MentionType.User
|
||||
? `@${node.attrs.label}`
|
||||
: node.attrs.label;
|
||||
|
||||
return {
|
||||
attrs: {
|
||||
type: {
|
||||
@@ -93,9 +88,12 @@ export default class Mention extends Node {
|
||||
"data-actorid": node.attrs.actorId,
|
||||
"data-url": `mention://${node.attrs.id}/${node.attrs.type}/${node.attrs.modelId}`,
|
||||
},
|
||||
toPlainText(node),
|
||||
String(node.attrs.label),
|
||||
],
|
||||
toPlainText,
|
||||
toPlainText: (node) =>
|
||||
node.attrs.type === MentionType.User
|
||||
? `@${node.attrs.label}`
|
||||
: node.attrs.label,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -7,8 +7,6 @@ type Options = {
|
||||
onlyBlock?: boolean;
|
||||
/** Only check if the selection is inside a code mark. */
|
||||
onlyMark?: boolean;
|
||||
/** If true then code must contain entire selection */
|
||||
inclusive?: boolean;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -22,29 +20,17 @@ export function isInCode(state: EditorState, options?: Options): boolean {
|
||||
const { nodes, marks } = state.schema;
|
||||
|
||||
if (!options?.onlyMark) {
|
||||
if (
|
||||
nodes.code_block &&
|
||||
isNodeActive(nodes.code_block, undefined, {
|
||||
inclusive: options?.inclusive,
|
||||
})(state)
|
||||
) {
|
||||
if (nodes.code_block && isNodeActive(nodes.code_block)(state)) {
|
||||
return true;
|
||||
}
|
||||
if (
|
||||
nodes.code_fence &&
|
||||
isNodeActive(nodes.code_fence, undefined, {
|
||||
inclusive: options?.inclusive,
|
||||
})(state)
|
||||
) {
|
||||
if (nodes.code_fence && isNodeActive(nodes.code_fence)(state)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!options?.onlyBlock) {
|
||||
if (marks.code_inline) {
|
||||
return isMarkActive(marks.code_inline, undefined, {
|
||||
inclusive: options?.inclusive,
|
||||
})(state);
|
||||
return isMarkActive(marks.code_inline)(state);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,8 +6,6 @@ import { getMarksBetween } from "./getMarksBetween";
|
||||
type Options = {
|
||||
/** Only return match if the range and attrs is exact */
|
||||
exact?: boolean;
|
||||
/** If true then mark must contain entire selection */
|
||||
inclusive?: boolean;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -42,8 +40,7 @@ export const isMarkActive =
|
||||
Object.keys(attrs).every(
|
||||
(key) => mark.attrs[key] === attrs[key]
|
||||
)) &&
|
||||
(!options?.exact || (start === from && end === to)) &&
|
||||
(!options?.inclusive || (start <= from && end >= to))
|
||||
(!options?.exact || (start === from && end === to))
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -3,55 +3,31 @@ import { EditorState } from "prosemirror-state";
|
||||
import { Primitive } from "utility-types";
|
||||
import { findParentNode } from "./findParentNode";
|
||||
|
||||
type Options = {
|
||||
/** Only return match if the range and attrs is exact */
|
||||
exact?: boolean;
|
||||
/** If true then node must contain entire selection */
|
||||
inclusive?: boolean;
|
||||
};
|
||||
|
||||
/**
|
||||
* Checks if a node is active in the current selection or not.
|
||||
*
|
||||
* @param type The node type to check.
|
||||
* @param attrs The attributes to check.
|
||||
* @param options The options to use.
|
||||
* @returns A function that checks if a node is active in the current selection or not.
|
||||
*/
|
||||
export const isNodeActive =
|
||||
(type: NodeType, attrs?: Record<string, Primitive>, options?: Options) =>
|
||||
(state: EditorState): boolean => {
|
||||
(type: NodeType, attrs: Record<string, Primitive> = {}) =>
|
||||
(state: EditorState) => {
|
||||
if (!type) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const { from, to } = state.selection;
|
||||
const nodeWithPos = findParentNode(
|
||||
(node) =>
|
||||
node.type === type &&
|
||||
(!attrs ||
|
||||
Object.keys(attrs).every((key) => node.attrs[key] === attrs[key]))
|
||||
)(state.selection);
|
||||
const nodeAfter = state.selection.$from.nodeAfter;
|
||||
let node = nodeAfter?.type === type ? nodeAfter : undefined;
|
||||
|
||||
if (!nodeWithPos) {
|
||||
return false;
|
||||
if (!node) {
|
||||
const parent = findParentNode((n) => n.type === type)(state.selection);
|
||||
node = parent?.node;
|
||||
}
|
||||
|
||||
if (options?.inclusive) {
|
||||
// Check if the node's position contains the entire selection
|
||||
return (
|
||||
nodeWithPos.pos <= from &&
|
||||
nodeWithPos.pos + nodeWithPos.node.nodeSize >= to
|
||||
);
|
||||
if (!Object.keys(attrs).length || !node) {
|
||||
return !!node;
|
||||
}
|
||||
|
||||
if (options?.exact) {
|
||||
// Check if node's range exactly matches selection
|
||||
return (
|
||||
nodeWithPos.pos === from &&
|
||||
nodeWithPos.pos + nodeWithPos.node.nodeSize === to
|
||||
);
|
||||
}
|
||||
|
||||
return true;
|
||||
return node.hasMarkup(type, { ...node.attrs, ...attrs });
|
||||
};
|
||||
|
||||
@@ -1,5 +1,16 @@
|
||||
import { useState, useLayoutEffect } from "react";
|
||||
|
||||
const defaultRect = {
|
||||
top: 0,
|
||||
left: 0,
|
||||
bottom: 0,
|
||||
right: 0,
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: 0,
|
||||
height: 0,
|
||||
};
|
||||
|
||||
/**
|
||||
* A hook that returns the size of an element or ref.
|
||||
*
|
||||
@@ -8,11 +19,19 @@ import { useState, useLayoutEffect } from "react";
|
||||
*/
|
||||
export function useComponentSize(
|
||||
input: HTMLElement | null | React.RefObject<HTMLElement | null>
|
||||
) {
|
||||
): DOMRect | typeof defaultRect {
|
||||
const element = input instanceof HTMLElement ? input : input?.current;
|
||||
const [size, setSize] = useState<DOMRect | undefined>(
|
||||
() => element?.getBoundingClientRect() || new DOMRect()
|
||||
);
|
||||
const [size, setSize] = useState(() => element?.getBoundingClientRect());
|
||||
|
||||
useLayoutEffect(() => {
|
||||
const sizeObserver = new ResizeObserver(() => {
|
||||
element?.dispatchEvent(new CustomEvent("resize"));
|
||||
});
|
||||
if (element) {
|
||||
sizeObserver.observe(element);
|
||||
}
|
||||
return () => sizeObserver.disconnect();
|
||||
}, [element]);
|
||||
|
||||
useLayoutEffect(() => {
|
||||
const handleResize = () => {
|
||||
@@ -36,7 +55,6 @@ export function useComponentSize(
|
||||
window.addEventListener("click", handleResize);
|
||||
window.addEventListener("resize", handleResize);
|
||||
element?.addEventListener("resize", handleResize);
|
||||
handleResize();
|
||||
|
||||
return () => {
|
||||
window.removeEventListener("click", handleResize);
|
||||
@@ -45,15 +63,5 @@ export function useComponentSize(
|
||||
};
|
||||
});
|
||||
|
||||
useLayoutEffect(() => {
|
||||
const sizeObserver = new ResizeObserver(() => {
|
||||
element?.dispatchEvent(new CustomEvent("resize"));
|
||||
});
|
||||
if (element) {
|
||||
sizeObserver.observe(element);
|
||||
}
|
||||
return () => sizeObserver.disconnect();
|
||||
}, [element]);
|
||||
|
||||
return size ?? new DOMRect();
|
||||
return size ?? defaultRect;
|
||||
}
|
||||
|
||||
@@ -105,32 +105,32 @@
|
||||
"@smithy/util-utf8" "^2.0.0"
|
||||
tslib "^2.6.2"
|
||||
|
||||
"@aws-sdk/client-s3@3.774.0":
|
||||
version "3.774.0"
|
||||
resolved "https://registry.yarnpkg.com/@aws-sdk/client-s3/-/client-s3-3.774.0.tgz#b8fba20417464385ee6c855aaafb67d024d10019"
|
||||
integrity sha512-HQ5Xi01r/Pv2IpzPTf5acrN0g/yJQalheDCYbBSA8VU31zoYiT/w5kLFWYJHQDB2hRozh2DB/VC/VDmntkWXxA==
|
||||
"@aws-sdk/client-s3@3.758.0":
|
||||
version "3.758.0"
|
||||
resolved "https://registry.yarnpkg.com/@aws-sdk/client-s3/-/client-s3-3.758.0.tgz#430708980e86584172ea8e3dc1450be50bd86818"
|
||||
integrity sha512-f8SlhU9/93OC/WEI6xVJf/x/GoQFj9a/xXK6QCtr5fvCjfSLgMVFmKTiIl/tgtDRzxUDc8YS6EGtbHjJ3Y/atg==
|
||||
dependencies:
|
||||
"@aws-crypto/sha1-browser" "5.2.0"
|
||||
"@aws-crypto/sha256-browser" "5.2.0"
|
||||
"@aws-crypto/sha256-js" "5.2.0"
|
||||
"@aws-sdk/core" "3.774.0"
|
||||
"@aws-sdk/credential-provider-node" "3.774.0"
|
||||
"@aws-sdk/core" "3.758.0"
|
||||
"@aws-sdk/credential-provider-node" "3.758.0"
|
||||
"@aws-sdk/middleware-bucket-endpoint" "3.734.0"
|
||||
"@aws-sdk/middleware-expect-continue" "3.734.0"
|
||||
"@aws-sdk/middleware-flexible-checksums" "3.774.0"
|
||||
"@aws-sdk/middleware-host-header" "3.774.0"
|
||||
"@aws-sdk/middleware-flexible-checksums" "3.758.0"
|
||||
"@aws-sdk/middleware-host-header" "3.734.0"
|
||||
"@aws-sdk/middleware-location-constraint" "3.734.0"
|
||||
"@aws-sdk/middleware-logger" "3.734.0"
|
||||
"@aws-sdk/middleware-recursion-detection" "3.772.0"
|
||||
"@aws-sdk/middleware-sdk-s3" "3.774.0"
|
||||
"@aws-sdk/middleware-recursion-detection" "3.734.0"
|
||||
"@aws-sdk/middleware-sdk-s3" "3.758.0"
|
||||
"@aws-sdk/middleware-ssec" "3.734.0"
|
||||
"@aws-sdk/middleware-user-agent" "3.774.0"
|
||||
"@aws-sdk/middleware-user-agent" "3.758.0"
|
||||
"@aws-sdk/region-config-resolver" "3.734.0"
|
||||
"@aws-sdk/signature-v4-multi-region" "3.774.0"
|
||||
"@aws-sdk/signature-v4-multi-region" "3.758.0"
|
||||
"@aws-sdk/types" "3.734.0"
|
||||
"@aws-sdk/util-endpoints" "3.743.0"
|
||||
"@aws-sdk/util-user-agent-browser" "3.734.0"
|
||||
"@aws-sdk/util-user-agent-node" "3.774.0"
|
||||
"@aws-sdk/util-user-agent-node" "3.758.0"
|
||||
"@aws-sdk/xml-builder" "3.734.0"
|
||||
"@smithy/config-resolver" "^4.0.1"
|
||||
"@smithy/core" "^3.1.5"
|
||||
@@ -167,23 +167,23 @@
|
||||
"@smithy/util-waiter" "^4.0.2"
|
||||
tslib "^2.6.2"
|
||||
|
||||
"@aws-sdk/client-sso@3.774.0":
|
||||
version "3.774.0"
|
||||
resolved "https://registry.yarnpkg.com/@aws-sdk/client-sso/-/client-sso-3.774.0.tgz#8af5eeaa644eb1e4775babaa46de89e1e9f3ab21"
|
||||
integrity sha512-bN+wd2gpTq+DNJ/fZdam/mX6K3TcVdZBIvxaVtg+imep6xAuRukdFhsoG0cDzk96+WHPCOhkyi+6lFljCof43Q==
|
||||
"@aws-sdk/client-sso@3.758.0":
|
||||
version "3.758.0"
|
||||
resolved "https://registry.yarnpkg.com/@aws-sdk/client-sso/-/client-sso-3.758.0.tgz#59a249abdfa52125fbe98b1d59c11e4f08ca6527"
|
||||
integrity sha512-BoGO6IIWrLyLxQG6txJw6RT2urmbtlwfggapNCrNPyYjlXpzTSJhBYjndg7TpDATFd0SXL0zm8y/tXsUXNkdYQ==
|
||||
dependencies:
|
||||
"@aws-crypto/sha256-browser" "5.2.0"
|
||||
"@aws-crypto/sha256-js" "5.2.0"
|
||||
"@aws-sdk/core" "3.774.0"
|
||||
"@aws-sdk/middleware-host-header" "3.774.0"
|
||||
"@aws-sdk/core" "3.758.0"
|
||||
"@aws-sdk/middleware-host-header" "3.734.0"
|
||||
"@aws-sdk/middleware-logger" "3.734.0"
|
||||
"@aws-sdk/middleware-recursion-detection" "3.772.0"
|
||||
"@aws-sdk/middleware-user-agent" "3.774.0"
|
||||
"@aws-sdk/middleware-recursion-detection" "3.734.0"
|
||||
"@aws-sdk/middleware-user-agent" "3.758.0"
|
||||
"@aws-sdk/region-config-resolver" "3.734.0"
|
||||
"@aws-sdk/types" "3.734.0"
|
||||
"@aws-sdk/util-endpoints" "3.743.0"
|
||||
"@aws-sdk/util-user-agent-browser" "3.734.0"
|
||||
"@aws-sdk/util-user-agent-node" "3.774.0"
|
||||
"@aws-sdk/util-user-agent-node" "3.758.0"
|
||||
"@smithy/config-resolver" "^4.0.1"
|
||||
"@smithy/core" "^3.1.5"
|
||||
"@smithy/fetch-http-handler" "^5.0.1"
|
||||
@@ -211,10 +211,10 @@
|
||||
"@smithy/util-utf8" "^4.0.0"
|
||||
tslib "^2.6.2"
|
||||
|
||||
"@aws-sdk/core@3.774.0":
|
||||
version "3.774.0"
|
||||
resolved "https://registry.yarnpkg.com/@aws-sdk/core/-/core-3.774.0.tgz#88926fc1c2efefa8fad602217865ee0c5ffca40b"
|
||||
integrity sha512-JDkAAlPyGWMX42L4Cv8mxybwHTOoFweNbNrOc5oQJhFxZAe1zkW4uLTEfr79vYhnXCFbThCyPpBotmo3U2vULA==
|
||||
"@aws-sdk/core@3.758.0":
|
||||
version "3.758.0"
|
||||
resolved "https://registry.yarnpkg.com/@aws-sdk/core/-/core-3.758.0.tgz#d13a4bb95de0460d5269cd5a40503c85b344b0b4"
|
||||
integrity sha512-0RswbdR9jt/XKemaLNuxi2gGr4xGlHyGxkTdhSQzCyUe9A9OPCoLl3rIESRguQEech+oJnbHk/wuiwHqTuP9sg==
|
||||
dependencies:
|
||||
"@aws-sdk/types" "3.734.0"
|
||||
"@smithy/core" "^3.1.5"
|
||||
@@ -228,23 +228,23 @@
|
||||
fast-xml-parser "4.4.1"
|
||||
tslib "^2.6.2"
|
||||
|
||||
"@aws-sdk/credential-provider-env@3.774.0":
|
||||
version "3.774.0"
|
||||
resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-env/-/credential-provider-env-3.774.0.tgz#1bbbb4e9ad0683d691aa65714a23ecdcbc649746"
|
||||
integrity sha512-FkSDBi9Ly0bmzyrMDeqQq1lGsFMrrd/bIB3c9VD4Llh0sPLxB/DU31+VTPTuQ0pBPz4sX5Vay6tLy43DStzcFQ==
|
||||
"@aws-sdk/credential-provider-env@3.758.0":
|
||||
version "3.758.0"
|
||||
resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-env/-/credential-provider-env-3.758.0.tgz#6193d1607eedd0929640ff64013f7787f29ff6a1"
|
||||
integrity sha512-N27eFoRrO6MeUNumtNHDW9WOiwfd59LPXPqDrIa3kWL/s+fOKFHb9xIcF++bAwtcZnAxKkgpDCUP+INNZskE+w==
|
||||
dependencies:
|
||||
"@aws-sdk/core" "3.774.0"
|
||||
"@aws-sdk/core" "3.758.0"
|
||||
"@aws-sdk/types" "3.734.0"
|
||||
"@smithy/property-provider" "^4.0.1"
|
||||
"@smithy/types" "^4.1.0"
|
||||
tslib "^2.6.2"
|
||||
|
||||
"@aws-sdk/credential-provider-http@3.774.0":
|
||||
version "3.774.0"
|
||||
resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-http/-/credential-provider-http-3.774.0.tgz#af35ae8b64a2d8347631259bf4ca0a2f1944fe35"
|
||||
integrity sha512-iurWGQColf52HpHeHCQs/LnSjZ0Ufq3VtSQx/6QdZwIhmgbbqvGMAaBJg41SQjWhpqdufE96HzcaCJw/lnCefQ==
|
||||
"@aws-sdk/credential-provider-http@3.758.0":
|
||||
version "3.758.0"
|
||||
resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-http/-/credential-provider-http-3.758.0.tgz#f7b28d642f2ac933e81a7add08ce582b398c1635"
|
||||
integrity sha512-Xt9/U8qUCiw1hihztWkNeIR+arg6P+yda10OuCHX6kFVx3auTlU7+hCqs3UxqniGU4dguHuftf3mRpi5/GJ33Q==
|
||||
dependencies:
|
||||
"@aws-sdk/core" "3.774.0"
|
||||
"@aws-sdk/core" "3.758.0"
|
||||
"@aws-sdk/types" "3.734.0"
|
||||
"@smithy/fetch-http-handler" "^5.0.1"
|
||||
"@smithy/node-http-handler" "^4.0.3"
|
||||
@@ -255,18 +255,18 @@
|
||||
"@smithy/util-stream" "^4.1.2"
|
||||
tslib "^2.6.2"
|
||||
|
||||
"@aws-sdk/credential-provider-ini@3.774.0":
|
||||
version "3.774.0"
|
||||
resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.774.0.tgz#5908b083a6f839de672c0b6cae7b725308ef3816"
|
||||
integrity sha512-+AsJOX9pGsnGPAC8wQw7LAO8ZfXzjXTjJxSP1fvg04PX7OBk4zwhVaryH6pu5raan+9cVbfEO1Z7EEMdkweGQA==
|
||||
"@aws-sdk/credential-provider-ini@3.758.0":
|
||||
version "3.758.0"
|
||||
resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.758.0.tgz#66457e71d8f5013e18111b25629c2367ed8ef116"
|
||||
integrity sha512-cymSKMcP5d+OsgetoIZ5QCe1wnp2Q/tq+uIxVdh9MbfdBBEnl9Ecq6dH6VlYS89sp4QKuxHxkWXVnbXU3Q19Aw==
|
||||
dependencies:
|
||||
"@aws-sdk/core" "3.774.0"
|
||||
"@aws-sdk/credential-provider-env" "3.774.0"
|
||||
"@aws-sdk/credential-provider-http" "3.774.0"
|
||||
"@aws-sdk/credential-provider-process" "3.774.0"
|
||||
"@aws-sdk/credential-provider-sso" "3.774.0"
|
||||
"@aws-sdk/credential-provider-web-identity" "3.774.0"
|
||||
"@aws-sdk/nested-clients" "3.774.0"
|
||||
"@aws-sdk/core" "3.758.0"
|
||||
"@aws-sdk/credential-provider-env" "3.758.0"
|
||||
"@aws-sdk/credential-provider-http" "3.758.0"
|
||||
"@aws-sdk/credential-provider-process" "3.758.0"
|
||||
"@aws-sdk/credential-provider-sso" "3.758.0"
|
||||
"@aws-sdk/credential-provider-web-identity" "3.758.0"
|
||||
"@aws-sdk/nested-clients" "3.758.0"
|
||||
"@aws-sdk/types" "3.734.0"
|
||||
"@smithy/credential-provider-imds" "^4.0.1"
|
||||
"@smithy/property-provider" "^4.0.1"
|
||||
@@ -274,17 +274,17 @@
|
||||
"@smithy/types" "^4.1.0"
|
||||
tslib "^2.6.2"
|
||||
|
||||
"@aws-sdk/credential-provider-node@3.774.0":
|
||||
version "3.774.0"
|
||||
resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-node/-/credential-provider-node-3.774.0.tgz#b82ecf506098a62b2f3774aee4377f3089e7bf39"
|
||||
integrity sha512-/t+TNhHNW6BNyf7Lgv6I0NUfFk6/dz4+6dUjopRxpDVJtp1YvNza0Zhl25ffRkqX4CKmuXyJYusDbbObcsncUA==
|
||||
"@aws-sdk/credential-provider-node@3.758.0":
|
||||
version "3.758.0"
|
||||
resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-node/-/credential-provider-node-3.758.0.tgz#b0a5d18e5d7f1b091fd891e2e8088578c0246cef"
|
||||
integrity sha512-+DaMv63wiq7pJrhIQzZYMn4hSarKiizDoJRvyR7WGhnn0oQ/getX9Z0VNCV3i7lIFoLNTb7WMmQ9k7+z/uD5EQ==
|
||||
dependencies:
|
||||
"@aws-sdk/credential-provider-env" "3.774.0"
|
||||
"@aws-sdk/credential-provider-http" "3.774.0"
|
||||
"@aws-sdk/credential-provider-ini" "3.774.0"
|
||||
"@aws-sdk/credential-provider-process" "3.774.0"
|
||||
"@aws-sdk/credential-provider-sso" "3.774.0"
|
||||
"@aws-sdk/credential-provider-web-identity" "3.774.0"
|
||||
"@aws-sdk/credential-provider-env" "3.758.0"
|
||||
"@aws-sdk/credential-provider-http" "3.758.0"
|
||||
"@aws-sdk/credential-provider-ini" "3.758.0"
|
||||
"@aws-sdk/credential-provider-process" "3.758.0"
|
||||
"@aws-sdk/credential-provider-sso" "3.758.0"
|
||||
"@aws-sdk/credential-provider-web-identity" "3.758.0"
|
||||
"@aws-sdk/types" "3.734.0"
|
||||
"@smithy/credential-provider-imds" "^4.0.1"
|
||||
"@smithy/property-provider" "^4.0.1"
|
||||
@@ -292,57 +292,57 @@
|
||||
"@smithy/types" "^4.1.0"
|
||||
tslib "^2.6.2"
|
||||
|
||||
"@aws-sdk/credential-provider-process@3.774.0":
|
||||
version "3.774.0"
|
||||
resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-process/-/credential-provider-process-3.774.0.tgz#f3e507621cdd9818dc538f8ca142bf323b71c76a"
|
||||
integrity sha512-lycBRY1NeWa46LefN258m1MRVUPQgvf6TPA6ZYajyq6/dCr6BPeuUoUAyrzePTPlxV/M25YXNiyORHjjwlK0ug==
|
||||
"@aws-sdk/credential-provider-process@3.758.0":
|
||||
version "3.758.0"
|
||||
resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-process/-/credential-provider-process-3.758.0.tgz#563bfae58049afd9968ca60f61672753834ff506"
|
||||
integrity sha512-AzcY74QTPqcbXWVgjpPZ3HOmxQZYPROIBz2YINF0OQk0MhezDWV/O7Xec+K1+MPGQO3qS6EDrUUlnPLjsqieHA==
|
||||
dependencies:
|
||||
"@aws-sdk/core" "3.774.0"
|
||||
"@aws-sdk/core" "3.758.0"
|
||||
"@aws-sdk/types" "3.734.0"
|
||||
"@smithy/property-provider" "^4.0.1"
|
||||
"@smithy/shared-ini-file-loader" "^4.0.1"
|
||||
"@smithy/types" "^4.1.0"
|
||||
tslib "^2.6.2"
|
||||
|
||||
"@aws-sdk/credential-provider-sso@3.774.0":
|
||||
version "3.774.0"
|
||||
resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.774.0.tgz#61a384c6fd56b5dd5ec1cae4c8dcc90fd77551fc"
|
||||
integrity sha512-j7vbGCWF6dVpd9qiT0PQGzY4NKf8KUa86sSoosGGbtu0dV9T/Y0s/fvPZ0F8ZyuPIKUMJaBpIJYZ/ECZRfT2mg==
|
||||
"@aws-sdk/credential-provider-sso@3.758.0":
|
||||
version "3.758.0"
|
||||
resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.758.0.tgz#5098c196a2dd38ba467aca052fc5193476b8a404"
|
||||
integrity sha512-x0FYJqcOLUCv8GLLFDYMXRAQKGjoM+L0BG4BiHYZRDf24yQWFCAZsCQAYKo6XZYh2qznbsW6f//qpyJ5b0QVKQ==
|
||||
dependencies:
|
||||
"@aws-sdk/client-sso" "3.774.0"
|
||||
"@aws-sdk/core" "3.774.0"
|
||||
"@aws-sdk/token-providers" "3.774.0"
|
||||
"@aws-sdk/client-sso" "3.758.0"
|
||||
"@aws-sdk/core" "3.758.0"
|
||||
"@aws-sdk/token-providers" "3.758.0"
|
||||
"@aws-sdk/types" "3.734.0"
|
||||
"@smithy/property-provider" "^4.0.1"
|
||||
"@smithy/shared-ini-file-loader" "^4.0.1"
|
||||
"@smithy/types" "^4.1.0"
|
||||
tslib "^2.6.2"
|
||||
|
||||
"@aws-sdk/credential-provider-web-identity@3.774.0":
|
||||
version "3.774.0"
|
||||
resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.774.0.tgz#4063e879ec57357333af542a32a72576908ecd7e"
|
||||
integrity sha512-kuE5Hdqm9xXdrYBWCU6l2aM3W3HBtZrIBgyf0y41LulJHwld1nvIySus/lILdzbipmUAv9FI07B8TF5y7p/aFA==
|
||||
"@aws-sdk/credential-provider-web-identity@3.758.0":
|
||||
version "3.758.0"
|
||||
resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.758.0.tgz#ea88729ee0e5de0bf5f31929d60dfd148934b6a5"
|
||||
integrity sha512-XGguXhBqiCXMXRxcfCAVPlMbm3VyJTou79r/3mxWddHWF0XbhaQiBIbUz6vobVTD25YQRbWSmSch7VA8kI5Lrw==
|
||||
dependencies:
|
||||
"@aws-sdk/core" "3.774.0"
|
||||
"@aws-sdk/nested-clients" "3.774.0"
|
||||
"@aws-sdk/core" "3.758.0"
|
||||
"@aws-sdk/nested-clients" "3.758.0"
|
||||
"@aws-sdk/types" "3.734.0"
|
||||
"@smithy/property-provider" "^4.0.1"
|
||||
"@smithy/types" "^4.1.0"
|
||||
tslib "^2.6.2"
|
||||
|
||||
"@aws-sdk/crt-loader@3.774.0":
|
||||
version "3.774.0"
|
||||
resolved "https://registry.yarnpkg.com/@aws-sdk/crt-loader/-/crt-loader-3.774.0.tgz#124ad98cce8320153e010b97f665ecddf0608ed1"
|
||||
integrity sha512-9pZZLebem2Q6rsT29Tzto0/P92IpwOg4c1viZltl2xnEH7kD4nxG+6v6upzPE5L2pm2S88kZXkXi7jZ6HOIBjQ==
|
||||
"@aws-sdk/crt-loader@3.758.0":
|
||||
version "3.758.0"
|
||||
resolved "https://registry.yarnpkg.com/@aws-sdk/crt-loader/-/crt-loader-3.758.0.tgz#ed9372fc887c34af4408e376832d8684316055fc"
|
||||
integrity sha512-FnLhsDNK3il4rm6Egv7IEuOf8Oiyte5AVeoYkuqgmkCll58tRZCJXYNG/VE+Tket0s3joueVt7rwvHXnMxG0rg==
|
||||
dependencies:
|
||||
"@aws-sdk/util-user-agent-node" "3.774.0"
|
||||
"@aws-sdk/util-user-agent-node" "3.758.0"
|
||||
aws-crt "^1.24.0"
|
||||
tslib "^2.6.2"
|
||||
|
||||
"@aws-sdk/lib-storage@3.774.0":
|
||||
version "3.774.0"
|
||||
resolved "https://registry.yarnpkg.com/@aws-sdk/lib-storage/-/lib-storage-3.774.0.tgz#f198af2fe92a3fe6e3368577ca836f5382c411b8"
|
||||
integrity sha512-xB3rD+F5pt+JLJaUt5eakCJ3+CUa8PXk9nxgN2VozfpuvuR6A/l3lnxmP5wYLhw1I9hxJLV9AD1/QYcibdBjtQ==
|
||||
"@aws-sdk/lib-storage@3.758.0":
|
||||
version "3.758.0"
|
||||
resolved "https://registry.yarnpkg.com/@aws-sdk/lib-storage/-/lib-storage-3.758.0.tgz#6fe6a128e6a1bc062cc3e4bd920774545ce94933"
|
||||
integrity sha512-g07y7rA505zaTJNPTmvW4zYJA3gThFDE1be7kBUKhTKAdwv8jVSbOiAy2AhClXs2evSUoQiFFtD1xWxLRXPPRQ==
|
||||
dependencies:
|
||||
"@smithy/abort-controller" "^4.0.1"
|
||||
"@smithy/middleware-endpoint" "^4.0.6"
|
||||
@@ -375,15 +375,15 @@
|
||||
"@smithy/types" "^4.1.0"
|
||||
tslib "^2.6.2"
|
||||
|
||||
"@aws-sdk/middleware-flexible-checksums@3.774.0":
|
||||
version "3.774.0"
|
||||
resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.774.0.tgz#d0345541dddda11bf8daafb25dc82809f2627c7f"
|
||||
integrity sha512-S0vs+U7sEZkRRnjf05KCbEHDduyxGgNPq+ZeaiyWbs5yTZ8wzSYrSzMAKcbCqAseNVYQbpGMXDh8tnzx6H/ihw==
|
||||
"@aws-sdk/middleware-flexible-checksums@3.758.0":
|
||||
version "3.758.0"
|
||||
resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.758.0.tgz#50b753e5c83f4fe2ec3578a1768a68336ec86e3c"
|
||||
integrity sha512-o8Rk71S08YTKLoSobucjnbj97OCGaXgpEDNKXpXaavUM5xLNoHCLSUPRCiEN86Ivqxg1n17Y2nSRhfbsveOXXA==
|
||||
dependencies:
|
||||
"@aws-crypto/crc32" "5.2.0"
|
||||
"@aws-crypto/crc32c" "5.2.0"
|
||||
"@aws-crypto/util" "5.2.0"
|
||||
"@aws-sdk/core" "3.774.0"
|
||||
"@aws-sdk/core" "3.758.0"
|
||||
"@aws-sdk/types" "3.734.0"
|
||||
"@smithy/is-array-buffer" "^4.0.0"
|
||||
"@smithy/node-config-provider" "^4.0.1"
|
||||
@@ -394,10 +394,10 @@
|
||||
"@smithy/util-utf8" "^4.0.0"
|
||||
tslib "^2.6.2"
|
||||
|
||||
"@aws-sdk/middleware-host-header@3.774.0":
|
||||
version "3.774.0"
|
||||
resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-host-header/-/middleware-host-header-3.774.0.tgz#a71a6884823512f5190b0a56db3234395d0a45ba"
|
||||
integrity sha512-7QHA0ZyEBVfyJqmIc0FW4MUtPdrWhDsHQudsvBCHFS+mqP5fhpU/o4e5RQ+0M7tQqDE65+8MrZRniRa+Txz3xA==
|
||||
"@aws-sdk/middleware-host-header@3.734.0":
|
||||
version "3.734.0"
|
||||
resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-host-header/-/middleware-host-header-3.734.0.tgz#a9a02c055352f5c435cc925a4e1e79b7ba41b1b5"
|
||||
integrity sha512-LW7RRgSOHHBzWZnigNsDIzu3AiwtjeI2X66v+Wn1P1u+eXssy1+up4ZY/h+t2sU4LU36UvEf+jrZti9c6vRnFw==
|
||||
dependencies:
|
||||
"@aws-sdk/types" "3.734.0"
|
||||
"@smithy/protocol-http" "^5.0.1"
|
||||
@@ -422,22 +422,22 @@
|
||||
"@smithy/types" "^4.1.0"
|
||||
tslib "^2.6.2"
|
||||
|
||||
"@aws-sdk/middleware-recursion-detection@3.772.0":
|
||||
version "3.772.0"
|
||||
resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.772.0.tgz#5f9bf624de8dca8791678fadc5cc905e839b3ca3"
|
||||
integrity sha512-zg0LjJa4v7fcLzn5QzZvtVS+qyvmsnu7oQnb86l6ckduZpWDCDC9+A0ZzcXTrxblPCJd3JqkoG1+Gzi4S4Ny/Q==
|
||||
"@aws-sdk/middleware-recursion-detection@3.734.0":
|
||||
version "3.734.0"
|
||||
resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.734.0.tgz#4fa1deb9887455afbb39130f7d9bc89ccee17168"
|
||||
integrity sha512-CUat2d9ITsFc2XsmeiRQO96iWpxSKYFjxvj27Hc7vo87YUHRnfMfnc8jw1EpxEwMcvBD7LsRa6vDNky6AjcrFA==
|
||||
dependencies:
|
||||
"@aws-sdk/types" "3.734.0"
|
||||
"@smithy/protocol-http" "^5.0.1"
|
||||
"@smithy/types" "^4.1.0"
|
||||
tslib "^2.6.2"
|
||||
|
||||
"@aws-sdk/middleware-sdk-s3@3.774.0":
|
||||
version "3.774.0"
|
||||
resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.774.0.tgz#e2d078a941550f70abfeed710d966958dd402cf9"
|
||||
integrity sha512-iMEaOj+S8LZfg7fZaSfXQ8YDtEfOSBiQUllyxzaVhSYlM7IeNDbpBdCWnRi34VrI1J1AuryMdX/foU9JNSTLXg==
|
||||
"@aws-sdk/middleware-sdk-s3@3.758.0":
|
||||
version "3.758.0"
|
||||
resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.758.0.tgz#75c224a49e47111df880b683debbd8f49f30ca24"
|
||||
integrity sha512-6mJ2zyyHPYSV6bAcaFpsdoXZJeQlR1QgBnZZ6juY/+dcYiuyWCdyLUbGzSZSE7GTfx6i+9+QWFeoIMlWKgU63A==
|
||||
dependencies:
|
||||
"@aws-sdk/core" "3.774.0"
|
||||
"@aws-sdk/core" "3.758.0"
|
||||
"@aws-sdk/types" "3.734.0"
|
||||
"@aws-sdk/util-arn-parser" "3.723.0"
|
||||
"@smithy/core" "^3.1.5"
|
||||
@@ -461,12 +461,12 @@
|
||||
"@smithy/types" "^4.1.0"
|
||||
tslib "^2.6.2"
|
||||
|
||||
"@aws-sdk/middleware-user-agent@3.774.0":
|
||||
version "3.774.0"
|
||||
resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.774.0.tgz#dbe66f063cf692de13301a696bb6bc693afd5608"
|
||||
integrity sha512-SVDeBV6DESgc9zex1Wk5XYbUqRI1tmJYQor47uKqD18r6UaCpvzVOBP4x8l/6hteAYxsWER6ZZmsjBQkenEuFQ==
|
||||
"@aws-sdk/middleware-user-agent@3.758.0":
|
||||
version "3.758.0"
|
||||
resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.758.0.tgz#f3c9d2025aa55fd400acb1d699c1fbd6b4f68f34"
|
||||
integrity sha512-iNyehQXtQlj69JCgfaOssgZD4HeYGOwxcaKeG6F+40cwBjTAi0+Ph1yfDwqk2qiBPIRWJ/9l2LodZbxiBqgrwg==
|
||||
dependencies:
|
||||
"@aws-sdk/core" "3.774.0"
|
||||
"@aws-sdk/core" "3.758.0"
|
||||
"@aws-sdk/types" "3.734.0"
|
||||
"@aws-sdk/util-endpoints" "3.743.0"
|
||||
"@smithy/core" "^3.1.5"
|
||||
@@ -474,23 +474,23 @@
|
||||
"@smithy/types" "^4.1.0"
|
||||
tslib "^2.6.2"
|
||||
|
||||
"@aws-sdk/nested-clients@3.774.0":
|
||||
version "3.774.0"
|
||||
resolved "https://registry.yarnpkg.com/@aws-sdk/nested-clients/-/nested-clients-3.774.0.tgz#b46a8ad0f1b106066ba58387fb8977b228186121"
|
||||
integrity sha512-00+UiYvxiZaDFVzn87kPpiZ/GiEWNaTNzC82C+bIyXt1M9AnAR6PAnnvMErTFwyG+Un6n2ai/I81wvJ1ftFmeQ==
|
||||
"@aws-sdk/nested-clients@3.758.0":
|
||||
version "3.758.0"
|
||||
resolved "https://registry.yarnpkg.com/@aws-sdk/nested-clients/-/nested-clients-3.758.0.tgz#571c853602d38f5e8faa10178347e711e4f0e444"
|
||||
integrity sha512-YZ5s7PSvyF3Mt2h1EQulCG93uybprNGbBkPmVuy/HMMfbFTt4iL3SbKjxqvOZelm86epFfj7pvK7FliI2WOEcg==
|
||||
dependencies:
|
||||
"@aws-crypto/sha256-browser" "5.2.0"
|
||||
"@aws-crypto/sha256-js" "5.2.0"
|
||||
"@aws-sdk/core" "3.774.0"
|
||||
"@aws-sdk/middleware-host-header" "3.774.0"
|
||||
"@aws-sdk/core" "3.758.0"
|
||||
"@aws-sdk/middleware-host-header" "3.734.0"
|
||||
"@aws-sdk/middleware-logger" "3.734.0"
|
||||
"@aws-sdk/middleware-recursion-detection" "3.772.0"
|
||||
"@aws-sdk/middleware-user-agent" "3.774.0"
|
||||
"@aws-sdk/middleware-recursion-detection" "3.734.0"
|
||||
"@aws-sdk/middleware-user-agent" "3.758.0"
|
||||
"@aws-sdk/region-config-resolver" "3.734.0"
|
||||
"@aws-sdk/types" "3.734.0"
|
||||
"@aws-sdk/util-endpoints" "3.743.0"
|
||||
"@aws-sdk/util-user-agent-browser" "3.734.0"
|
||||
"@aws-sdk/util-user-agent-node" "3.774.0"
|
||||
"@aws-sdk/util-user-agent-node" "3.758.0"
|
||||
"@smithy/config-resolver" "^4.0.1"
|
||||
"@smithy/core" "^3.1.5"
|
||||
"@smithy/fetch-http-handler" "^5.0.1"
|
||||
@@ -530,12 +530,12 @@
|
||||
"@smithy/util-middleware" "^4.0.1"
|
||||
tslib "^2.6.2"
|
||||
|
||||
"@aws-sdk/s3-presigned-post@3.774.0":
|
||||
version "3.774.0"
|
||||
resolved "https://registry.yarnpkg.com/@aws-sdk/s3-presigned-post/-/s3-presigned-post-3.774.0.tgz#3359884307a2937c70632b6979bd47e6690a47c1"
|
||||
integrity sha512-JttkojrrhYrTPe/svhGuMWjmoI9sbrIQ6RdXUt6JiNFVFMOqSMj5rpue3L9I4WS0Yb1+n7EiDnjLGNM9cY5/Bw==
|
||||
"@aws-sdk/s3-presigned-post@3.758.0":
|
||||
version "3.758.0"
|
||||
resolved "https://registry.yarnpkg.com/@aws-sdk/s3-presigned-post/-/s3-presigned-post-3.758.0.tgz#d65319c780a251a688c1a4158d9329cce16f6f21"
|
||||
integrity sha512-x+TWQ6xYD+/i3IlIM0nn1HGAKCmkG12VslKyJSrZAjwWQeVerj6LPVIJvYFcZbNU5lEPWCnlVqKw3S3NgG+N4Q==
|
||||
dependencies:
|
||||
"@aws-sdk/client-s3" "3.774.0"
|
||||
"@aws-sdk/client-s3" "3.758.0"
|
||||
"@aws-sdk/types" "3.734.0"
|
||||
"@aws-sdk/util-format-url" "3.734.0"
|
||||
"@smithy/middleware-endpoint" "^4.0.6"
|
||||
@@ -545,12 +545,12 @@
|
||||
"@smithy/util-utf8" "^4.0.0"
|
||||
tslib "^2.6.2"
|
||||
|
||||
"@aws-sdk/s3-request-presigner@3.774.0":
|
||||
version "3.774.0"
|
||||
resolved "https://registry.yarnpkg.com/@aws-sdk/s3-request-presigner/-/s3-request-presigner-3.774.0.tgz#b0e8301a38879a1ff03df3a807fadb88c64dac1f"
|
||||
integrity sha512-vD37Nq7+ChUkXSoDqkNMXu37R8kRDUo13pOfYgesSI4HA970fjXP1T4Mf2131Ms/NuYbBHNn330+3MAkbbYKxg==
|
||||
"@aws-sdk/s3-request-presigner@3.758.0":
|
||||
version "3.758.0"
|
||||
resolved "https://registry.yarnpkg.com/@aws-sdk/s3-request-presigner/-/s3-request-presigner-3.758.0.tgz#e7bbf9251927952584739b5e45464a9f4bdf0739"
|
||||
integrity sha512-dVyItwu/J1InfJBbCPpHRV9jrsBfI7L0RlDGyS3x/xqBwnm5qpvgNZQasQiyqIl+WJB4f5rZRZHgHuwftqINbA==
|
||||
dependencies:
|
||||
"@aws-sdk/signature-v4-multi-region" "3.774.0"
|
||||
"@aws-sdk/signature-v4-multi-region" "3.758.0"
|
||||
"@aws-sdk/types" "3.734.0"
|
||||
"@aws-sdk/util-format-url" "3.734.0"
|
||||
"@smithy/middleware-endpoint" "^4.0.6"
|
||||
@@ -559,13 +559,13 @@
|
||||
"@smithy/types" "^4.1.0"
|
||||
tslib "^2.6.2"
|
||||
|
||||
"@aws-sdk/signature-v4-crt@^3.774.0":
|
||||
version "3.774.0"
|
||||
resolved "https://registry.yarnpkg.com/@aws-sdk/signature-v4-crt/-/signature-v4-crt-3.774.0.tgz#22f6c07ac4c96b9128da57a0304f54baa07687bd"
|
||||
integrity sha512-aXc1Mw+TkDDZqG/8VFexIWqNsYqsArT+auX0QmrCv+x2XgUSpoe++2Ge2CEH4N8ez6/jE9UBqQHLn+0h734X4w==
|
||||
"@aws-sdk/signature-v4-crt@^3.758.0":
|
||||
version "3.758.0"
|
||||
resolved "https://registry.yarnpkg.com/@aws-sdk/signature-v4-crt/-/signature-v4-crt-3.758.0.tgz#a28b376a7d69019a3cb8e1afa11bfbeef9285662"
|
||||
integrity sha512-DioxfJ8+KenOwydElJvWwMxw0IN8rTD3lbV3AbURwIp+5FBDz8F5ykMO1o1YUQvrGuUNtala8lX3ScE2L7tw9w==
|
||||
dependencies:
|
||||
"@aws-sdk/crt-loader" "3.774.0"
|
||||
"@aws-sdk/signature-v4-multi-region" "3.774.0"
|
||||
"@aws-sdk/crt-loader" "3.758.0"
|
||||
"@aws-sdk/signature-v4-multi-region" "3.758.0"
|
||||
"@aws-sdk/types" "3.734.0"
|
||||
"@smithy/querystring-parser" "^4.0.1"
|
||||
"@smithy/signature-v4" "^5.0.1"
|
||||
@@ -573,24 +573,24 @@
|
||||
"@smithy/util-middleware" "^4.0.1"
|
||||
tslib "^2.6.2"
|
||||
|
||||
"@aws-sdk/signature-v4-multi-region@3.774.0":
|
||||
version "3.774.0"
|
||||
resolved "https://registry.yarnpkg.com/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.774.0.tgz#46b2240559560d064d563951af0f23a488336ff9"
|
||||
integrity sha512-vQwATjZfl5vxfO+BDUH7nUnhfKoIJMnBmOxmUh4N10PWlz3WWwkT/YtH79nVpr+y1eM6GQUSGuNa4Reda6SaFA==
|
||||
"@aws-sdk/signature-v4-multi-region@3.758.0":
|
||||
version "3.758.0"
|
||||
resolved "https://registry.yarnpkg.com/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.758.0.tgz#2ccd34e90120dbf6f29e4f621574efd02e463b79"
|
||||
integrity sha512-0RPCo8fYJcrenJ6bRtiUbFOSgQ1CX/GpvwtLU2Fam1tS9h2klKK8d74caeV6A1mIUvBU7bhyQ0wMGlwMtn3EYw==
|
||||
dependencies:
|
||||
"@aws-sdk/middleware-sdk-s3" "3.774.0"
|
||||
"@aws-sdk/middleware-sdk-s3" "3.758.0"
|
||||
"@aws-sdk/types" "3.734.0"
|
||||
"@smithy/protocol-http" "^5.0.1"
|
||||
"@smithy/signature-v4" "^5.0.1"
|
||||
"@smithy/types" "^4.1.0"
|
||||
tslib "^2.6.2"
|
||||
|
||||
"@aws-sdk/token-providers@3.774.0":
|
||||
version "3.774.0"
|
||||
resolved "https://registry.yarnpkg.com/@aws-sdk/token-providers/-/token-providers-3.774.0.tgz#d0b4b2e6b887bf5b61fbfbb946bfbb863f849d15"
|
||||
integrity sha512-DDERwCduWFFXj7gx3qvnaB8GlnCUpQ8ZA03qI4QFokWu3EyHNK+hjp3nN5Dg81fI0Z82LRe30Q2uDsLBwNCZDg==
|
||||
"@aws-sdk/token-providers@3.758.0":
|
||||
version "3.758.0"
|
||||
resolved "https://registry.yarnpkg.com/@aws-sdk/token-providers/-/token-providers-3.758.0.tgz#fcab3885ba2b222ff8bb7817448d3c786dc2ddf9"
|
||||
integrity sha512-ckptN1tNrIfQUaGWm/ayW1ddG+imbKN7HHhjFdS4VfItsP0QQOB0+Ov+tpgb4MoNR4JaUghMIVStjIeHN2ks1w==
|
||||
dependencies:
|
||||
"@aws-sdk/nested-clients" "3.774.0"
|
||||
"@aws-sdk/nested-clients" "3.758.0"
|
||||
"@aws-sdk/types" "3.734.0"
|
||||
"@smithy/property-provider" "^4.0.1"
|
||||
"@smithy/shared-ini-file-loader" "^4.0.1"
|
||||
@@ -649,12 +649,12 @@
|
||||
bowser "^2.11.0"
|
||||
tslib "^2.6.2"
|
||||
|
||||
"@aws-sdk/util-user-agent-node@3.774.0":
|
||||
version "3.774.0"
|
||||
resolved "https://registry.yarnpkg.com/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.774.0.tgz#9160dac000b699cbae623a95718fdcb3bf155f0b"
|
||||
integrity sha512-kFmnK4sf5Wco8mkzO2PszqDXEwtQ5H896tUxqWDQhk67NtOLsHYfg98ymOBWWudth2POaldiIx6KFXtg0DvLLQ==
|
||||
"@aws-sdk/util-user-agent-node@3.758.0":
|
||||
version "3.758.0"
|
||||
resolved "https://registry.yarnpkg.com/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.758.0.tgz#604ccb02a5d11c9cedaea0bea279641ea9d4194d"
|
||||
integrity sha512-A5EZw85V6WhoKMV2hbuFRvb9NPlxEErb4HPO6/SPXYY4QrjprIzScHxikqcWv1w4J3apB1wto9LPU3IMsYtfrw==
|
||||
dependencies:
|
||||
"@aws-sdk/middleware-user-agent" "3.774.0"
|
||||
"@aws-sdk/middleware-user-agent" "3.758.0"
|
||||
"@aws-sdk/types" "3.734.0"
|
||||
"@smithy/node-config-provider" "^4.0.1"
|
||||
"@smithy/types" "^4.1.0"
|
||||
@@ -675,10 +675,10 @@
|
||||
"@smithy/types" "^4.1.0"
|
||||
tslib "^2.6.2"
|
||||
|
||||
"@babel/cli@^7.27.0":
|
||||
version "7.27.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/cli/-/cli-7.27.0.tgz#076603b25fc7dd88298ea94ab249c8237c7e71cc"
|
||||
integrity sha512-bZfxn8DRxwiVzDO5CEeV+7IqXeCkzI4yYnrQbpwjT76CUyossQc6RYE7n+xfm0/2k40lPaCpW0FhxYs7EBAetw==
|
||||
"@babel/cli@^7.26.4":
|
||||
version "7.26.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/cli/-/cli-7.26.4.tgz#4101ff8ee5de8447a6c395397a97921056411d20"
|
||||
integrity sha512-+mORf3ezU3p3qr+82WvJSnQNE1GAYeoCfEv4fik6B5/2cvKZ75AX8oawWQdXtM9MmndooQj15Jr9kelRFWsuRw==
|
||||
dependencies:
|
||||
"@jridgewell/trace-mapping" "^0.3.25"
|
||||
commander "^6.2.0"
|
||||
@@ -705,34 +705,34 @@
|
||||
resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.26.8.tgz#821c1d35641c355284d4a870b8a4a7b0c141e367"
|
||||
integrity sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ==
|
||||
|
||||
"@babel/core@^7.11.6", "@babel/core@^7.12.3", "@babel/core@^7.20.12", "@babel/core@^7.24.4", "@babel/core@^7.26.10":
|
||||
version "7.26.10"
|
||||
resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.26.10.tgz#5c876f83c8c4dcb233ee4b670c0606f2ac3000f9"
|
||||
integrity sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ==
|
||||
"@babel/core@^7.11.6", "@babel/core@^7.12.3", "@babel/core@^7.20.12", "@babel/core@^7.24.4", "@babel/core@^7.26.9":
|
||||
version "7.26.9"
|
||||
resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.26.9.tgz#71838542a4b1e49dfed353d7acbc6eb89f4a76f2"
|
||||
integrity sha512-lWBYIrF7qK5+GjY5Uy+/hEgp8OJWOD/rpy74GplYRhEauvbHDeFB8t5hPOZxCZ0Oxf4Cc36tK51/l3ymJysrKw==
|
||||
dependencies:
|
||||
"@ampproject/remapping" "^2.2.0"
|
||||
"@babel/code-frame" "^7.26.2"
|
||||
"@babel/generator" "^7.26.10"
|
||||
"@babel/generator" "^7.26.9"
|
||||
"@babel/helper-compilation-targets" "^7.26.5"
|
||||
"@babel/helper-module-transforms" "^7.26.0"
|
||||
"@babel/helpers" "^7.26.10"
|
||||
"@babel/parser" "^7.26.10"
|
||||
"@babel/helpers" "^7.26.9"
|
||||
"@babel/parser" "^7.26.9"
|
||||
"@babel/template" "^7.26.9"
|
||||
"@babel/traverse" "^7.26.10"
|
||||
"@babel/types" "^7.26.10"
|
||||
"@babel/traverse" "^7.26.9"
|
||||
"@babel/types" "^7.26.9"
|
||||
convert-source-map "^2.0.0"
|
||||
debug "^4.1.0"
|
||||
gensync "^1.0.0-beta.2"
|
||||
json5 "^2.2.3"
|
||||
semver "^6.3.1"
|
||||
|
||||
"@babel/generator@^7.26.10", "@babel/generator@^7.27.0", "@babel/generator@^7.7.2":
|
||||
version "7.27.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.27.0.tgz#764382b5392e5b9aff93cadb190d0745866cbc2c"
|
||||
integrity sha512-VybsKvpiN1gU1sdMZIp7FcqphVVKEwcuj02x73uvcHE0PTihx1nlBcowYWhDwjpoAXRv43+gDzyggGnn1XZhVw==
|
||||
"@babel/generator@^7.26.9", "@babel/generator@^7.7.2":
|
||||
version "7.26.9"
|
||||
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.26.9.tgz#75a9482ad3d0cc7188a537aa4910bc59db67cbca"
|
||||
integrity sha512-kEWdzjOAUMW4hAyrzJ0ZaTOu9OmpyDIQicIh0zg0EEcEkYXZb2TjtBhnHi2ViX7PKwZqF4xwqfAm299/QMP3lg==
|
||||
dependencies:
|
||||
"@babel/parser" "^7.27.0"
|
||||
"@babel/types" "^7.27.0"
|
||||
"@babel/parser" "^7.26.9"
|
||||
"@babel/types" "^7.26.9"
|
||||
"@jridgewell/gen-mapping" "^0.3.5"
|
||||
"@jridgewell/trace-mapping" "^0.3.25"
|
||||
jsesc "^3.0.2"
|
||||
@@ -755,17 +755,17 @@
|
||||
lru-cache "^5.1.1"
|
||||
semver "^6.3.1"
|
||||
|
||||
"@babel/helper-create-class-features-plugin@^7.25.9", "@babel/helper-create-class-features-plugin@^7.27.0":
|
||||
version "7.27.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.27.0.tgz#518fad6a307c6a96f44af14912b2c20abe9bfc30"
|
||||
integrity sha512-vSGCvMecvFCd/BdpGlhpXYNhhC4ccxyvQWpbGL4CWbvfEoLFWUZuSuf7s9Aw70flgQF+6vptvgK2IfOnKlRmBg==
|
||||
"@babel/helper-create-class-features-plugin@^7.25.9":
|
||||
version "7.25.9"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.25.9.tgz#7644147706bb90ff613297d49ed5266bde729f83"
|
||||
integrity sha512-UTZQMvt0d/rSz6KI+qdu7GQze5TIajwTS++GUozlw8VBJDEOAqSXwm1WvmYEZwqdqSGQshRocPDqrt4HBZB3fQ==
|
||||
dependencies:
|
||||
"@babel/helper-annotate-as-pure" "^7.25.9"
|
||||
"@babel/helper-member-expression-to-functions" "^7.25.9"
|
||||
"@babel/helper-optimise-call-expression" "^7.25.9"
|
||||
"@babel/helper-replace-supers" "^7.26.5"
|
||||
"@babel/helper-replace-supers" "^7.25.9"
|
||||
"@babel/helper-skip-transparent-expression-wrappers" "^7.25.9"
|
||||
"@babel/traverse" "^7.27.0"
|
||||
"@babel/traverse" "^7.25.9"
|
||||
semver "^6.3.1"
|
||||
|
||||
"@babel/helper-create-regexp-features-plugin@^7.18.6", "@babel/helper-create-regexp-features-plugin@^7.25.9":
|
||||
@@ -848,7 +848,7 @@
|
||||
"@babel/helper-wrap-function" "^7.25.9"
|
||||
"@babel/traverse" "^7.25.9"
|
||||
|
||||
"@babel/helper-replace-supers@^7.25.9", "@babel/helper-replace-supers@^7.26.5":
|
||||
"@babel/helper-replace-supers@^7.25.9":
|
||||
version "7.26.5"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.26.5.tgz#6cb04e82ae291dae8e72335dfe438b0725f14c8d"
|
||||
integrity sha512-bJ6iIVdYX1YooY2X7w1q6VITt+LnUILtNk7zT78ykuwStx8BauCzxvFqFaHjOpW1bVnSUM1PN1f0p5P21wHxvg==
|
||||
@@ -889,20 +889,20 @@
|
||||
"@babel/traverse" "^7.25.9"
|
||||
"@babel/types" "^7.25.9"
|
||||
|
||||
"@babel/helpers@^7.26.10":
|
||||
version "7.27.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.27.0.tgz#53d156098defa8243eab0f32fa17589075a1b808"
|
||||
integrity sha512-U5eyP/CTFPuNE3qk+WZMxFkp/4zUzdceQlfzf7DdGdhp+Fezd7HD+i8Y24ZuTMKX3wQBld449jijbGq6OdGNQg==
|
||||
"@babel/helpers@^7.26.9":
|
||||
version "7.26.10"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.26.10.tgz#6baea3cd62ec2d0c1068778d63cb1314f6637384"
|
||||
integrity sha512-UPYc3SauzZ3JGgj87GgZ89JVdC5dj0AoetR5Bw6wj4niittNyFh6+eOGonYvJ1ao6B8lEa3Q3klS7ADZ53bc5g==
|
||||
dependencies:
|
||||
"@babel/template" "^7.27.0"
|
||||
"@babel/types" "^7.27.0"
|
||||
"@babel/template" "^7.26.9"
|
||||
"@babel/types" "^7.26.10"
|
||||
|
||||
"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.26.10", "@babel/parser@^7.27.0", "@babel/parser@^7.7.0":
|
||||
version "7.27.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.27.0.tgz#3d7d6ee268e41d2600091cbd4e145ffee85a44ec"
|
||||
integrity sha512-iaepho73/2Pz7w2eMS0Q5f83+0RKI7i4xmiYeBmDzfRVbQtTOG7Ts0S4HzJVsTMGI9keU8rNfuZr8DKfSt7Yyg==
|
||||
"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.26.9", "@babel/parser@^7.7.0":
|
||||
version "7.26.9"
|
||||
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.26.9.tgz#d9e78bee6dc80f9efd8f2349dcfbbcdace280fd5"
|
||||
integrity sha512-81NWa1njQblgZbQHxWHpxxCzNsa3ZwvFqpUg7P+NNUU6f3UU2jBEg4OlF/J6rl8+PQGh1q6/zWScd001YwcA5A==
|
||||
dependencies:
|
||||
"@babel/types" "^7.27.0"
|
||||
"@babel/types" "^7.26.9"
|
||||
|
||||
"@babel/plugin-bugfix-firefox-class-in-computed-class-key@^7.25.9":
|
||||
version "7.25.9"
|
||||
@@ -1263,7 +1263,7 @@
|
||||
"@babel/helper-module-transforms" "^7.25.9"
|
||||
"@babel/helper-plugin-utils" "^7.25.9"
|
||||
|
||||
"@babel/plugin-transform-modules-commonjs@^7.26.3":
|
||||
"@babel/plugin-transform-modules-commonjs@^7.25.9", "@babel/plugin-transform-modules-commonjs@^7.26.3":
|
||||
version "7.26.3"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.26.3.tgz#8f011d44b20d02c3de44d8850d971d8497f981fb"
|
||||
integrity sha512-MgR55l4q9KddUDITEzEFYn5ZsGDXMSsU9E+kh7fjRXTIC3RHqfCo8RPRbyReYJh44HQ/yomFkqbOFohXvDCiIQ==
|
||||
@@ -1428,12 +1428,12 @@
|
||||
"@babel/helper-annotate-as-pure" "^7.25.9"
|
||||
"@babel/helper-plugin-utils" "^7.25.9"
|
||||
|
||||
"@babel/plugin-transform-regenerator@^7.25.9", "@babel/plugin-transform-regenerator@^7.27.0":
|
||||
version "7.27.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.27.0.tgz#822feebef43d6a59a81f696b2512df5b1682db31"
|
||||
integrity sha512-LX/vCajUJQDqE7Aum/ELUMZAY19+cDpghxrnyt5I1tV6X5PyC86AOoWXWFYFeIvauyeSA6/ktn4tQVn/3ZifsA==
|
||||
"@babel/plugin-transform-regenerator@^7.25.9":
|
||||
version "7.25.9"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.25.9.tgz#03a8a4670d6cebae95305ac6defac81ece77740b"
|
||||
integrity sha512-vwDcDNsgMPDGP0nMqzahDWE5/MLcX8sv96+wfX7as7LoF/kr97Bo/7fI00lXY4wUXYfVmwIIyG80fGZ1uvt2qg==
|
||||
dependencies:
|
||||
"@babel/helper-plugin-utils" "^7.26.5"
|
||||
"@babel/helper-plugin-utils" "^7.25.9"
|
||||
regenerator-transform "^0.15.2"
|
||||
|
||||
"@babel/plugin-transform-regexp-modifiers@^7.26.0":
|
||||
@@ -1499,13 +1499,13 @@
|
||||
dependencies:
|
||||
"@babel/helper-plugin-utils" "^7.26.5"
|
||||
|
||||
"@babel/plugin-transform-typescript@^7.27.0":
|
||||
version "7.27.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.27.0.tgz#a29fd3481da85601c7e34091296e9746d2cccba8"
|
||||
integrity sha512-fRGGjO2UEGPjvEcyAZXRXAS8AfdaQoq7HnxAbJoAoW10B9xOKesmmndJv+Sym2a+9FHWZ9KbyyLCe9s0Sn5jtg==
|
||||
"@babel/plugin-transform-typescript@^7.25.9":
|
||||
version "7.26.7"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.26.7.tgz#64339515ea3eff610160f62499c3ef437d0ac83d"
|
||||
integrity sha512-5cJurntg+AT+cgelGP9Bt788DKiAw9gIMSMU2NJrLAilnj0m8WZWUNZPSLOmadYsujHutpgElO+50foX+ib/Wg==
|
||||
dependencies:
|
||||
"@babel/helper-annotate-as-pure" "^7.25.9"
|
||||
"@babel/helper-create-class-features-plugin" "^7.27.0"
|
||||
"@babel/helper-create-class-features-plugin" "^7.25.9"
|
||||
"@babel/helper-plugin-utils" "^7.26.5"
|
||||
"@babel/helper-skip-transparent-expression-wrappers" "^7.25.9"
|
||||
"@babel/plugin-syntax-typescript" "^7.25.9"
|
||||
@@ -1637,16 +1637,16 @@
|
||||
"@babel/plugin-transform-react-jsx-development" "^7.25.9"
|
||||
"@babel/plugin-transform-react-pure-annotations" "^7.25.9"
|
||||
|
||||
"@babel/preset-typescript@^7.27.0":
|
||||
version "7.27.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.27.0.tgz#4dcb8827225975f4290961b0b089f9c694ca50c7"
|
||||
integrity sha512-vxaPFfJtHhgeOVXRKuHpHPAOgymmy8V8I65T1q53R7GCZlefKeCaTyDs3zOPHTTbmquvNlQYC5klEvWsBAtrBQ==
|
||||
"@babel/preset-typescript@^7.26.0":
|
||||
version "7.26.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.26.0.tgz#4a570f1b8d104a242d923957ffa1eaff142a106d"
|
||||
integrity sha512-NMk1IGZ5I/oHhoXEElcm+xUnL/szL6xflkFZmoEU9xj1qSJXpiS7rsspYo92B4DRCDvZn2erT5LdsCeXAKNCkg==
|
||||
dependencies:
|
||||
"@babel/helper-plugin-utils" "^7.26.5"
|
||||
"@babel/helper-plugin-utils" "^7.25.9"
|
||||
"@babel/helper-validator-option" "^7.25.9"
|
||||
"@babel/plugin-syntax-jsx" "^7.25.9"
|
||||
"@babel/plugin-transform-modules-commonjs" "^7.26.3"
|
||||
"@babel/plugin-transform-typescript" "^7.27.0"
|
||||
"@babel/plugin-transform-modules-commonjs" "^7.25.9"
|
||||
"@babel/plugin-transform-typescript" "^7.25.9"
|
||||
|
||||
"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.13", "@babel/runtime@^7.12.5", "@babel/runtime@^7.13.10", "@babel/runtime@^7.17.8", "@babel/runtime@^7.20.6", "@babel/runtime@^7.21.0", "@babel/runtime@^7.23.2", "@babel/runtime@^7.6.2", "@babel/runtime@^7.8.4", "@babel/runtime@^7.9.2":
|
||||
version "7.26.10"
|
||||
@@ -1655,32 +1655,32 @@
|
||||
dependencies:
|
||||
regenerator-runtime "^0.14.0"
|
||||
|
||||
"@babel/template@^7.25.9", "@babel/template@^7.26.9", "@babel/template@^7.27.0", "@babel/template@^7.3.3":
|
||||
version "7.27.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.27.0.tgz#b253e5406cc1df1c57dcd18f11760c2dbf40c0b4"
|
||||
integrity sha512-2ncevenBqXI6qRMukPlXwHKHchC7RyMuu4xv5JBXRfOGVcTy1mXCD12qrp7Jsoxll1EV3+9sE4GugBVRjT2jFA==
|
||||
"@babel/template@^7.25.9", "@babel/template@^7.26.9", "@babel/template@^7.3.3":
|
||||
version "7.26.9"
|
||||
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.26.9.tgz#4577ad3ddf43d194528cff4e1fa6b232fa609bb2"
|
||||
integrity sha512-qyRplbeIpNZhmzOysF/wFMuP9sctmh2cFzRAZOn1YapxBsE1i9bJIY586R/WBLfLcmcBlM8ROBiQURnnNy+zfA==
|
||||
dependencies:
|
||||
"@babel/code-frame" "^7.26.2"
|
||||
"@babel/parser" "^7.27.0"
|
||||
"@babel/types" "^7.27.0"
|
||||
"@babel/parser" "^7.26.9"
|
||||
"@babel/types" "^7.26.9"
|
||||
|
||||
"@babel/traverse@^7.13.0", "@babel/traverse@^7.25.9", "@babel/traverse@^7.26.10", "@babel/traverse@^7.26.5", "@babel/traverse@^7.26.8", "@babel/traverse@^7.27.0", "@babel/traverse@^7.4.5", "@babel/traverse@^7.7.0":
|
||||
version "7.27.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.27.0.tgz#11d7e644779e166c0442f9a07274d02cd91d4a70"
|
||||
integrity sha512-19lYZFzYVQkkHkl4Cy4WrAVcqBkgvV2YM2TU3xG6DIwO7O3ecbDPfW3yM3bjAGcqcQHi+CCtjMR3dIEHxsd6bA==
|
||||
"@babel/traverse@^7.13.0", "@babel/traverse@^7.25.9", "@babel/traverse@^7.26.5", "@babel/traverse@^7.26.8", "@babel/traverse@^7.26.9", "@babel/traverse@^7.4.5", "@babel/traverse@^7.7.0":
|
||||
version "7.26.9"
|
||||
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.26.9.tgz#4398f2394ba66d05d988b2ad13c219a2c857461a"
|
||||
integrity sha512-ZYW7L+pL8ahU5fXmNbPF+iZFHCv5scFak7MZ9bwaRPLUhHh7QQEMjZUg0HevihoqCM5iSYHN61EyCoZvqC+bxg==
|
||||
dependencies:
|
||||
"@babel/code-frame" "^7.26.2"
|
||||
"@babel/generator" "^7.27.0"
|
||||
"@babel/parser" "^7.27.0"
|
||||
"@babel/template" "^7.27.0"
|
||||
"@babel/types" "^7.27.0"
|
||||
"@babel/generator" "^7.26.9"
|
||||
"@babel/parser" "^7.26.9"
|
||||
"@babel/template" "^7.26.9"
|
||||
"@babel/types" "^7.26.9"
|
||||
debug "^4.3.1"
|
||||
globals "^11.1.0"
|
||||
|
||||
"@babel/types@^7.0.0", "@babel/types@^7.25.9", "@babel/types@^7.26.10", "@babel/types@^7.27.0", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.4.4", "@babel/types@^7.7.0":
|
||||
version "7.27.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.27.0.tgz#ef9acb6b06c3173f6632d993ecb6d4ae470b4559"
|
||||
integrity sha512-H45s8fVLYjbhFH62dIJ3WtmJ6RSPt/3DRO0ZcT2SUiYiQyz3BLVb9ADEnLl91m74aQPS3AzzeajZHYOalWe3bg==
|
||||
"@babel/types@^7.0.0", "@babel/types@^7.25.9", "@babel/types@^7.26.10", "@babel/types@^7.26.9", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.4.4", "@babel/types@^7.7.0":
|
||||
version "7.26.10"
|
||||
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.26.10.tgz#396382f6335bd4feb65741eacfc808218f859259"
|
||||
integrity sha512-emqcG3vHrpxUKTrxcblR36dcrcoRDvKmnL/dCL6ZsHaShW80qxCAcNhzQZrpeM765VzEos+xOi4s+r4IXzTwdQ==
|
||||
dependencies:
|
||||
"@babel/helper-string-parser" "^7.25.9"
|
||||
"@babel/helper-validator-identifier" "^7.25.9"
|
||||
@@ -1828,10 +1828,10 @@
|
||||
enabled "2.0.x"
|
||||
kuler "^2.0.0"
|
||||
|
||||
"@datadog/datadog-api-client@^1.17.0":
|
||||
version "1.33.1"
|
||||
resolved "https://registry.yarnpkg.com/@datadog/datadog-api-client/-/datadog-api-client-1.33.1.tgz#7dcdc86383699c3a4d4414c1a3deacb44a6d3262"
|
||||
integrity sha512-ztX1/uutcuSdRqZLlirKy8tIn1VbMjBE/oLCcNL8PsDlzztaXkjhRzX71V8LTc35iQcuv9XzjjbUfOLGhypwdw==
|
||||
"@datadog/datadog-api-client@^1.16.0":
|
||||
version "1.19.0"
|
||||
resolved "https://registry.yarnpkg.com/@datadog/datadog-api-client/-/datadog-api-client-1.19.0.tgz#3bd7cafa2e83080a0efba836602699ea0441899b"
|
||||
integrity "sha1-O9fK+i6DCAoO+6g2YCaZ6gRBiZs= sha512-tMkHo7nBFtpDP4dbT/dGIIdittGaTuA6hIY6v4vWb/f+NlJPwnJUf/gBJ9Hwz1HEmlYQMuAnpdFxIQ2P6zjujA=="
|
||||
dependencies:
|
||||
"@types/buffer-from" "^1.1.0"
|
||||
"@types/node" "*"
|
||||
@@ -1842,6 +1842,7 @@
|
||||
form-data "^4.0.0"
|
||||
loglevel "^1.8.1"
|
||||
pako "^2.0.4"
|
||||
url-parse "^1.4.3"
|
||||
|
||||
"@datadog/libdatadog@^0.5.0":
|
||||
version "0.5.0"
|
||||
@@ -5312,10 +5313,10 @@
|
||||
"@types/node" "*"
|
||||
form-data "^4.0.0"
|
||||
|
||||
"@types/node@*", "@types/node@20.17.27", "@types/node@>=10.0.0", "@types/node@>=13.7.0":
|
||||
version "20.17.27"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-20.17.27.tgz#dbf0f9e6f905e9004045742f94e8413e20bad776"
|
||||
integrity sha512-U58sbKhDrthHlxHRJw7ZLiLDZGmAUOZUbpw0S6nL27sYUdhvgBLCRu/keSd6qcTsfArd1sRFCCBxzWATGr/0UA==
|
||||
"@types/node@*", "@types/node@20.17.16", "@types/node@>=10.0.0", "@types/node@>=13.7.0":
|
||||
version "20.17.16"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-20.17.16.tgz#b33b0edc1bf925b27349e494b871ca4451fabab4"
|
||||
integrity sha512-vOTpLduLkZXePLxHiHsBLp98mHGnl8RptV4YAO3HfKO5UHjDvySGbxKtpYfy8Sx5+WKcgc45qNreJJRVM3L6mw==
|
||||
dependencies:
|
||||
undici-types "~6.19.2"
|
||||
|
||||
@@ -5817,11 +5818,6 @@ agent-base@6:
|
||||
dependencies:
|
||||
debug "4"
|
||||
|
||||
agent-base@^7.1.2:
|
||||
version "7.1.3"
|
||||
resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-7.1.3.tgz#29435eb821bc4194633a5b89e5bc4703bafc25a1"
|
||||
integrity sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==
|
||||
|
||||
aggregate-error@^3.1.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a"
|
||||
@@ -7749,12 +7745,12 @@ data-view-byte-offset@^1.0.1:
|
||||
es-errors "^1.3.0"
|
||||
is-data-view "^1.0.1"
|
||||
|
||||
datadog-metrics@^0.12.1:
|
||||
version "0.12.1"
|
||||
resolved "https://registry.yarnpkg.com/datadog-metrics/-/datadog-metrics-0.12.1.tgz#8d3b91d554f9149990520d05199d08975d3edb7a"
|
||||
integrity sha512-Gy+17ia7m9Uy+nKQHDd7fljdq0fqqfpgkpxlwW0x1oFKI7RcgDV32pMCfHtv4HKychP6fHtncj3Lf4VN/g4G6A==
|
||||
datadog-metrics@^0.11.2:
|
||||
version "0.11.2"
|
||||
resolved "https://registry.yarnpkg.com/datadog-metrics/-/datadog-metrics-0.11.2.tgz#3fadf376773b06da21d5527e8574f5f315aee547"
|
||||
integrity sha512-gM2Yc9b0fwpsDtcE4Q573Xy0OJw0tp+vsli3ghZ4QRLGKkQtviKj6EFOxRYtFADV5opP+bIIJIclcWmaI76uvg==
|
||||
dependencies:
|
||||
"@datadog/datadog-api-client" "^1.17.0"
|
||||
"@datadog/datadog-api-client" "^1.16.0"
|
||||
debug "^4.1.0"
|
||||
|
||||
date-fns@^2.28.0, date-fns@^2.30.0:
|
||||
@@ -9758,14 +9754,6 @@ https-proxy-agent@^5.0.1:
|
||||
agent-base "6"
|
||||
debug "4"
|
||||
|
||||
https-proxy-agent@^7.0.6:
|
||||
version "7.0.6"
|
||||
resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz#da8dfeac7da130b05c2ba4b59c9b6cd66611a6b9"
|
||||
integrity sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==
|
||||
dependencies:
|
||||
agent-base "^7.1.2"
|
||||
debug "4"
|
||||
|
||||
human-signals@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0"
|
||||
@@ -9980,10 +9968,10 @@ invariant@^2.2.2, invariant@^2.2.4:
|
||||
dependencies:
|
||||
loose-envify "^1.0.0"
|
||||
|
||||
ioredis@^5.3.2, ioredis@^5.6.0:
|
||||
version "5.6.0"
|
||||
resolved "https://registry.yarnpkg.com/ioredis/-/ioredis-5.6.0.tgz#faa2a27132f8a05c0ddfef400b01d1326df211a0"
|
||||
integrity sha512-tBZlIIWbndeWBWCXWZiqtOF/yxf6yZX3tAlTJ7nfo5jhd6dctNxF7QnYlZLZ1a0o0pDoen7CgZqO+zjNaFbJAg==
|
||||
ioredis@^5.3.2, ioredis@^5.4.1:
|
||||
version "5.4.1"
|
||||
resolved "https://registry.yarnpkg.com/ioredis/-/ioredis-5.4.1.tgz#1c56b70b759f01465913887375ed809134296f40"
|
||||
integrity sha512-2YZsvl7jopIa1gaePkeMtd9rAcSjOOjPtpcLlOeusyO+XH2SK5ZcT+UCrElPP+WVIInh2TzeI4XW9ENaSLVVHA==
|
||||
dependencies:
|
||||
"@ioredis/commands" "^1.1.1"
|
||||
cluster-key-slot "^1.1.0"
|
||||
@@ -12742,25 +12730,25 @@ pg-cloudflare@^1.1.1:
|
||||
resolved "https://registry.yarnpkg.com/pg-cloudflare/-/pg-cloudflare-1.1.1.tgz#e6d5833015b170e23ae819e8c5d7eaedb472ca98"
|
||||
integrity "sha1-5tWDMBWxcOI66Bnoxdfq7bRyypg= sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q=="
|
||||
|
||||
pg-connection-string@^2.6.1, pg-connection-string@^2.7.0:
|
||||
version "2.7.0"
|
||||
resolved "https://registry.yarnpkg.com/pg-connection-string/-/pg-connection-string-2.7.0.tgz#f1d3489e427c62ece022dba98d5262efcb168b37"
|
||||
integrity sha512-PI2W9mv53rXJQEOb8xNR8lH7Hr+EKa6oJa38zsK0S/ky2er16ios1wLKhZyxzD7jUReiWokc9WK5nxSnC7W1TA==
|
||||
pg-connection-string@^2.6.1, pg-connection-string@^2.6.4:
|
||||
version "2.6.4"
|
||||
resolved "https://registry.yarnpkg.com/pg-connection-string/-/pg-connection-string-2.6.4.tgz#f543862adfa49fa4e14bc8a8892d2a84d754246d"
|
||||
integrity sha512-v+Z7W/0EO707aNMaAEfiGnGL9sxxumwLl2fJvCQtMn9Fxsg+lPpPkdcyBSv/KFgpGdYkMfn+EI1Or2EHjpgLCA==
|
||||
|
||||
pg-int8@1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/pg-int8/-/pg-int8-1.0.1.tgz#943bd463bf5b71b4170115f80f8efc9a0c0eb78c"
|
||||
integrity "sha1-lDvUY79bcbQXARX4D478mgwOt4w= sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw=="
|
||||
|
||||
pg-pool@^3.8.0:
|
||||
version "3.8.0"
|
||||
resolved "https://registry.yarnpkg.com/pg-pool/-/pg-pool-3.8.0.tgz#e6bce7fc4506a8d6106551363fc5283e5445b776"
|
||||
integrity sha512-VBw3jiVm6ZOdLBTIcXLNdSotb6Iy3uOCwDGFAksZCXmi10nyRvnP2v3jl4d+IsLYRyXf6o9hIm/ZtUzlByNUdw==
|
||||
pg-pool@^3.6.2:
|
||||
version "3.6.2"
|
||||
resolved "https://registry.yarnpkg.com/pg-pool/-/pg-pool-3.6.2.tgz#3a592370b8ae3f02a7c8130d245bc02fa2c5f3f2"
|
||||
integrity sha512-Htjbg8BlwXqSBQ9V8Vjtc+vzf/6fVUuak/3/XXKA9oxZprwW3IMDQTGHP+KDmVL7rtd+R1QjbnCFPuTHm3G4hg==
|
||||
|
||||
pg-protocol@^1.8.0:
|
||||
version "1.8.0"
|
||||
resolved "https://registry.yarnpkg.com/pg-protocol/-/pg-protocol-1.8.0.tgz#c707101dd07813868035a44571488e4b98639d48"
|
||||
integrity sha512-jvuYlEkL03NRvOoyoRktBK7+qU5kOvlAwvmrH8sr3wbLrOdVWsRxQfz8mMy9sZFsqJ1hEWNfdWKI4SAmoL+j7g==
|
||||
pg-protocol@^1.6.1:
|
||||
version "1.6.1"
|
||||
resolved "https://registry.yarnpkg.com/pg-protocol/-/pg-protocol-1.6.1.tgz#21333e6d83b01faaebfe7a33a7ad6bfd9ed38cb3"
|
||||
integrity sha512-jPIlvgoD63hrEuihvIg+tJhoGjUsLPn6poJY9N5CnlPd91c2T18T/9zBtLxZSb1EhYxBRoZJtzScCaWlYLtktg==
|
||||
|
||||
pg-tsquery@^8.4.2:
|
||||
version "8.4.2"
|
||||
@@ -12778,14 +12766,14 @@ pg-types@^2.1.0:
|
||||
postgres-date "~1.0.4"
|
||||
postgres-interval "^1.1.0"
|
||||
|
||||
pg@^8.14.1:
|
||||
version "8.14.1"
|
||||
resolved "https://registry.yarnpkg.com/pg/-/pg-8.14.1.tgz#2e3d1f287b64797cdfc8d1ba000f61a7ff8d66ed"
|
||||
integrity sha512-0TdbqfjwIun9Fm/r89oB7RFQ0bLgduAhiIqIXOsyKoiC/L54DbuAAzIEN/9Op0f1Po9X7iCPXGoa/Ah+2aI8Xw==
|
||||
pg@^8.12.0:
|
||||
version "8.12.0"
|
||||
resolved "https://registry.yarnpkg.com/pg/-/pg-8.12.0.tgz#9341724db571022490b657908f65aee8db91df79"
|
||||
integrity sha512-A+LHUSnwnxrnL/tZ+OLfqR1SxLN3c/pgDztZ47Rpbsd4jUytsTtwQo/TLPRzPJMp/1pbhYVhH9cuSZLAajNfjQ==
|
||||
dependencies:
|
||||
pg-connection-string "^2.7.0"
|
||||
pg-pool "^3.8.0"
|
||||
pg-protocol "^1.8.0"
|
||||
pg-connection-string "^2.6.4"
|
||||
pg-pool "^3.6.2"
|
||||
pg-protocol "^1.6.1"
|
||||
pg-types "^2.1.0"
|
||||
pgpass "1.x"
|
||||
optionalDependencies:
|
||||
@@ -13062,10 +13050,10 @@ prosemirror-codemark@^0.4.2:
|
||||
resolved "https://registry.yarnpkg.com/prosemirror-codemark/-/prosemirror-codemark-0.4.2.tgz#b4d0a57c0f1f6c6667e2a1ae7cfb6ba031dfb2e5"
|
||||
integrity "sha1-tNClfA8fbGZn4qGufPtroDHfsuU= sha512-4n+PnGQToa/vTjn0OiivUvE8/moLtguUAfry8UA4Q8p47MhqT2Qpf2zBLustX5Upi4mSp3z1ZYBqLLovZC6abA=="
|
||||
|
||||
prosemirror-commands@^1.7.0:
|
||||
version "1.7.0"
|
||||
resolved "https://registry.yarnpkg.com/prosemirror-commands/-/prosemirror-commands-1.7.0.tgz#c0a60c808f51157caa146922494fc59fe257f27c"
|
||||
integrity sha512-6toodS4R/Aah5pdsrIwnTYPEjW70SlO5a66oo5Kk+CIrgJz3ukOoS+FYDGqvQlAX5PxoGWDX1oD++tn5X3pyRA==
|
||||
prosemirror-commands@^1.6.2:
|
||||
version "1.6.2"
|
||||
resolved "https://registry.yarnpkg.com/prosemirror-commands/-/prosemirror-commands-1.6.2.tgz#d9cf6654912442cff47daa1677eb43ebd0b1f117"
|
||||
integrity sha512-0nDHH++qcf/BuPLYvmqZTUUsPJUCPBUXt0J1ErTcDIS369CTp773itzLGIgIXG4LJXOlwYCr44+Mh4ii6MP1QA==
|
||||
dependencies:
|
||||
prosemirror-model "^1.0.0"
|
||||
prosemirror-state "^1.0.0"
|
||||
@@ -13203,7 +13191,7 @@ protobufjs@^7.2.5:
|
||||
proxy-from-env@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2"
|
||||
integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==
|
||||
integrity "sha1-4QLxbKNVQkhldV0sno6k8k1Yw+I= sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
|
||||
|
||||
pseudomap@^1.0.2:
|
||||
version "1.0.2"
|
||||
@@ -13920,17 +13908,17 @@ rollup-plugin-node-resolve@^3.0.0:
|
||||
is-module "^1.0.0"
|
||||
resolve "^1.1.6"
|
||||
|
||||
rollup-plugin-stats@1.3.4:
|
||||
version "1.3.4"
|
||||
resolved "https://registry.yarnpkg.com/rollup-plugin-stats/-/rollup-plugin-stats-1.3.4.tgz#772f147bb195f7bd77877b95a7e0baf801aeaf94"
|
||||
integrity sha512-N6PCNucOrRJxqzeAvpEyK9Wf4bxQlCCuIj5+n0XUB0plFU0u1VwjY0GDM6Z3lvs/KDhzJ2anYwxXUZVfmFw8LA==
|
||||
rollup-plugin-stats@1.3.2:
|
||||
version "1.3.2"
|
||||
resolved "https://registry.yarnpkg.com/rollup-plugin-stats/-/rollup-plugin-stats-1.3.2.tgz#4dd088465cff3c00688e388787e240dff20aeed8"
|
||||
integrity sha512-VVCNU//OBzroB73gPmGJIm6xkoi25t2MsPoV6LsWUt4BVXbnrKpYAY3CwwnAfiWzM2KL4PN3SeFe/jZ9Ky7WRQ==
|
||||
|
||||
rollup-plugin-webpack-stats@^2.0.3:
|
||||
version "2.0.3"
|
||||
resolved "https://registry.yarnpkg.com/rollup-plugin-webpack-stats/-/rollup-plugin-webpack-stats-2.0.3.tgz#918dc46aa652a731bb62239c894e487bf8e5365a"
|
||||
integrity sha512-tJJaYkP3yQctWRoAn7zh47DszOpwXVaDDmxriu48cohi7Nv/87l8Ry0vHnUd8e9MbpXuKZwEGQjqk1BjYLbYww==
|
||||
rollup-plugin-webpack-stats@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/rollup-plugin-webpack-stats/-/rollup-plugin-webpack-stats-2.0.1.tgz#0ca7913227fc42db34ae51a74fa6742a6e8f5a1e"
|
||||
integrity sha512-1JALgjz4RDe14SowXJxAsQqJxGnj6JF4TIRo0FistxspFr3TyYIWCpO8B5qaes7vfdKxSNTowJtuQTOlZOobMA==
|
||||
dependencies:
|
||||
rollup-plugin-stats "1.3.4"
|
||||
rollup-plugin-stats "1.3.2"
|
||||
|
||||
rollup@^0.41.4, rollup@^2.43.1, rollup@^4.20.0, rollup@^4.5.1:
|
||||
version "4.5.1"
|
||||
@@ -15150,7 +15138,7 @@ ttl-set@^1.0.0:
|
||||
tunnel-agent@^0.6.0:
|
||||
version "0.6.0"
|
||||
resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd"
|
||||
integrity sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==
|
||||
integrity "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0= sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w=="
|
||||
dependencies:
|
||||
safe-buffer "^5.0.1"
|
||||
|
||||
@@ -15442,7 +15430,7 @@ urijs@^1.19.0:
|
||||
resolved "https://registry.yarnpkg.com/urijs/-/urijs-1.19.11.tgz#204b0d6b605ae80bea54bea39280cdb7c9f923cc"
|
||||
integrity "sha1-IEsNa2Ba6AvqVL6jkoDNt8n5I8w= sha512-HXgFDgDommxn5/bIv0cnQZsPhHDA90NPHD6+c/v21U5+Sx5hoP8+dP9IZXBU1gIfvdRfhG8cel9QNPeionfcCQ=="
|
||||
|
||||
url-parse@^1.5.3:
|
||||
url-parse@^1.4.3, url-parse@^1.5.3:
|
||||
version "1.5.10"
|
||||
resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.10.tgz#9d3c2f736c1d75dd3bd2be507dcc111f1e2ea9c1"
|
||||
integrity "sha1-nTwvc2wddd070r5QfcwRHx4uqcE= sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ=="
|
||||
@@ -15615,10 +15603,10 @@ vite-plugin-static-copy@^0.17.0:
|
||||
fs-extra "^11.1.0"
|
||||
picocolors "^1.0.0"
|
||||
|
||||
vite@^5.4.15:
|
||||
version "5.4.15"
|
||||
resolved "https://registry.yarnpkg.com/vite/-/vite-5.4.15.tgz#2941547f10ebb4bf9b0fa0da863c06711eb7e5e5"
|
||||
integrity sha512-6ANcZRivqL/4WtwPGTKNaosuNJr5tWiftOC7liM7G9+rMb8+oeJeyzymDu4rTN93seySBmbjSfsS3Vzr19KNtA==
|
||||
vite@^5.4.14:
|
||||
version "5.4.14"
|
||||
resolved "https://registry.yarnpkg.com/vite/-/vite-5.4.14.tgz#ff8255edb02134df180dcfca1916c37a6abe8408"
|
||||
integrity sha512-EK5cY7Q1D8JNhSaPKVK4pwBFvaTmZxEnoKXLG/U9gmdDcihQGNzFlgIvaxezFR4glP1LsuiedwMBqCXH3wZccA==
|
||||
dependencies:
|
||||
esbuild "^0.21.3"
|
||||
postcss "^8.4.43"
|
||||
@@ -16226,7 +16214,7 @@ yocto-queue@^0.1.0:
|
||||
resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b"
|
||||
integrity "sha1-ApTrPe4FAo0x7hpfosVWpqrxChs= sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="
|
||||
|
||||
zod@^3.19.1, zod@^3.24.2:
|
||||
version "3.24.2"
|
||||
resolved "https://registry.yarnpkg.com/zod/-/zod-3.24.2.tgz#8efa74126287c675e92f46871cfc8d15c34372b3"
|
||||
integrity sha512-lY7CDW43ECgW9u1TcT3IoXHflywfVqDYze4waEz812jR/bZ8FHDsl7pFQoSZTz5N+2NqRXs8GBwnAwo3ZNxqhQ==
|
||||
zod@^3.19.1, zod@^3.23.8:
|
||||
version "3.23.8"
|
||||
resolved "https://registry.yarnpkg.com/zod/-/zod-3.23.8.tgz#e37b957b5d52079769fb8097099b592f0ef4067d"
|
||||
integrity sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==
|
||||
|
||||
Reference in New Issue
Block a user