diff --git a/packages/chronos/tsconfig.json b/packages/chronos/tsconfig.json index 00f66831a3b..87e7ef08687 100644 --- a/packages/chronos/tsconfig.json +++ b/packages/chronos/tsconfig.json @@ -9,13 +9,6 @@ "~/*": ["client/*"] }, "outDir": "lib", - "lib": ["esnext"], - "types": ["node"] - }, - "files": [ - "chronos.ts", - "../server/types/webpackEnv.ts", - "../server/types/modules.d.ts", - "../client/modules/email/components/SummaryEmail/MeetingSummaryEmail/MeetingSummaryEmail.tsx" - ] + "lib": ["esnext"] + } } diff --git a/packages/client/components/AnimatedFade.tsx b/packages/client/components/AnimatedFade.tsx deleted file mode 100644 index f1f612ec4ff..00000000000 --- a/packages/client/components/AnimatedFade.tsx +++ /dev/null @@ -1,74 +0,0 @@ -/* Deprecated. See internals of useMenuPortal */ - -import {ClassNames} from '@emotion/core' -import React, {Component, ReactNode} from 'react' -import {CSSTransition} from 'react-transition-group' - -interface Props extends CSSTransition { - appear?: boolean - in?: boolean - onExited?: () => void - exit?: boolean - unmountOnExit?: boolean - children: ReactNode - duration?: number - slide?: number -} - -// eslint-disable-next-line -class AnimatedFade extends Component { - render() { - const {children, duration = 100, slide = 32, ...props} = this.props - - const classNames = (css) => { - const enter = css({ - opacity: 0, - transform: `translate3d(0, ${slide}px, 0)` - }) - const enterActive = css({ - opacity: '1 !important' as any, - transform: 'translate3d(0, 0, 0) !important', - transition: `all ${duration}ms ease-in !important` - }) - - const exit = css({ - opacity: 1, - transform: 'translate3d(0, 0, 0)' - }) - - const exitActive = css({ - opacity: '0 !important' as any, - transform: `translate3d(0, ${-slide}px, 0) !important`, - transition: `all ${duration}ms ease-in !important` - }) - return { - appear: enter, - appearActive: enterActive, - enter, - enterActive, - exit, - exitActive - } - } - return ( - - {({css}) => { - return ( - - {children} - - ) - }} - - ) - } -} - -export default AnimatedFade diff --git a/packages/client/components/AzureDevOpsScopingSelectAllIssues.tsx b/packages/client/components/AzureDevOpsScopingSelectAllIssues.tsx index d4f80d54fe0..24c42792294 100644 --- a/packages/client/components/AzureDevOpsScopingSelectAllIssues.tsx +++ b/packages/client/components/AzureDevOpsScopingSelectAllIssues.tsx @@ -3,6 +3,7 @@ import graphql from 'babel-plugin-relay/macro' import React from 'react' import {useFragment} from 'react-relay' import useUnusedRecords from '~/hooks/useUnusedRecords' +import {AzureDevOpsScopingSelectAllIssues_workItems$key} from '../__generated__/AzureDevOpsScopingSelectAllIssues_workItems.graphql' import useAtmosphere from '../hooks/useAtmosphere' import useMutationProps from '../hooks/useMutationProps' import UpdatePokerScopeMutation from '../mutations/UpdatePokerScopeMutation' @@ -11,7 +12,6 @@ import {PALETTE} from '../styles/paletteV3' import {Threshold} from '../types/constEnums' import AzureDevOpsClientManager from '../utils/AzureDevOpsClientManager' import getSelectAllTitle from '../utils/getSelectAllTitle' -import {AzureDevOpsScopingSelectAllIssues_workItems$key} from '../__generated__/AzureDevOpsScopingSelectAllIssues_workItems.graphql' import Checkbox from './Checkbox' const Item = styled('div')({ @@ -42,7 +42,7 @@ interface Props { } const AzureDevOpsScopingSelectAllIssues = (props: Props) => { - const {meetingId, usedServiceTaskIds, workItems: workItemsRef, providerId} = props + const {meetingId, usedServiceTaskIds, workItems: workItemsRef} = props const workItems = useFragment( graphql` fragment AzureDevOpsScopingSelectAllIssues_workItems on AzureDevOpsWorkItemEdge @@ -57,7 +57,7 @@ const AzureDevOpsScopingSelectAllIssues = (props: Props) => { workItemsRef ) const atmosphere = useAtmosphere() - const {onCompleted, onError, submitMutation, submitting, error} = useMutationProps() + const {onCompleted, onError, submitMutation, error} = useMutationProps() const getProjectId = (url: URL) => { const firstIndex = url.pathname.indexOf('/', 1) const seconedIndex = url.pathname.indexOf('/', firstIndex + 1) diff --git a/packages/client/hooks/useAtlassianSites.ts b/packages/client/hooks/useAtlassianSites.ts deleted file mode 100644 index 8fdb3a66567..00000000000 --- a/packages/client/hooks/useAtlassianSites.ts +++ /dev/null @@ -1,43 +0,0 @@ -import {useEffect, useRef, useState} from 'react' -import {Unpromise} from '../types/generics' -import AtlassianClientManager from '../utils/AtlassianClientManager' -import {AccessibleResource} from '../utils/AtlassianManager' - -const useAtlassianSites = (accessToken?: string) => { - const isMountedRef = useRef(true) - const [sites, setSites] = useState([]) - const [status, setStatus] = useState(null) - useEffect(() => { - const manager = new AtlassianClientManager(accessToken || '') - const fetchSites = async () => { - let res: Unpromise> - try { - res = await manager.getAccessibleResources() - } catch (e) { - if (isMountedRef.current) { - setStatus('error') - } - return - } - if (isMountedRef.current) { - if (Array.isArray(res)) { - setStatus('loaded') - setSites(res) - } else { - setStatus('error') - } - } - } - - if (accessToken && isMountedRef.current) { - setStatus('loading') - fetchSites().catch() - } - return () => { - isMountedRef.current = false - } - }, [accessToken]) - return {sites, status} -} - -export default useAtlassianSites diff --git a/packages/client/modules/email/components/MeetingSummaryEmailRootSSR.tsx b/packages/client/modules/email/components/MeetingSummaryEmailRootSSR.tsx index 9ad3310cd7d..bd17389a344 100644 --- a/packages/client/modules/email/components/MeetingSummaryEmailRootSSR.tsx +++ b/packages/client/modules/email/components/MeetingSummaryEmailRootSSR.tsx @@ -2,7 +2,6 @@ import graphql from 'babel-plugin-relay/macro' import {MeetingSummaryEmailRootSSRQuery} from 'parabol-client/__generated__/MeetingSummaryEmailRootSSRQuery.graphql' import React from 'react' import {useLazyLoadQuery} from 'react-relay' -import {Environment} from 'relay-runtime' import {EMAIL_CORS_OPTIONS} from '../../../types/cors' import makeAppURL from '../../../utils/makeAppURL' import MeetingSummaryEmail from './SummaryEmail/MeetingSummaryEmail/MeetingSummaryEmail' diff --git a/packages/client/modules/email/components/NotificationSummaryEmailRoot.tsx b/packages/client/modules/email/components/NotificationSummaryEmailRoot.tsx index bcf16c49bb0..cd610f6758d 100644 --- a/packages/client/modules/email/components/NotificationSummaryEmailRoot.tsx +++ b/packages/client/modules/email/components/NotificationSummaryEmailRoot.tsx @@ -56,7 +56,7 @@ const NotificationSummaryEmailRoot = (props: NotificationSummaryRootProps) => { (edge) => edge.node.status === 'UNREAD' && new Date(edge.node.createdAt) > new Date(Date.now() - ms('1d')) && - NOTIFICATION_TEMPLATE_TYPE[edge.node.type] // Filter down to the notifications that have been implemented. + NOTIFICATION_TEMPLATE_TYPE[edge.node.type as keyof typeof NOTIFICATION_TEMPLATE_TYPE] // Filter down to the notifications that have been implemented. ) .map((edge) => edge.node) .slice(0, MAX_EMAIL_NOTIFICATIONS) diff --git a/packages/client/modules/email/components/SummaryEmail/MeetingSummaryEmail/MeetingSummaryEmail.tsx b/packages/client/modules/email/components/SummaryEmail/MeetingSummaryEmail/MeetingSummaryEmail.tsx index 5a2611456f8..b49644af0f5 100644 --- a/packages/client/modules/email/components/SummaryEmail/MeetingSummaryEmail/MeetingSummaryEmail.tsx +++ b/packages/client/modules/email/components/SummaryEmail/MeetingSummaryEmail/MeetingSummaryEmail.tsx @@ -36,20 +36,6 @@ const pagePadding = { paddingTop: 24 } -declare module 'react' { - interface TdHTMLAttributes { - height?: string | number - width?: string | number - bgcolor?: string - } - interface TableHTMLAttributes { - align?: 'center' | 'left' | 'right' - bgcolor?: string - height?: string | number - width?: string | number - } -} - const PagePadding = () => { return ( diff --git a/packages/client/mutations/handlers/handleUpdateTeamMembers.ts b/packages/client/mutations/handlers/handleUpdateTeamMembers.ts index f62a323f291..6ccecccea3c 100644 --- a/packages/client/mutations/handlers/handleUpdateTeamMembers.ts +++ b/packages/client/mutations/handlers/handleUpdateTeamMembers.ts @@ -1,8 +1,12 @@ +import {RecordProxy, RecordSourceSelectorProxy} from 'relay-runtime' import fromTeamMemberId from '../../utils/relay/fromTeamMemberId' import safeRemoveNodeFromArray from '../../utils/relay/safeRemoveNodeFromArray' import pluralizeHandler from './pluralizeHandler' -const handleUpdateTeamMember = (updatedTeamMember, store) => { +const handleUpdateTeamMember = ( + updatedTeamMember: RecordProxy<{id: string}>, + store: RecordSourceSelectorProxy +) => { if (!updatedTeamMember) return const {teamId} = fromTeamMemberId(updatedTeamMember.getValue('id')) const isNotRemoved = updatedTeamMember.getValue('isNotRemoved') @@ -11,7 +15,7 @@ const handleUpdateTeamMember = (updatedTeamMember, store) => { const sorts = ['preferredName'] if (isNotRemoved) { sorts.forEach((sortBy) => { - const teamMembers = team.getLinkedRecords('teamMembers', {sortBy}) + const teamMembers = team.getLinkedRecords<[]>('teamMembers', {sortBy}) if (!teamMembers) return teamMembers.sort((a, b) => (a.getValue(sortBy) > b.getValue(sortBy) ? 1 : -1)) team.setLinkedRecords(teamMembers, 'teamMembers', {sortBy}) @@ -19,8 +23,7 @@ const handleUpdateTeamMember = (updatedTeamMember, store) => { } else { const teamMemberId = updatedTeamMember.getValue('id') sorts.forEach((sortBy) => { - const teamMembers = team.getLinkedRecords('teamMembers', {sortBy}) - safeRemoveNodeFromArray(teamMemberId, teamMembers, 'teamMembers', { + safeRemoveNodeFromArray(teamMemberId, team, 'teamMembers', { storageKeyArgs: {sortBy} }) }) diff --git a/packages/client/package.json b/packages/client/package.json index 3f105e730fb..5775dc743ab 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -31,7 +31,7 @@ "@types/draft-js": "^0.10.24", "@types/fbjs": "^3.0.4", "@types/humanize-duration": "3.27.1", - "@types/jest": "^29.5.1", + "@types/jest": "^29.5.12", "@types/json2csv": "^4.4.0", "@types/jwt-decode": "^2.1.0", "@types/linkify-it": "^3.0.2", @@ -75,6 +75,8 @@ "@mui/icons-material": "^5.8.4", "@mui/material": "^5.9.2", "@mui/x-date-pickers": "^6.3.1", + "@radix-ui/react-alert-dialog": "1.0.5", + "@radix-ui/react-avatar": "^1.0.4", "@radix-ui/react-collapsible": "^1.0.3", "@radix-ui/react-dialog": "^1.0.4", "@radix-ui/react-dropdown-menu": "^2.0.4", @@ -82,8 +84,6 @@ "@radix-ui/react-scroll-area": "^1.0.3", "@radix-ui/react-select": "^1.2.2", "@radix-ui/react-slot": "^1.0.2", - "@radix-ui/react-avatar": "^1.0.4", - "@radix-ui/react-alert-dialog": "1.0.5", "@radix-ui/react-tooltip": "^1.0.7", "@sentry/browser": "^5.8.0", "@stripe/react-stripe-js": "^1.16.5", diff --git a/packages/client/serviceWorker/tsconfig.json b/packages/client/serviceWorker/tsconfig.json index ec0c5fb0b28..f393dcadb5f 100644 --- a/packages/client/serviceWorker/tsconfig.json +++ b/packages/client/serviceWorker/tsconfig.json @@ -1,7 +1,6 @@ { "extends": "../../tsconfig.base.json", "compilerOptions": { -// "composite": true, "lib": ["esnext", "webworker"], "target": "esnext", "module": "commonjs", @@ -11,6 +10,5 @@ "*" // resolve all absolute imports as imports relative to the client package ] } - }, -// "references": [{"path": "../"}] + } } diff --git a/packages/client/tsconfig.json b/packages/client/tsconfig.json index 58280d064ea..32bb2473e60 100644 --- a/packages/client/tsconfig.json +++ b/packages/client/tsconfig.json @@ -3,15 +3,10 @@ "compilerOptions": { "baseUrl": ".", "paths": { - "~/*": ["*"], - "static/*": ["../../static/*"] + "~/*": ["*"] }, "outDir": "lib", - "lib": ["esnext", "dom"], - "types": ["node"] + "lib": ["esnext", "dom"] }, - "files": [ - "client.tsx", - ], "exclude": ["serviceWorker", "**/node_modules"] } diff --git a/packages/client/types/modules.d.ts b/packages/client/types/modules.d.ts index 92293d0cbbd..28b06e27aa7 100644 --- a/packages/client/types/modules.d.ts +++ b/packages/client/types/modules.d.ts @@ -20,6 +20,7 @@ declare module 'emoji-mart/dist-modern/utils/data.js' declare module 'emoji-mart/dist-modern/components/picker/nimble-picker' declare module 'react-textarea-autosize' declare module 'react-copy-to-clipboard' +declare module 'tayden-clusterfck' declare let __webpack_public_path__: string declare const __PRODUCTION__: string diff --git a/packages/client/types/reactHTML4.d.ts b/packages/client/types/reactHTML4.d.ts new file mode 100644 index 00000000000..995d555df4a --- /dev/null +++ b/packages/client/types/reactHTML4.d.ts @@ -0,0 +1,15 @@ +import 'react' + +declare module 'react' { + export interface TdHTMLAttributes { + height?: string | number + width?: string | number + bgcolor?: string + } + export interface TableHTMLAttributes { + align?: 'center' | 'left' | 'right' + bgcolor?: string + height?: string | number + width?: string | number + } +} diff --git a/packages/client/ui/AlertDialog/AlertDialogContent.tsx b/packages/client/ui/AlertDialog/AlertDialogContent.tsx index dbcd0de0582..12d5a79355c 100644 --- a/packages/client/ui/AlertDialog/AlertDialogContent.tsx +++ b/packages/client/ui/AlertDialog/AlertDialogContent.tsx @@ -1,8 +1,8 @@ -import * as React from 'react' import * as AlertDialogPrimitive from '@radix-ui/react-alert-dialog' import clsx from 'clsx' +import * as React from 'react' import {AlertDialogOverlay} from './AlertDialogOverlay' -import {AlertDialogPortal} from './AlertDialog' +import {AlertDialogPortal} from './AlertDialogPortal' const AlertDialogContent = React.forwardRef< HTMLDivElement, diff --git a/packages/client/ui/AlertDialog/AlertDialogPortal.tsx b/packages/client/ui/AlertDialog/AlertDialogPortal.tsx index c4e8d56916f..f572b2d9baa 100644 --- a/packages/client/ui/AlertDialog/AlertDialogPortal.tsx +++ b/packages/client/ui/AlertDialog/AlertDialogPortal.tsx @@ -1,3 +1,3 @@ import * as AlertDialogPrimitive from '@radix-ui/react-alert-dialog' -const AlertDialogPortal = AlertDialogPrimitive.Portal +export const AlertDialogPortal = AlertDialogPrimitive.Portal diff --git a/packages/client/ui/AlertDialog/AlertDialogTrigger.tsx b/packages/client/ui/AlertDialog/AlertDialogTrigger.tsx index 0a20feddfc1..6b2d6149df4 100644 --- a/packages/client/ui/AlertDialog/AlertDialogTrigger.tsx +++ b/packages/client/ui/AlertDialog/AlertDialogTrigger.tsx @@ -1,3 +1,3 @@ import * as AlertDialogPrimitive from '@radix-ui/react-alert-dialog' -const AlertDialogTrigger = AlertDialogPrimitive.Trigger +export const AlertDialogTrigger = AlertDialogPrimitive.Trigger diff --git a/packages/client/utils/__tests__/parseEmailAddressList.test.ts b/packages/client/utils/__tests__/parseEmailAddressList.test.ts index a9778e7bebe..87c83ee894e 100644 --- a/packages/client/utils/__tests__/parseEmailAddressList.test.ts +++ b/packages/client/utils/__tests__/parseEmailAddressList.test.ts @@ -1,7 +1,12 @@ /* eslint-env jest */ import parseEmailAddressList from '../parseEmailAddressList' -const getAddressStr = (res) => res && res.parsedInvitees.map((val) => val.address).join(', ') +type Res = { + parsedInvitees: { + [other: string]: any + }[] +} +const getAddressStr = (res: Res) => res && res.parsedInvitees.map((val) => val.address).join(', ') describe('parseEmailAddressList', () => { it('validates a simple single email', () => { diff --git a/packages/client/utils/getBezierTimePercentGivenDistancePercent.ts b/packages/client/utils/getBezierTimePercentGivenDistancePercent.ts index af2b6ab346b..3b988aec450 100644 --- a/packages/client/utils/getBezierTimePercentGivenDistancePercent.ts +++ b/packages/client/utils/getBezierTimePercentGivenDistancePercent.ts @@ -10,7 +10,12 @@ const bezierLookup = [] as {x: number; y: number}[] const getBezierTimePercentGivenDistancePercent = (threshold: number, bezierCurve: string) => { if (bezierLookup.length === 0) { const re = /\(([^)]+)\)/ - const [x1, y1, x2, y2] = re.exec(bezierCurve)![1].split(',').map(Number) + const [x1, y1, x2, y2] = re.exec(bezierCurve)![1]!.split(',').map(Number) as [ + number, + number, + number, + number + ] // css bezier-curves imply a start of 0,0 and end of 1,1 const x0 = 0 const y0 = 0 @@ -32,9 +37,9 @@ const getBezierTimePercentGivenDistancePercent = (threshold: number, bezierCurve } let x for (let i = 1; i < bezierLookup.length; i++) { - const point = bezierLookup[i] + const point = bezierLookup[i]! if (point.y > threshold) { - x = bezierLookup[i - 1].x + x = bezierLookup[i - 1]!.x break } } diff --git a/packages/client/utils/screenBugs/Bug.ts b/packages/client/utils/screenBugs/Bug.ts index 536d0142887..0ab7411d40d 100644 --- a/packages/client/utils/screenBugs/Bug.ts +++ b/packages/client/utils/screenBugs/Bug.ts @@ -183,7 +183,7 @@ export default class Bug { this.bug.classList.remove('bug-dead') } - animate = (t) => { + animate = (t: any) => { if (!this.animating || !this.alive || !this.active) return this.going = requestAnimationFrame((t) => { this.animate(t) @@ -217,9 +217,9 @@ export default class Bug { this.angle_deg %= 360 if (this.angle_deg < 0) this.angle_deg += 360 - if (Math.abs(this.directions[this.near_edge] - this.angle_deg) > 15) { - const angle1 = this.directions[this.near_edge] - this.angle_deg - const angle2 = 360 - this.angle_deg + this.directions[this.near_edge] + if (Math.abs(this.directions[this.near_edge]! - this.angle_deg) > 15) { + const angle1 = this.directions[this.near_edge]! - this.angle_deg + const angle2 = 360 - this.angle_deg + this.directions[this.near_edge]! this.large_turn_angle_deg = Math.abs(angle1) < Math.abs(angle2) ? angle1 : angle2 this.edge_test_counter = 10 @@ -399,7 +399,7 @@ export default class Bug { let side = Math.round(Math.random() * 4 - 0.5) const d = document const e = d.documentElement - const g = d.getElementsByTagName('body')[0] + const g = d.getElementsByTagName('body')[0]! const windowX = window.innerWidth || e.clientWidth || g.clientWidth const windowY = window.innerHeight || e.clientHeight || g.clientHeight if (side > 3) side = 3 @@ -455,7 +455,7 @@ export default class Bug { let side = Math.round(Math.random() * 4 - 0.5) const d = document const e = d.documentElement - const g = d.getElementsByTagName('body')[0] + const g = d.getElementsByTagName('body')[0]! const windowX = window.innerWidth || e.clientWidth || g.clientWidth const windowY = window.innerHeight || e.clientHeight || g.clientHeight if (side > 3) side = 3 @@ -496,7 +496,7 @@ export default class Bug { const style = {} as Pos const d = document const e = d.documentElement - const g = d.getElementsByTagName('body')[0] + const g = d.getElementsByTagName('body')[0]! const windowX = window.innerWidth || e.clientWidth || g.clientWidth const windowY = window.innerHeight || e.clientHeight || g.clientHeight @@ -529,11 +529,11 @@ export default class Bug { this.drop(deathType) } - drop = (deathType) => { + drop = (deathType: any) => { const startPos = this.bug.top const d = document const e = d.documentElement - const g = d.getElementsByTagName('body')[0] + const g = d.getElementsByTagName('body')[0]! const pos = window.innerHeight || e.clientHeight || g.clientHeight const finalPos = pos - this.options.bugHeight const rotationRate = this.random(0, 20, true) @@ -545,7 +545,7 @@ export default class Bug { }) } - dropping = (t, startPos, finalPos, rotationRate, deathType) => { + dropping = (t: number, startPos: any, finalPos: any, rotationRate: any, deathType: any) => { const elapsedTime = t - this._lastTimestamp! const deltaPos = 0.002 * (elapsedTime * elapsedTime) let newPos = startPos + deltaPos diff --git a/packages/client/utils/screenBugs/BugController.ts b/packages/client/utils/screenBugs/BugController.ts index 132c1796103..330f729ad61 100644 --- a/packages/client/utils/screenBugs/BugController.ts +++ b/packages/client/utils/screenBugs/BugController.ts @@ -131,7 +131,7 @@ class BugDispatch { this.spawnDelay = [] for (let i = 0; i < numBugs; i++) { const delay = this.random(this.options.minDelay, this.options.maxDelay, true) - const thebug = this.bugs[i] + const thebug = this.bugs[i]! // fly the bug onto the page: this.spawnDelay[i] = window.setTimeout(() => { this.options.canFly ? thebug.flyIn() : thebug.walkIn() @@ -152,30 +152,30 @@ class BugDispatch { stop = () => { for (let i = 0; i < this.bugs.length; i++) { if (this.spawnDelay[i]) clearTimeout(this.spawnDelay[i]) - this.bugs[i].stop() + this.bugs[i]!.stop() } } end = () => { for (let i = 0; i < this.bugs.length; i++) { if (this.spawnDelay[i]) clearTimeout(this.spawnDelay[i]) - this.bugs[i].stop() - this.bugs[i].remove() + this.bugs[i]!.stop() + this.bugs[i]!.remove() } } reset = () => { this.stop() for (let i = 0; i < this.bugs.length; i++) { - this.bugs[i].reset() - this.bugs[i].walkIn() + this.bugs[i]!.reset() + this.bugs[i]!.walkIn() } } killAll = () => { for (let i = 0; i < this.bugs.length; i++) { if (this.spawnDelay[i]) clearTimeout(this.spawnDelay[i]) - this.bugs[i].die() + this.bugs[i]!.die() } } @@ -209,13 +209,13 @@ class BugDispatch { } const numBugs = this.bugs.length for (let i = 0; i < numBugs; i++) { - const pos = this.bugs[i].getPos() + const pos = this.bugs[i]!.getPos() if (pos) { if ( Math.abs(pos.top - posy) + Math.abs(pos.left - posx) < this.options.eventDistanceToBug && - !this.bugs[i].flyperiodical + !this.bugs[i]!.flyperiodical ) { - this.near_bug(this.bugs[i]) + this.near_bug(this.bugs[i]!) } } } @@ -233,7 +233,7 @@ class BugDispatch { let mode = this.options.mouseOver if (mode === 'random') { - mode = this.modes[this.random(0, this.modes.length - 1, true)] + mode = this.modes[this.random(0, this.modes.length - 1, true)]! } if (mode === 'fly') { diff --git a/packages/embedder/ai_models/OpenAIGeneration.ts b/packages/embedder/ai_models/OpenAIGeneration.ts index b5614b608c5..9818012edb4 100644 --- a/packages/embedder/ai_models/OpenAIGeneration.ts +++ b/packages/embedder/ai_models/OpenAIGeneration.ts @@ -6,8 +6,6 @@ import { GenerationOptions } from './AbstractModel' -const MAX_REQUEST_TIME_S = 3 * 60 - export type ModelId = 'gpt-3.5-turbo-0125' | 'gpt-4-turbo-preview' type OpenAIGenerationOptions = Omit @@ -27,7 +25,7 @@ function isValidModelId(object: any): object is ModelId { export class OpenAIGeneration extends AbstractGenerationModel { private openAIApi: OpenAI | null - private modelId: ModelId + private modelId!: ModelId constructor(config: GenerationModelConfig) { super(config) diff --git a/packages/embedder/embedder.ts b/packages/embedder/embedder.ts index f6762013d08..dccd9492a02 100644 --- a/packages/embedder/embedder.ts +++ b/packages/embedder/embedder.ts @@ -1,25 +1,25 @@ -import {Insertable} from 'kysely' import tracer from 'dd-trace' +import {Insertable} from 'kysely' import Redlock, {RedlockAbortSignal} from 'redlock' import 'parabol-server/initSentry' import getKysely from 'parabol-server/postgres/getKysely' import {DB} from 'parabol-server/postgres/pg' -import {refreshRetroDiscussionTopicsMeta as refreshRetroDiscussionTopicsMeta} from './indexing/retrospectiveDiscussionTopic' -import {orgIdsWithFeatureFlag} from './indexing/orgIdsWithFeatureFlag' import getModelManager, {ModelManager} from './ai_models/ModelManager' import {countWords} from './indexing/countWords' import {createEmbeddingTextFrom} from './indexing/createEmbeddingTextFrom' import { + completeJobTxn, + insertNewJobs, selectJobQueueItemById, + selectMetaToQueue, selectMetadataByJobQueueId, updateJobState } from './indexing/embeddingsTablesOps' -import {selectMetaToQueue} from './indexing/embeddingsTablesOps' -import {insertNewJobs} from './indexing/embeddingsTablesOps' -import {completeJobTxn} from './indexing/embeddingsTablesOps' -import {getRootDataLoader} from './indexing/getRootDataLoader' import {getRedisClient} from './indexing/getRedisClient' +import {getRootDataLoader} from './indexing/getRootDataLoader' +import {orgIdsWithFeatureFlag} from './indexing/orgIdsWithFeatureFlag' +import {refreshRetroDiscussionTopicsMeta} from './indexing/retrospectiveDiscussionTopic' /* * TODO List @@ -91,11 +91,11 @@ const maybeQueueMetadataItems = async (modelManager: ModelManager) => { model: item.model, state: 'queued' as const } - }) + }) as any[] const ejqRows = await insertNewJobs(ejqValues) - ejqRows.forEach((item) => { + ejqRows.forEach((item: any) => { const {refUpdatedAt} = ejqHash[makeKey(item)]! const score = new Date(refUpdatedAt).getTime() redisClient.zadd('embedder:queue', score, item.id) @@ -117,7 +117,7 @@ const dequeueAndEmbedUntilEmpty = async (modelManager: ModelManager) => { continue } const jobQueueId = parseInt(id, 10) - const jobQueueItem = await selectJobQueueItemById(jobQueueId) + const jobQueueItem = (await selectJobQueueItemById(jobQueueId)) as any if (!jobQueueItem) { console.log(`embedder: unable to fetch EmbeddingsJobQueue.id = ${id}`) continue @@ -131,7 +131,7 @@ const dequeueAndEmbedUntilEmpty = async (modelManager: ModelManager) => { continue } - let fullText = metadata?.fullText + let fullText = metadata?.fullText as string try { if (!fullText) { fullText = await createEmbeddingTextFrom(jobQueueItem, dataLoader) diff --git a/packages/embedder/indexing/createEmbeddingTextFrom.ts b/packages/embedder/indexing/createEmbeddingTextFrom.ts index 9d6e66b60e7..ce76c7fc380 100644 --- a/packages/embedder/indexing/createEmbeddingTextFrom.ts +++ b/packages/embedder/indexing/createEmbeddingTextFrom.ts @@ -1,14 +1,14 @@ import {Selectable} from 'kysely' -import {DB} from 'parabol-server/postgres/pg' import {DataLoaderWorker} from 'parabol-server/graphql/graphql' +import {DB} from 'parabol-server/postgres/pg' import {createText as createTextFromRetrospectiveDiscussionTopic} from './retrospectiveDiscussionTopic' export const createEmbeddingTextFrom = async ( item: Selectable, dataLoader: DataLoaderWorker -): Promise => { - switch (item.objectType) { +): Promise => { + switch ((item as any).objectType) { case 'retrospectiveDiscussionTopic': return createTextFromRetrospectiveDiscussionTopic(item, dataLoader) } diff --git a/packages/embedder/indexing/embeddingsTablesOps.ts b/packages/embedder/indexing/embeddingsTablesOps.ts index c74eb709708..4ce843248a9 100644 --- a/packages/embedder/indexing/embeddingsTablesOps.ts +++ b/packages/embedder/indexing/embeddingsTablesOps.ts @@ -1,8 +1,7 @@ -import {Insertable, Selectable, Updateable, sql} from 'kysely' +import {Insertable, RawBuilder, Selectable, Updateable, sql} from 'kysely' import getKysely from 'parabol-server/postgres/getKysely' import {DB} from 'parabol-server/postgres/pg' import {DBInsert} from '../embedder' -import {RawBuilder} from 'kysely' import numberVectorToString from './numberVectorToString' function unnestedArray(maybeArray: T[] | T): RawBuilder { @@ -24,7 +23,9 @@ export const selectMetadataByJobQueueId = async ( .selectFrom('EmbeddingsMetadata as em') .selectAll() .leftJoin('EmbeddingsJobQueue as ejq', (join) => - join.onRef('em.objectType', '=', 'ejq.objectType').onRef('em.refId', '=', 'ejq.refId') + join + .onRef('em.objectType', '=', 'ejq.objectType' as any) + .onRef('em.refId', '=', 'ejq.refId' as any) ) .where('ejq.id', '=', id) .executeTakeFirstOrThrow() @@ -52,16 +53,18 @@ export async function selectMetaToQueue( .where(({eb, not, or, and, exists, selectFrom}) => and([ or([ - not(eb('em.models', '@>', sql`ARRAY[${sql.ref('model')}]::varchar[]` as any) as any), + not( + eb('em.models' as any, '@>', sql`ARRAY[${sql.ref('model')}]::varchar[]` as any) as any + ), eb('em.models' as any, 'is', null) ]), not( exists( selectFrom('EmbeddingsJobQueue as ejq') .select('ejq.id') - .whereRef('em.objectType', '=', 'ejq.objectType') - .whereRef('em.refId', '=', 'ejq.refId') - .whereRef('ejq.model', '=', 'model' as any) + .whereRef('em.objectType', '=', 'ejq.objectType' as any) + .whereRef('em.refId', '=', 'ejq.refId' as any) + .whereRef('ejq.model' as any, '=', 'model' as any) ) ), eb('t.orgId', 'in', orgIds) @@ -104,7 +107,7 @@ export function insertNewJobs(ejqValues: Insertable[]) return pg .insertInto('EmbeddingsJobQueue') .values(ejqValues) - .returning(['id', 'objectType', 'refId']) + .returning(['id', 'objectType', 'refId'] as any) .execute() } @@ -123,11 +126,11 @@ export function completeJobTxn( const pg = getKysely() return pg.transaction().execute(async (trx) => { // get fields to update correct metadata row - const jobQueueItem = await trx + const jobQueueItem = (await trx .selectFrom('EmbeddingsJobQueue') - .select(['objectType', 'refId', 'model']) + .select(['objectType', 'refId', 'model'] as any) .where('id', '=', jobQueueId) - .executeTakeFirstOrThrow() + .executeTakeFirstOrThrow()) as any // (1) update metadata row const metadataColumnsToUpdate: { diff --git a/packages/embedder/indexing/retrospectiveDiscussionTopic.ts b/packages/embedder/indexing/retrospectiveDiscussionTopic.ts index f31aab74cc2..eb28b1bc3b0 100644 --- a/packages/embedder/indexing/retrospectiveDiscussionTopic.ts +++ b/packages/embedder/indexing/retrospectiveDiscussionTopic.ts @@ -1,4 +1,3 @@ -import {Selectable} from 'kysely' import prettier from 'prettier' import getRethink, {RethinkSchema} from 'parabol-server/database/rethinkDriver' @@ -12,8 +11,8 @@ import MeetingRetrospective, { isMeetingRetrospective } from 'parabol-server/database/types/MeetingRetrospective' -import {upsertEmbeddingsMetaRows} from './embeddingsTablesOps' import {AnyMeeting} from 'parabol-server/postgres/types/Meeting' +import {upsertEmbeddingsMetaRows} from './embeddingsTablesOps' const BATCH_SIZE = 1000 @@ -291,10 +290,7 @@ export const createTextFromNewMeetingDiscussionStage = async ( return markdown } -export const createText = async ( - item: Selectable, - dataLoader: DataLoaderWorker -): Promise => { +export const createText = async (item: any, dataLoader: DataLoaderWorker): Promise => { if (!item.refId) throw 'refId is undefined' const [newMeetingId, discussionId] = item.refId.split(':') if (!newMeetingId) throw new Error('newMeetingId cannot be undefined') diff --git a/packages/embedder/modules.d.ts b/packages/embedder/modules.d.ts new file mode 100644 index 00000000000..8a2be20ba0c --- /dev/null +++ b/packages/embedder/modules.d.ts @@ -0,0 +1,2 @@ +import '../server/types/modules' +import '../server/types/webpackEnv' diff --git a/packages/embedder/tsconfig.json b/packages/embedder/tsconfig.json index 1d179d08096..b75106d1a8a 100644 --- a/packages/embedder/tsconfig.json +++ b/packages/embedder/tsconfig.json @@ -3,13 +3,10 @@ "compilerOptions": { "baseUrl": "../", "paths": { - // when we import from lib, make goto-definition point to the src "parabol-server/*": ["server/*"], - "parabol-client/*": ["client/*"] + "parabol-client/*": ["client/*"], + "~/*": ["client/*"] }, - "outDir": "lib", - "lib": ["esnext"], - "types": ["node"] - }, - "files": ["../server/types/modules.d.ts"] + "lib": ["esnext"] + } } diff --git a/packages/gql-executor/RedisStream.ts b/packages/gql-executor/RedisStream.ts index 739480bd51d..173a493321a 100644 --- a/packages/gql-executor/RedisStream.ts +++ b/packages/gql-executor/RedisStream.ts @@ -2,8 +2,8 @@ import RedisInstance from 'parabol-server/utils/RedisInstance' type MessageValue = [prop: string, stringifiedData: string] type Message = [messageId: string, value: MessageValue] -type XReadGroupRes = [streamName: string, messages: Message[]] -export default class RedisStream implements AsyncIterableIterator { +type XReadGroupRes = [streamName: string, messages: [Message, ...Message[]]] +export default class RedisStream implements AsyncIterableIterator { private stream: string private consumerGroup: string // xreadgroup blocks until a response is received, so this needs its own connection @@ -19,7 +19,7 @@ export default class RedisStream implements AsyncIterableIterator { [Symbol.asyncIterator]() { return this } - async next() { + async next(): Promise> { const response = await this.redis.xreadgroup( 'GROUP', this.consumerGroup, diff --git a/packages/gql-executor/gqlExecutor.ts b/packages/gql-executor/gqlExecutor.ts index 2d4239b22a6..a3ce88d0853 100644 --- a/packages/gql-executor/gqlExecutor.ts +++ b/packages/gql-executor/gqlExecutor.ts @@ -2,9 +2,10 @@ import tracer from 'dd-trace' import {ServerChannel} from 'parabol-client/types/constEnums' import GQLExecutorChannelId from '../client/shared/gqlIds/GQLExecutorChannelId' import SocketServerChannelId from '../client/shared/gqlIds/SocketServerChannelId' -import executeGraphQL, {GQLRequest} from '../server/graphql/executeGraphQL' +import executeGraphQL from '../server/graphql/executeGraphQL' import '../server/initSentry' import '../server/monkeyPatchFetch' +import {GQLRequest} from '../server/types/custom' import RedisInstance from '../server/utils/RedisInstance' import RedisStream from './RedisStream' @@ -16,7 +17,7 @@ tracer.init({ }) tracer.use('ioredis').use('http').use('pg') -const {REDIS_URL, SERVER_ID} = process.env +const {SERVER_ID} = process.env interface PubSubPromiseMessage { jobId: string socketServerId: string @@ -26,7 +27,7 @@ interface PubSubPromiseMessage { const run = async () => { const publisher = new RedisInstance('gql_pub') const subscriber = new RedisInstance('gql_sub') - const executorChannel = GQLExecutorChannelId.join(SERVER_ID) + const executorChannel = GQLExecutorChannelId.join(SERVER_ID!) // on shutdown, remove consumer from the group process.on('SIGTERM', async () => { diff --git a/packages/gql-executor/modules.d.ts b/packages/gql-executor/modules.d.ts new file mode 100644 index 00000000000..8a2be20ba0c --- /dev/null +++ b/packages/gql-executor/modules.d.ts @@ -0,0 +1,2 @@ +import '../server/types/modules' +import '../server/types/webpackEnv' diff --git a/packages/gql-executor/tsconfig.json b/packages/gql-executor/tsconfig.json index 1d179d08096..5f1fdbf2d75 100644 --- a/packages/gql-executor/tsconfig.json +++ b/packages/gql-executor/tsconfig.json @@ -1,15 +1,14 @@ { "extends": "../../tsconfig.base.json", "compilerOptions": { + "esModuleInterop": true, "baseUrl": "../", "paths": { // when we import from lib, make goto-definition point to the src "parabol-server/*": ["server/*"], - "parabol-client/*": ["client/*"] + "parabol-client/*": ["client/*"], + "~/*": ["client/*"] }, - "outDir": "lib", - "lib": ["esnext"], - "types": ["node"] - }, - "files": ["../server/types/modules.d.ts"] + "lib": ["esnext"] + } } diff --git a/packages/server/__tests__/autoJoin.test.ts b/packages/server/__tests__/autoJoin.test.ts index 85bc9e3e222..3fe4564e6eb 100644 --- a/packages/server/__tests__/autoJoin.test.ts +++ b/packages/server/__tests__/autoJoin.test.ts @@ -1,11 +1,11 @@ import faker from 'faker' -import {getUserTeams, sendPublic, sendIntranet, signUp, signUpWithEmail} from './common' import getRethink from '../database/rethinkDriver' import createEmailVerification from '../email/createEmailVerification' +import {getUserTeams, sendIntranet, sendPublic} from './common' const signUpVerified = async (email: string) => { const password = faker.internet.password() - const signUp = await sendPublic({ + await sendPublic({ query: ` mutation SignUpWithPassword($email: ID!, $password: String!) { signUpWithPassword(email: $email, password: $password, params: "") { diff --git a/packages/server/__tests__/common.ts b/packages/server/__tests__/common.ts index f9ca34ab293..93c134b229b 100644 --- a/packages/server/__tests__/common.ts +++ b/packages/server/__tests__/common.ts @@ -199,5 +199,5 @@ export const getUserTeams = async (userId: string) => { } } }) - return user.data.user.teams + return user.data.user.teams as [{id: string}, ...{id: string}[]] } diff --git a/packages/server/__tests__/disableAnonymity.test.ts b/packages/server/__tests__/disableAnonymity.test.ts index 7143981aa36..1887c3357a0 100644 --- a/packages/server/__tests__/disableAnonymity.test.ts +++ b/packages/server/__tests__/disableAnonymity.test.ts @@ -89,8 +89,12 @@ const startRetro = async (teamId: string, authToken: string) => { }, authToken }) - - const meeting = startRetroQuery.data.startRetrospective.meeting + const meeting = startRetroQuery.data.startRetrospective.meeting as { + id: string + phases: { + reflectPrompts: [{id: string}] + }[] + } return meeting } @@ -134,7 +138,7 @@ test('By default all reflections are anonymous', async () => { expect(meetingSettings.disableAnonymity).toEqual(false) const meeting = await startRetro(teamId, authToken) - const reflectPrompts = meeting.phases.find(({reflectPrompts}) => !!reflectPrompts).reflectPrompts + const reflectPrompts = meeting.phases.find(({reflectPrompts}) => !!reflectPrompts)!.reflectPrompts const reflection = await addReflection(meeting.id, reflectPrompts[0].id, authToken) expect(reflection).toEqual({ @@ -153,7 +157,7 @@ test('Creator is visible when disableAnonymity is set', async () => { expect(updatedMeetingSettings.disableAnonymity).toEqual(true) const meeting = await startRetro(teamId, authToken) - const reflectPrompts = meeting.phases.find(({reflectPrompts}) => !!reflectPrompts).reflectPrompts + const reflectPrompts = meeting.phases.find(({reflectPrompts}) => !!reflectPrompts)!.reflectPrompts const reflection = await addReflection(meeting.id, reflectPrompts[0].id, authToken) expect(reflection).toEqual({ @@ -172,7 +176,7 @@ test('Super user can always read creatorId of a reflection', async () => { expect(meetingSettings.disableAnonymity).toEqual(false) const meeting = await startRetro(teamId, authToken) - const reflectPrompts = meeting.phases.find(({reflectPrompts}) => !!reflectPrompts).reflectPrompts + const reflectPrompts = meeting.phases.find(({reflectPrompts}) => !!reflectPrompts)!.reflectPrompts await addReflection(meeting.id, reflectPrompts[0].id, authToken) diff --git a/packages/server/__tests__/loginSAML.test.ts b/packages/server/__tests__/loginSAML.test.ts index 426f9606140..312bb3154e5 100644 --- a/packages/server/__tests__/loginSAML.test.ts +++ b/packages/server/__tests__/loginSAML.test.ts @@ -10,30 +10,6 @@ test.skip('SAML', async () => { const orgId = `${samlName}-orgId` const domain = 'example.com' - const _metadata = ` - - - - - - - MIICUDCCAbmgAwIBAgIBADANBgkqhkiG9w0BAQ0FADBFMQswCQYDVQQGEwJ1czELMAkGA1UECAwCQ0ExEzARBgNVBAoMCkV4YW1wbGUgQ28xFDASBgNVBAMMC2V4YW1wbGUuY29tMB4XDTIxMDkxMDA3NTkzMFoXDTI2MDkwOTA3NTkzMFowRTELMAkGA1UEBhMCdXMxCzAJBgNVBAgMAkNBMRMwEQYDVQQKDApFeGFtcGxlIENvMRQwEgYDVQQDDAtleGFtcGxlLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEArg9DZwR9v7Vok1IW+hIpYin9llPBh1MV5CxjfK596EwuadyQuko3jGv8qDlx4tG6JiGTjQfCuzJVAhYi2OKuKBqyJewKoen1uF0dRyws9n6zZl0GsVJkObdrNo5P6eib3VOsXPJ10RjxWsWx5WRur2dYdkOJFxC6zN1IbXSXYYMCAwEAAaNQME4wHQYDVR0OBBYEFKr/1y4R+kamPz623HnHM7tz6C4XMB8GA1UdIwQYMBaAFKr/1y4R+kamPz623HnHM7tz6C4XMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQENBQADgYEALKBl6QPk9HMB5V+GYu50XNFmzyuuXt3zAKMSYcyhxVSBCe6SKw1iqvvPza4rGp7DpeJI/8R3qBTuZqfl0rX624wvHGc4N9WubMLPejAn7dMu3oGfm9KUX+Um1RG0U6zsi9t3X90rroea/5SQvw/uAWUxS59U2r8massI/WFJKh8= - - - - - - - MIICUDCCAbmgAwIBAgIBADANBgkqhkiG9w0BAQ0FADBFMQswCQYDVQQGEwJ1czELMAkGA1UECAwCQ0ExEzARBgNVBAoMCkV4YW1wbGUgQ28xFDASBgNVBAMMC2V4YW1wbGUuY29tMB4XDTIxMDkxMDA3NTkzMFoXDTI2MDkwOTA3NTkzMFowRTELMAkGA1UEBhMCdXMxCzAJBgNVBAgMAkNBMRMwEQYDVQQKDApFeGFtcGxlIENvMRQwEgYDVQQDDAtleGFtcGxlLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEArg9DZwR9v7Vok1IW+hIpYin9llPBh1MV5CxjfK596EwuadyQuko3jGv8qDlx4tG6JiGTjQfCuzJVAhYi2OKuKBqyJewKoen1uF0dRyws9n6zZl0GsVJkObdrNo5P6eib3VOsXPJ10RjxWsWx5WRur2dYdkOJFxC6zN1IbXSXYYMCAwEAAaNQME4wHQYDVR0OBBYEFKr/1y4R+kamPz623HnHM7tz6C4XMB8GA1UdIwQYMBaAFKr/1y4R+kamPz623HnHM7tz6C4XMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQENBQADgYEALKBl6QPk9HMB5V+GYu50XNFmzyuuXt3zAKMSYcyhxVSBCe6SKw1iqvvPza4rGp7DpeJI/8R3qBTuZqfl0rX624wvHGc4N9WubMLPejAn7dMu3oGfm9KUX+Um1RG0U6zsi9t3X90rroea/5SQvw/uAWUxS59U2r8massI/WFJKh8= - - - - urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified - - - - ` - const verifyDomain = await sendIntranet({ query: ` mutation VerifyDomain($slug: ID!, $addDomains: [ID!], $orgId: ID!) { diff --git a/packages/server/__tests__/processRecurrence.test.ts b/packages/server/__tests__/processRecurrence.test.ts index f6e6c685715..fab6970bc9a 100644 --- a/packages/server/__tests__/processRecurrence.test.ts +++ b/packages/server/__tests__/processRecurrence.test.ts @@ -1,14 +1,13 @@ import ms from 'ms' import {RRule} from 'rrule' import getRethink from '../database/rethinkDriver' -import MeetingTeamPrompt from '../database/types/MeetingTeamPrompt' -import TeamPromptResponsesPhase from '../database/types/TeamPromptResponsesPhase' import MeetingRetrospective from '../database/types/MeetingRetrospective' +import MeetingTeamPrompt from '../database/types/MeetingTeamPrompt' import ReflectPhase from '../database/types/ReflectPhase' +import TeamPromptResponsesPhase from '../database/types/TeamPromptResponsesPhase' import generateUID from '../generateUID' import {insertMeetingSeries as insertMeetingSeriesQuery} from '../postgres/queries/insertMeetingSeries' import {getUserTeams, sendIntranet, signUp} from './common' -import createNewMeetingPhases from '../graphql/mutations/helpers/createNewMeetingPhases' const PROCESS_RECURRENCE = ` mutation { @@ -292,7 +291,11 @@ test('Should end the current retro meeting and start a new meeting', async () => facilitatorUserId: userId, scheduledEndTime: new Date(Date.now() - ms('5m')), meetingSeriesId, - templateId: 'startStopContinueTemplate' + templateId: 'startStopContinueTemplate', + disableAnonymity: false, + totalVotes: 5, + name: '', + maxVotesPerGroup: 5 }) // The last meeting in the series was created just over 24h ago, so the next one should start diff --git a/packages/server/__tests__/startRetrospective.test.ts b/packages/server/__tests__/startRetrospective.test.ts index 22ff21a7f12..17deae321e5 100644 --- a/packages/server/__tests__/startRetrospective.test.ts +++ b/packages/server/__tests__/startRetrospective.test.ts @@ -1,14 +1,8 @@ -import ms from 'ms' -import {RRule} from 'rrule' import getRethink from '../database/rethinkDriver' -import MeetingTeamPrompt from '../database/types/MeetingTeamPrompt' -import TeamPromptResponsesPhase from '../database/types/TeamPromptResponsesPhase' -import generateUID from '../generateUID' -import {insertMeetingSeries as insertMeetingSeriesQuery} from '../postgres/queries/insertMeetingSeries' -import {getUserTeams, sendIntranet, sendPublic, signUp} from './common' +import {getUserTeams, sendPublic, signUp} from './common' test('Retro is named Retro #1 by default', async () => { - const r = await getRethink() + await getRethink() const {userId, authToken} = await signUp() const {id: teamId} = (await getUserTeams(userId))[0] @@ -48,7 +42,7 @@ test('Retro is named Retro #1 by default', async () => { }) test('Recurring retro is named like RetroSeries Jan 1', async () => { - const r = await getRethink() + await getRethink() const {userId, authToken} = await signUp() const {id: teamId} = (await getUserTeams(userId))[0] @@ -81,7 +75,11 @@ test('Recurring retro is named like RetroSeries Jan 1', async () => { authToken }) - const formattedDate = now.toLocaleDateString('en-US', {month: 'short', day: 'numeric'}, 'UTC') + const formattedDate = now.toLocaleDateString('en-US', { + month: 'short', + day: 'numeric', + timeZone: 'UTC' + }) expect(newRetro).toMatchObject({ data: { startRetrospective: { diff --git a/packages/server/dataloader/__tests__/isCompanyDomain.test.ts b/packages/server/dataloader/__tests__/isCompanyDomain.test.ts index 172958a60d6..d364d2a7d61 100644 --- a/packages/server/dataloader/__tests__/isCompanyDomain.test.ts +++ b/packages/server/dataloader/__tests__/isCompanyDomain.test.ts @@ -1,7 +1,5 @@ -import faker from 'faker' import '../../../../scripts/webpack/utils/dotenv' import getDataLoader from '../../graphql/getDataLoader' -import getPg from '../../postgres/getPg' const dataloader = getDataLoader() diff --git a/packages/server/dataloader/__tests__/isOrgVerified.test.ts b/packages/server/dataloader/__tests__/isOrgVerified.test.ts index b12897d4b3a..58247c515ab 100644 --- a/packages/server/dataloader/__tests__/isOrgVerified.test.ts +++ b/packages/server/dataloader/__tests__/isOrgVerified.test.ts @@ -1,18 +1,22 @@ /* eslint-env jest */ -import {MasterPool, r} from 'rethinkdb-ts' -import getRedis from '../../utils/getRedis' +import {r} from 'rethinkdb-ts' import getRethinkConfig from '../../database/getRethinkConfig' import getRethink from '../../database/rethinkDriver' -import isUserVerified from '../../utils/isUserVerified' +import OrganizationUser from '../../database/types/OrganizationUser' import generateUID from '../../generateUID' +import {DataLoaderWorker} from '../../graphql/graphql' +import getRedis from '../../utils/getRedis' +import isUserVerified from '../../utils/isUserVerified' +import RootDataLoader from '../RootDataLoader' import {isOrgVerified} from '../customLoaderMakers' jest.mock('../../database/rethinkDriver') jest.mock('../../utils/isUserVerified') -getRethink.mockImplementation(() => { - return r +jest.mocked(getRethink).mockImplementation(() => { + return r as any }) -isUserVerified.mockImplementation(() => { + +jest.mocked(isUserVerified).mockImplementation(() => { return true }) @@ -24,7 +28,7 @@ const testConfig = { db: TEST_DB } -const createTables = async (...tables: string) => { +const createTables = async (...tables: string[]) => { for (const tableName of tables) { const structure = await r .db('rethinkdb') @@ -40,9 +44,10 @@ const createTables = async (...tables: string) => { } } -type TestOrganizationUser = Pick< - OrganizationUser, - 'inactive' | 'joinedAt' | 'removedAt' | 'role' | 'userId' +type TestOrganizationUser = Partial< + Pick & { + domain: string + } > const userLoader = { @@ -61,9 +66,9 @@ const dataLoader = { users: userLoader, isCompanyDomain: isCompanyDomainLoader } - return loaders[loader] + return loaders[loader as keyof typeof loaders] }) -} +} as any as DataLoaderWorker const addOrg = async ( activeDomain: string | null, @@ -101,10 +106,10 @@ const addOrg = async ( return orgId } -const isOrgVerifiedLoader = isOrgVerified(dataLoader) +const isOrgVerifiedLoader = isOrgVerified(dataLoader as any as RootDataLoader) beforeAll(async () => { - const conn = await r.connectPool(testConfig) + await r.connectPool(testConfig) try { await r.dbDrop(TEST_DB).run() } catch (e) { @@ -121,7 +126,7 @@ afterEach(async () => { }) afterAll(async () => { - await r.getPoolMaster().drain() + await r.getPoolMaster()?.drain() getRedis().quit() }) @@ -203,12 +208,12 @@ test('Empty org does not throw', async () => { }) test('Orgs with verified emails from different domains do not qualify', async () => { - const org1 = await addOrg('parabol.co', [ + await addOrg('parabol.co', [ { joinedAt: new Date('2023-09-06'), userId: 'founder1', domain: 'not-parabol.co' - } + } as any ]) const isVerified = await isOrgVerifiedLoader.load('parabol.co') diff --git a/packages/server/dataloader/__tests__/usersCustomRedisQueries.test.ts b/packages/server/dataloader/__tests__/usersCustomRedisQueries.test.ts index 0aa1d0a3162..50fcc7fa77f 100644 --- a/packages/server/dataloader/__tests__/usersCustomRedisQueries.test.ts +++ b/packages/server/dataloader/__tests__/usersCustomRedisQueries.test.ts @@ -1,6 +1,7 @@ import faker from 'faker' import '../../../../scripts/webpack/utils/dotenv' import getDataLoader from '../../graphql/getDataLoader' +import isValid from '../../graphql/isValid' import getPg from '../../postgres/getPg' afterAll(async () => { @@ -17,16 +18,19 @@ test('Result is mapped to correct id', async () => { const dataloader = getDataLoader() const expectedUsers = faker.helpers.shuffle( - (await pg.query('SELECT "id", "email" FROM "User" LIMIT 100')).rows + (await pg.query('SELECT "id", "email" FROM "User" LIMIT 100')).rows as { + id: string + email: string + }[] ) const userIds = expectedUsers.map(({id}) => id) - const actualUsers = (await (dataloader.get('users') as any).loadMany(userIds)).map( - ({id, email}) => ({ + const actualUsers = (await dataloader.get('users').loadMany(userIds)) + .filter(isValid) + .map(({id, email}) => ({ id, email - }) - ) + })) console.log('Ran with #users:', actualUsers.length) diff --git a/packages/server/email/inlineImages.ts b/packages/server/email/inlineImages.ts index d02c7bf6448..176a10d5798 100644 --- a/packages/server/email/inlineImages.ts +++ b/packages/server/email/inlineImages.ts @@ -20,7 +20,7 @@ const getFile = async (pathname: string) => { try { const res = await fetch(pathname) if (res.status !== 200) return null - data = await res.buffer() + data = await (res as any).buffer() } catch (e) { return null } @@ -42,7 +42,7 @@ const inlineImages = async (html: string) => { $('body') .find('img') .each((_i, img) => { - const pathname = $(img).attr('src') + const pathname = $(img).attr('src') as keyof typeof cidDict if (!pathname) return cidDict[pathname] = cidDict[pathname] || generateUID() + path.extname(pathname) $(img).attr('src', `cid:${cidDict[pathname]}`) @@ -51,7 +51,7 @@ const inlineImages = async (html: string) => { const files = await Promise.all(uniquePathnames.map(getFile)) const options = files.map((data, idx) => { if (!data) return null - const pathname = uniquePathnames[idx] + const pathname = uniquePathnames[idx] as keyof typeof cidDict const filename = cidDict[pathname] return {data, filename} }) diff --git a/packages/server/generateUID.ts b/packages/server/generateUID.ts index 15d3a616e70..822843fa52d 100644 --- a/packages/server/generateUID.ts +++ b/packages/server/generateUID.ts @@ -8,7 +8,7 @@ const SEQ_BIT_LEN = 12 const TS_OFFSET = BigInt(MACHINE_ID_BIT_LEN + SEQ_BIT_LEN) const MID_OFFSET = BigInt(SEQ_BIT_LEN) const BIG_ZERO = BigInt(0) -const MAX_SEQ = 2 ** SEQ_BIT_LEN - 1 +export const MAX_SEQ = 2 ** SEQ_BIT_LEN - 1 // if MID overflows, we will generate duplicate ids, throw instead if (MID < 0 || MID > 2 ** MACHINE_ID_BIT_LEN - 1) { diff --git a/packages/server/graphql/executeGraphQL.ts b/packages/server/graphql/executeGraphQL.ts index 6b6ad34ea72..8fea40bc2a5 100644 --- a/packages/server/graphql/executeGraphQL.ts +++ b/packages/server/graphql/executeGraphQL.ts @@ -7,30 +7,13 @@ import tracer from 'dd-trace' import {graphql} from 'graphql' import {FormattedExecutionResult} from 'graphql/execution/execute' -import AuthToken from '../database/types/AuthToken' +import type {GQLRequest} from '../types/custom' import CompiledQueryCache from './CompiledQueryCache' import getDataLoader from './getDataLoader' import getRateLimiter from './getRateLimiter' import privateSchema from './private/rootSchema' import publicSchema from './public/rootSchema' -export interface GQLRequest { - authToken: AuthToken - ip?: string - socketId?: string - variables?: {[key: string]: any} - docId?: string - query?: string - rootValue?: {[key: string]: any} - dataLoaderId?: string - // true if the query is on the private schema - isPrivate?: boolean - // true if the query is ad-hoc (e.g. GraphiQL, CLI) - isAdHoc?: boolean - // Datadog opentracing span of the calling server - carrier?: any -} - const queryCache = new CompiledQueryCache() const executeGraphQL = async (req: GQLRequest) => { diff --git a/packages/server/package.json b/packages/server/package.json index 68cfcfbb846..62295579ced 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -32,6 +32,7 @@ "@types/bcryptjs": "^2.4.2", "@types/cheerio": "^0.22.30", "@types/dotenv": "^6.1.1", + "@types/faker": "^5.5.9", "@types/graphql": "^14.5.0", "@types/html-minifier-terser": "5.1.2", "@types/jest": "^29.5.1", diff --git a/packages/server/tsconfig.json b/packages/server/tsconfig.json index a1a9c3130df..bc89d53cbbe 100644 --- a/packages/server/tsconfig.json +++ b/packages/server/tsconfig.json @@ -8,24 +8,16 @@ "parabol-client/*": ["client/*"], "~/*": ["client/*"] }, - "lib": ["esnext", "dom"], - "types": ["node", "jest", "jest-extended"] + "lib": ["esnext", "dom"] }, "exclude": [ "**/node_modules", "types/githubTypes.ts", "postgres/migrationTemplate.ts", - "graphql/intranetSchema/sdl/resolverTypes.ts" - ], - "files": [ - "types/webpackEnv.ts", - "types/modules.d.ts", - "server.ts", - "../client/modules/email/components/SummaryEmail/MeetingSummaryEmail/MeetingSummaryEmail.tsx" - ], - "include": ["graphql/**/*.ts"] - - // if "include" or "files" is added, even if they are empty arrays, then strictNullChecks breaks - // repro: https://www.typescriptlang.org/play?strictFunctionTypes=false&strictPropertyInitialization=false&strictBindCallApply=false&noImplicitThis=false&noImplicitReturns=false&alwaysStrict=false&declaration=false&experimentalDecorators=false&emitDecoratorMetadata=false&target=6&ts=3.5.1#code/C4TwDgpgBA8gRgKygXigbwFBSgWwIYhwQDKwATgIJlkD8AXFAM7kCWAdgOYDaAuhgL4ZQkKFTIpYiLgHJ8hEuTHS+AYwD2bZlDwS2AVwA2B7Y21sQJ0dQx4AdADM1ZAKJ4VACwAUngF4BKFAA+KH8MIA + "database/migrations/**/*", + "postgres/migrations/**/*", + "graphql/intranetSchema/sdl/resolverTypes.ts", + "billing/debug.ts" + ] } diff --git a/packages/server/types/custom.d.ts b/packages/server/types/custom.d.ts index 34587f968c4..2fc4dba2ce8 100644 --- a/packages/server/types/custom.d.ts +++ b/packages/server/types/custom.d.ts @@ -1,3 +1,5 @@ +import '../../client/types/reactHTML4' +import type AuthToken from '../database/types/AuthToken' export interface OAuth2Success { access_token: string token_type: string @@ -17,3 +19,19 @@ export interface OAuth2Error { error_description?: string error_uri?: string } +export interface GQLRequest { + authToken: AuthToken + ip?: string + socketId?: string + variables?: {[key: string]: any} + docId?: string + query?: string + rootValue?: {[key: string]: any} + dataLoaderId?: string + // true if the query is on the private schema + isPrivate?: boolean + // true if the query is ad-hoc (e.g. GraphiQL, CLI) + isAdHoc?: boolean + // Datadog opentracing span of the calling server + carrier?: any +} diff --git a/packages/server/types/modules.d.ts b/packages/server/types/modules.d.ts index c79e5a0b011..9b16b604830 100644 --- a/packages/server/types/modules.d.ts +++ b/packages/server/types/modules.d.ts @@ -21,6 +21,7 @@ declare module 'node-env-flag' declare module '*getProjectRoot' declare module 'tayden-clusterfck' declare module 'unicode-substring' +declare module 'jest-extended' declare module 'json2csv/lib/JSON2CSVParser' declare module 'object-hash' declare module 'string-score' diff --git a/packages/server/utils/__tests__/isRequestToJoinDomainAllowed.test.ts b/packages/server/utils/__tests__/isRequestToJoinDomainAllowed.test.ts index 3c65dff93cb..6858d2854cf 100644 --- a/packages/server/utils/__tests__/isRequestToJoinDomainAllowed.test.ts +++ b/packages/server/utils/__tests__/isRequestToJoinDomainAllowed.test.ts @@ -1,16 +1,16 @@ /* eslint-env jest */ -import {MasterPool, r} from 'rethinkdb-ts' -import getRedis from '../getRedis' -import RedisLockQueue from '../RedisLockQueue' -import sleep from 'parabol-client/utils/sleep' +import {r} from 'rethinkdb-ts' import getRethinkConfig from '../../database/getRethinkConfig' import getRethink from '../../database/rethinkDriver' -import {getEligibleOrgIdsByDomain} from '../isRequestToJoinDomainAllowed' +import OrganizationUser from '../../database/types/OrganizationUser' import generateUID from '../../generateUID' +import {DataLoaderWorker} from '../../graphql/graphql' +import getRedis from '../getRedis' +import {getEligibleOrgIdsByDomain} from '../isRequestToJoinDomainAllowed' jest.mock('../../database/rethinkDriver') -getRethink.mockImplementation(() => { - return r +jest.mocked(getRethink).mockImplementation(() => { + return r as any }) const TEST_DB = 'isRequestToJoinDomainAllowedTest' @@ -21,7 +21,7 @@ const testConfig = { db: TEST_DB } -const createTables = async (...tables: string) => { +const createTables = async (...tables: string[]) => { for (const tableName of tables) { const structure = await r .db('rethinkdb') @@ -37,9 +37,8 @@ const createTables = async (...tables: string) => { } } -type TestOrganizationUser = Pick< - OrganizationUser, - 'inactive' | 'joinedAt' | 'removedAt' | 'role' | 'userId' +type TestOrganizationUser = Partial< + Pick > const addOrg = async ( @@ -88,12 +87,12 @@ const dataLoader = { users: userLoader, isCompanyDomain: isCompanyDomainLoader } - return loaders[loader] + return loaders[loader as keyof typeof loaders] }) -} +} as any as DataLoaderWorker beforeAll(async () => { - const conn = await r.connectPool(testConfig) + await r.connectPool(testConfig) try { await r.dbDrop(TEST_DB).run() } catch (e) { @@ -109,7 +108,7 @@ afterEach(async () => { }) afterAll(async () => { - await r.getPoolMaster().drain() + await r.getPoolMaster()?.drain() getRedis().quit() }) @@ -126,7 +125,7 @@ test('Founder is billing lead', async () => { } ]) - const orgIds = await getEligibleOrgIdsByDomain('parabol.co', 'newUser', dataLoader) + await getEligibleOrgIdsByDomain('parabol.co', 'newUser', dataLoader) expect(userLoader.loadMany).toHaveBeenCalledTimes(1) expect(userLoader.loadMany).toHaveBeenCalledWith(['user1']) }) @@ -148,7 +147,7 @@ test('Org with noPromptToJoinOrg feature flag is ignored', async () => { {featureFlags: ['noPromptToJoinOrg']} ) - const orgIds = await getEligibleOrgIdsByDomain('parabol.co', 'newUser', dataLoader) + await getEligibleOrgIdsByDomain('parabol.co', 'newUser', dataLoader) expect(userLoader.loadMany).toHaveBeenCalledTimes(0) }) @@ -170,7 +169,7 @@ test('Inactive founder is ignored', async () => { } ]) - const orgIds = await getEligibleOrgIdsByDomain('parabol.co', 'newUser', dataLoader) + await getEligibleOrgIdsByDomain('parabol.co', 'newUser', dataLoader) // implementation detail, important is only that no user was loaded expect(userLoader.loadMany).toHaveBeenCalledTimes(1) expect(userLoader.loadMany).toHaveBeenCalledWith([]) @@ -195,7 +194,7 @@ test('Non-founder billing lead is checked', async () => { } ]) - const orgIds = await getEligibleOrgIdsByDomain('parabol.co', 'newUser', dataLoader) + await getEligibleOrgIdsByDomain('parabol.co', 'newUser', dataLoader) expect(userLoader.loadMany).toHaveBeenCalledTimes(1) expect(userLoader.loadMany).toHaveBeenCalledWith(['billing1']) }) @@ -212,7 +211,7 @@ test('Founder is checked even when not billing lead', async () => { } ]) - const orgIds = await getEligibleOrgIdsByDomain('parabol.co', 'newUser', dataLoader) + await getEligibleOrgIdsByDomain('parabol.co', 'newUser', dataLoader) expect(userLoader.loadMany).toHaveBeenCalledTimes(1) expect(userLoader.loadMany).toHaveBeenCalledWith(['user1']) }) @@ -239,7 +238,7 @@ test('All matching orgs are checked', async () => { } ]) - const orgIds = await getEligibleOrgIdsByDomain('parabol.co', 'newUser', dataLoader) + await getEligibleOrgIdsByDomain('parabol.co', 'newUser', dataLoader) // implementation detail, important is only that both users were loaded expect(userLoader.loadMany).toHaveBeenCalledTimes(2) expect(userLoader.loadMany).toHaveBeenCalledWith(['founder1']) @@ -249,12 +248,12 @@ test('All matching orgs are checked', async () => { test('Empty org does not throw', async () => { await addOrg('parabol.co', []) - const orgIds = await getEligibleOrgIdsByDomain('parabol.co', 'newUser', dataLoader) + await getEligibleOrgIdsByDomain('parabol.co', 'newUser', dataLoader) expect(userLoader.loadMany).toHaveBeenCalledTimes(0) }) test('No org does not throw', async () => { - const orgIds = await getEligibleOrgIdsByDomain('example.com', 'newUser', dataLoader) + await getEligibleOrgIdsByDomain('example.com', 'newUser', dataLoader) expect(userLoader.loadMany).toHaveBeenCalledTimes(0) }) @@ -267,7 +266,7 @@ test('1 person orgs are ignored', async () => { } ]) - const orgIds = await getEligibleOrgIdsByDomain('parabol.co', 'newUser', dataLoader) + await getEligibleOrgIdsByDomain('parabol.co', 'newUser', dataLoader) expect(userLoader.loadMany).toHaveBeenCalledTimes(0) }) @@ -283,12 +282,12 @@ test('Org matching the user are ignored', async () => { } ]) - const orgIds = await getEligibleOrgIdsByDomain('parabol.co', 'newUser', dataLoader) + await getEligibleOrgIdsByDomain('parabol.co', 'newUser', dataLoader) expect(userLoader.loadMany).toHaveBeenCalledTimes(0) }) test('Only the biggest org with verified emails qualify', async () => { - const org = await addOrg('parabol.co', [ + await addOrg('parabol.co', [ { joinedAt: new Date('2023-09-06'), userId: 'founder1' @@ -350,7 +349,7 @@ test('Only the biggest org with verified emails qualify', async () => { ] } } - return userIds.map((id) => ({ + return userIds.map((id: keyof typeof users) => ({ id, ...users[id] })) @@ -423,7 +422,7 @@ test('All the biggest orgs with verified emails qualify', async () => { ] } } - return userIds.map((id) => ({ + return userIds.map((id: keyof typeof users) => ({ id, ...users[id] })) @@ -452,7 +451,7 @@ test('Team trumps starter tier with more users org', async () => { ], {tier: 'team'} ) - const biggerStarterOrg = await addOrg('parabol.co', [ + await addOrg('parabol.co', [ { joinedAt: new Date('2023-09-06'), userId: 'founder2' @@ -504,7 +503,7 @@ test('Team trumps starter tier with more users org', async () => { ] } } - return userIds.map((id) => ({ + return userIds.map((id: keyof typeof users) => ({ id, ...users[id] })) @@ -533,7 +532,7 @@ test('Enterprise trumps team tier with more users org', async () => { ], {tier: 'enterprise'} ) - const starterOrg = await addOrg( + await addOrg( 'parabol.co', [ { @@ -589,7 +588,7 @@ test('Enterprise trumps team tier with more users org', async () => { ] } } - return userIds.map((id) => ({ + return userIds.map((id: keyof typeof users) => ({ id, ...users[id] })) @@ -604,7 +603,7 @@ test('Enterprise trumps team tier with more users org', async () => { }) test('Orgs with verified emails from different domains do not qualify', async () => { - const org1 = await addOrg('parabol.co', [ + await addOrg('parabol.co', [ { joinedAt: new Date('2023-09-06'), userId: 'founder1' diff --git a/packages/server/utils/__tests__/rateLimiters/InMemoryRateLimiter.test.ts b/packages/server/utils/__tests__/rateLimiters/InMemoryRateLimiter.test.ts index 01f4fa4394a..3b2478aa9d6 100644 --- a/packages/server/utils/__tests__/rateLimiters/InMemoryRateLimiter.test.ts +++ b/packages/server/utils/__tests__/rateLimiters/InMemoryRateLimiter.test.ts @@ -14,7 +14,7 @@ describe('InMemoryRateLimiter', () => { } beforeEach(() => { - jest.useFakeTimers('modern') + jest.useFakeTimers() }) afterEach(() => { diff --git a/packages/server/utils/getGraphQLExecutor.ts b/packages/server/utils/getGraphQLExecutor.ts index bc70b875316..759f21bade2 100644 --- a/packages/server/utils/getGraphQLExecutor.ts +++ b/packages/server/utils/getGraphQLExecutor.ts @@ -1,7 +1,7 @@ import {ExecutionResult} from 'graphql' import {ServerChannel} from 'parabol-client/types/constEnums' +import type {GQLRequest} from '../types/custom' import SocketServerChannelId from '../../client/shared/gqlIds/SocketServerChannelId' -import {GQLRequest} from '../graphql/executeGraphQL' import PubSubPromise from './PubSubPromise' let pubsub: PubSubPromise diff --git a/packages/server/utils/uwsGetHeaders.ts b/packages/server/utils/uwsGetHeaders.ts index 9fd7bdcdc02..f51fd27e78f 100644 --- a/packages/server/utils/uwsGetHeaders.ts +++ b/packages/server/utils/uwsGetHeaders.ts @@ -1,7 +1,7 @@ import {HttpRequest} from 'uWebSockets.js' const uwsGetHeaders = (req: HttpRequest) => { - const reqHeaders = {} + const reqHeaders: Record = {} req.forEach((key, value) => { reqHeaders[key] = value }) diff --git a/scripts/webpack/utils/getProjectRoot.d.ts b/scripts/webpack/utils/getProjectRoot.d.ts new file mode 100644 index 00000000000..436f1feb4c9 --- /dev/null +++ b/scripts/webpack/utils/getProjectRoot.d.ts @@ -0,0 +1,2 @@ +declare function getProjectRoot(): string +export default getProjectRoot diff --git a/yarn.lock b/yarn.lock index dc34fd16fae..817e730db40 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7565,6 +7565,11 @@ "@types/qs" "*" "@types/serve-static" "*" +"@types/faker@^5.5.9": + version "5.5.9" + resolved "https://registry.yarnpkg.com/@types/faker/-/faker-5.5.9.tgz#588ede92186dc557bff8341d294335d50d255f0c" + integrity sha512-uCx6mP3UY5SIO14XlspxsGjgaemrxpssJI0Ol+GfhxtcKpv9pgRZYsS4eeKeHVLje6Qtc8lGszuBI461+gVZBA== + "@types/fbjs@^3.0.4": version "3.0.4" resolved "https://registry.yarnpkg.com/@types/fbjs/-/fbjs-3.0.4.tgz#272faf44b6a24d24d6fdf36ed895b47436e6c125" @@ -7674,6 +7679,14 @@ expect "^29.0.0" pretty-format "^29.0.0" +"@types/jest@^29.5.12": + version "29.5.12" + resolved "https://registry.yarnpkg.com/@types/jest/-/jest-29.5.12.tgz#7f7dc6eb4cf246d2474ed78744b05d06ce025544" + integrity sha512-eDC8bTvT/QhYdxJAulQikueigY5AsdBRH2yDKW3yveW7svY3+DzN84/2NUgkw10RTiJbWqZrTtoGVdYlvFJdLw== + dependencies: + expect "^29.0.0" + pretty-format "^29.0.0" + "@types/js-yaml@^4.0.0": version "4.0.5" resolved "https://registry.yarnpkg.com/@types/js-yaml/-/js-yaml-4.0.5.tgz#738dd390a6ecc5442f35e7f03fa1431353f7e138" @@ -9704,9 +9717,9 @@ camelcase@^6.2.0: integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== caniuse-lite@^1.0.30001426, caniuse-lite@^1.0.30001517, caniuse-lite@^1.0.30001580, caniuse-lite@~1.0.0: - version "1.0.30001594" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001594.tgz#bea552414cd52c2d0c985ed9206314a696e685f5" - integrity sha512-VblSX6nYqyJVs8DKFMldE2IVCJjZ225LW00ydtUWwh5hk9IfkTOffO6r8gJNsH0qqqeAF8KrbMYA2VEwTlGW5g== + version "1.0.30001600" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001600.tgz#93a3ee17a35aa6a9f0c6ef1b2ab49507d1ab9079" + integrity sha512-+2S9/2JFhYmYaDpZvo0lKkfvuKIglrx68MwOBqMGHhQsNkLjB5xtc/TGoEPs+MxjSyN/72qer2g97nzR641mOQ== capital-case@^1.0.4: version "1.0.4" @@ -11305,7 +11318,6 @@ draft-js-utils@^1.4.0: "draft-js@https://github.com/mattkrick/draft-js/tarball/559a21968370c4944511657817d601a6c4ade0f6": version "0.10.5" - uid "025fddba56f21aaf3383aee778e0b17025c9a7bc" resolved "https://github.com/mattkrick/draft-js/tarball/559a21968370c4944511657817d601a6c4ade0f6#025fddba56f21aaf3383aee778e0b17025c9a7bc" dependencies: fbjs "^0.8.15" @@ -20384,7 +20396,19 @@ tar@^4.4.13: safe-buffer "^5.2.1" yallist "^3.1.1" -tar@^6.0.2, tar@^6.1.0, tar@^6.1.11, tar@^6.1.2: +tar@^6.0.2: + version "6.2.1" + resolved "https://registry.yarnpkg.com/tar/-/tar-6.2.1.tgz#717549c541bc3c2af15751bea94b1dd068d4b03a" + integrity sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A== + dependencies: + chownr "^2.0.0" + fs-minipass "^2.0.0" + minipass "^5.0.0" + minizlib "^2.1.1" + mkdirp "^1.0.3" + yallist "^4.0.0" + +tar@^6.1.0, tar@^6.1.11, tar@^6.1.2: version "6.2.0" resolved "https://registry.yarnpkg.com/tar/-/tar-6.2.0.tgz#b14ce49a79cb1cd23bc9b016302dea5474493f73" integrity sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==