- {lines.map( ( { gurmukhi, id } ) => (
+ {lines?.map( ( { gurmukhi, id } ) => (
{
const { local: { hotkeys, display: { lineEnding } } } = useContext( SettingsContext )
- const lines = useCurrentLines()
- const [ line ] = useCurrentLine()
- const { typeId } = line || {}
+ const { lines, line } = useContent()
// Get Shabad, writer, sources for getting the author
- const { shabad } = useContext( ContentContext )
const writers = useContext( WritersContext )
const recommendedSources = useContext( RecommendedSourcesContext )
@@ -32,7 +30,7 @@ const CopyHotkeys = ( { children }: CopyHotkeysProps ) => {
LANGUAGES.punjabi,
LANGUAGES.spanish,
] ),
- ( line ) => customiseLine( line, { lineEnding, typeId } ),
+ ( line ) => customiseLine( line, { lineEnding, typeId: line?.typeId } ),
)
// Get all transliterators
@@ -43,14 +41,14 @@ const CopyHotkeys = ( { children }: CopyHotkeysProps ) => {
LANGUAGES.urdu,
] ),
( transliterate ) => () => transliterate(
- customiseLine( line.gurmukhi, { lineEnding, typeId } ),
+ customiseLine( line?.gurmukhi, { lineEnding, typeId: line?.typeId } ),
),
)
const getAuthor = () => {
if ( !line ) return ''
- const { sourceId, writerId } = shabad || line.shabad
+ const { sourceId, writerId } = content?.type === 'shabad' ? content.shabad : line.shabad
const { sourcePage } = line
const { pageNameEnglish: pageName } = recommendedSources[ sourceId ]
@@ -59,7 +57,7 @@ const CopyHotkeys = ( { children }: CopyHotkeysProps ) => {
return `${writerName} - ${SOURCE_ABBREVIATIONS[ sourceId ]} - ${pageName} ${sourcePage}`
}
- const getAllLines = () => lines.map( ( { gurmukhi } ) => gurmukhi ).join( ' ' )
+ const getAllLines = () => lines?.map( ( { gurmukhi } ) => gurmukhi ).join( ' ' )
const copyToClipboard = useCopyToClipboard()
diff --git a/apps/frontend/src/components/NavigatorHotkeys.tsx b/apps/frontend/src/components/NavigatorHotkeys.tsx
index b9669494..4d8ebdd4 100644
--- a/apps/frontend/src/components/NavigatorHotkeys.tsx
+++ b/apps/frontend/src/components/NavigatorHotkeys.tsx
@@ -2,10 +2,10 @@ import { noop } from 'lodash'
import { useCallback, useContext, useEffect } from 'react'
import { getJumpLines } from '~/helpers/auto-jump'
-import { ContentContext, HistoryContext, SettingsContext } from '~/helpers/contexts'
+import { HistoryContext, SettingsContext } from '~/helpers/contexts'
import { LINE_HOTKEYS, NAVIGATOR_SHORTCUTS } from '~/helpers/keyMap'
-import { findLineIndex } from '~/helpers/line'
-import { useCurrentLines, useWindowFocus } from '~/hooks'
+import { useWindowFocus } from '~/hooks'
+import { setLine, setNextContent, setPreviousContent, useContent } from '~/services/content'
import controller from '~/services/controller'
import GlobalHotKeys from './GlobalHotKeys'
@@ -21,9 +21,8 @@ const NavigatorHotKeys = (
) => {
const { viewedLines } = useContext( HistoryContext )
- const content = useContext( ContentContext )
- const { lineId, mainLineId, nextLineId, shabad, bani } = content
- const lines = useCurrentLines()
+ const { content, lineId } = useContent()
+ const lines = content?.lines
const goFirstLine = () => {
if ( !lines ) return
@@ -31,8 +30,8 @@ const NavigatorHotKeys = (
const [ firstLine ] = lines
// Go to the previous shabad if the first line is highlighted (but not for banis)
- if ( !bani && lineId === firstLine.id ) controller.previousShabad( shabad.orderId )
- else controller.line( firstLine.id )
+ if ( content.type === 'shabad' && lineId === firstLine.id ) setPreviousContent()
+ else setLine( firstLine.id )
}
const goLastLine = () => {
@@ -41,14 +40,14 @@ const NavigatorHotKeys = (
const lastLine = lines[ lines.length - 1 ]
// Go to the next shabad if the last line is highlighted (but not for banis)
- if ( !bani && lineId === lastLine.id ) controller.nextShabad( shabad.orderId )
- else controller.line( lastLine.id )
+ if ( content.type === 'shabad' && lineId === lastLine.id ) setNextContent()
+ else setLine( lastLine.id )
}
const autoToggle = useCallback( () => {
- if ( shabad ) controller.autoToggleShabad( content )
- else if ( bani ) controller.autoToggleBani( content )
- }, [ shabad, bani, content ] )
+ // if ( content.type === 'shabad' ) controller.autoToggleShabad( content )
+ // else if ( content.type === 'bani' ) controller.autoToggleBani( content )
+ }, [ content ] )
const restoreLine = () => {
const ids = Object
@@ -178,4 +177,4 @@ const NavigatorHotKeys = (
)
}
-export default NavigatorHotKeys
+export default ( { children } ) => children
diff --git a/apps/frontend/src/components/ThemeLoader.tsx b/apps/frontend/src/components/ThemeLoader.tsx
index 43b21947..102415d1 100644
--- a/apps/frontend/src/components/ThemeLoader.tsx
+++ b/apps/frontend/src/components/ThemeLoader.tsx
@@ -1,19 +1,18 @@
import defaultTheme from '@presenter/themes/presenter/Day.css?url'
-import { useContext } from 'react'
import { API_URL } from '~/helpers/consts'
-import { StatusContext } from '~/helpers/contexts'
+import { useStatus } from '~/services/status'
const PRESENTER_THEMES_URL = `${API_URL}/themes/presenter`
type ThemeLoaderProps = { name: string }
const ThemeLoader = ( { name = 'Day' }: ThemeLoaderProps ) => {
- const { connectedAt } = useContext( StatusContext )
+ const { connectedAt } = useStatus()
return (
diff --git a/apps/frontend/src/helpers/auto-jump.ts b/apps/frontend/src/helpers/auto-jump.ts
index 337ef970..64c1d0b2 100644
--- a/apps/frontend/src/helpers/auto-jump.ts
+++ b/apps/frontend/src/helpers/auto-jump.ts
@@ -1,8 +1,8 @@
+import { ClientEventParameters } from '@presenter/contract'
import { find, findIndex, findLastIndex, invert } from 'lodash'
import memoize from 'memoizee'
import { BANIS } from './data'
-import { findLineIndex } from './line'
const isBaniJumpLine = ( baniId, lines ) => (
{ jumpLines },
@@ -26,13 +26,11 @@ const isBaniJumpLine = ( baniId, lines ) => (
return filter()
}
-export const getJumpLines = memoize( ( { shabad, bani } ) => {
- if ( !( shabad || bani ) ) return {}
-
- const { lines } = shabad || bani
+export const getJumpLines = memoize( ( content: ClientEventParameters['content:current'] ) => {
+ if ( !content?.lines ) return {}
// Get a function for determining whether a line is jumpable
- const isJumpLine = bani ? isBaniJumpLine( bani.id, lines ) : () => true
+ const isJumpLine = content.type === 'bani' ? isBaniJumpLine( content.id, content.lines ) : () => true
// Go over each line, and tag which lines are jumpable
const { jumpLines } = lines.reduce( ( { jumpLines, jumpIndex }, line, lineIndex ) => ( {
@@ -51,17 +49,17 @@ export const getJumpLines = memoize( ( { shabad, bani } ) => {
}, {
primitive: true,
max: 1,
- normalizer: ( [ { bani, shabad } ] ) => JSON.stringify( {
- shabadId: ( shabad ? shabad.id : null ),
- baniId: ( bani ? bani.id : null ),
+ normalizer: ( [ content ] ) => JSON.stringify( {
+ shabadId: ( content?.type === 'shabad' ? content.shabad.id : null ),
+ baniId: ( content?.type === 'bani' ? content.bani.id : null ),
} ),
} )
-export const getBaniNextJumpLine = ( { bani, lineId } ) => {
- const { lines } = bani
+export const getBaniNextJumpLine = ( { content, lineId } ) => {
+ const { lines } = content
// Get jump lines and current line index
- const jumpLines = invert( getJumpLines( { bani } ) )
+ const jumpLines = invert( getJumpLines( content ) )
const currentLineIndex = findLineIndex( lines, lineId )
const currentLine = lines[ currentLineIndex ]
@@ -140,8 +138,8 @@ export const getBaniNextJumpLine = ( { bani, lineId } ) => {
return baniNextLineId
}
-export const getNextJumpLine = ( { nextLineId, shabad, bani, lineId } ) => {
- if ( !( shabad || bani ) ) return null
+export const getNextJumpLine = ( { nextLineId, content, lineId } ) => {
+ if ( !content ) return null
- return shabad ? nextLineId : getBaniNextJumpLine( { bani, lineId } )
+ return content.type === 'shabad' ? nextLineId : getBaniNextJumpLine( { content, lineId } )
}
diff --git a/apps/frontend/src/helpers/consts.ts b/apps/frontend/src/helpers/consts.ts
index 2bb2697f..9d1dd5bc 100644
--- a/apps/frontend/src/helpers/consts.ts
+++ b/apps/frontend/src/helpers/consts.ts
@@ -16,7 +16,6 @@ export const HOST = window.location.hostname || 'localhost'
export const PORT = window.location.port
export const BASE_URL = `${HOST}:${PORT}`
export const API_URL = `http://${BASE_URL}/api`
-export const WS_URL = `ws://${BASE_URL}/api`
/* Sentry Data Source Name */
export const SENTRY_DSN = 'https://51b714c1e7544cba86efb2cad85152ff@sentry.io/1363390'
diff --git a/apps/frontend/src/helpers/contexts.tsx b/apps/frontend/src/helpers/contexts.tsx
index 4d41b765..9e191486 100644
--- a/apps/frontend/src/helpers/contexts.tsx
+++ b/apps/frontend/src/helpers/contexts.tsx
@@ -1,4 +1,3 @@
-import { Bani, Line, Shabad } from '@presenter/contract'
import { ComponentType, Context, createContext } from 'react'
import { SettingsState } from './options'
@@ -14,18 +13,6 @@ export const
export const SettingsContext = createContext( {} as SettingsState )
-type Content = {
- bani: Bani | null,
- shabad: Shabad | null,
- lineId: string,
-}
-
-export const ContentContext = createContext( {
- bani: null,
- shabad: null,
- lineId: '',
-} )
-
type TransitionHistory = {
length: number,
}
@@ -43,15 +30,3 @@ type RecommendedSources = {
export const RecommendedSourcesContext = createContext( {} as RecommendedSources )
export const WritersContext = createContext( {} )
-
-export const BookmarksContext = createContext( [] )
-
-type Status = {
- connected: boolean,
- connectedAt: Date | null,
- status: string | null,
-}
-
-export const StatusContext = createContext( {
- connected: false, connectedAt: null, status: null,
-} )
diff --git a/apps/frontend/src/helpers/line.ts b/apps/frontend/src/helpers/line.ts
index ed6e6cf0..b8203b35 100644
--- a/apps/frontend/src/helpers/line.ts
+++ b/apps/frontend/src/helpers/line.ts
@@ -2,10 +2,9 @@
** Currently shared with backend! Should be refactored.
*/
-import type { Line, RecommendedSources, Shabad, Translation } from '@presenter/contract'
+import type { Content, Line, RecommendedSources, Shabad, Source, Translation } from '@presenter/contract'
import { stripEndings, stripVishraams } from 'gurmukhi-utils'
import vishraams from 'gurmukhi-utils/lib/vishraams.json'
-import memoize from 'memoizee'
import { LINE_TYPES, Translations, TRANSLITERATORS, Transliterators } from './data'
@@ -16,17 +15,8 @@ export const sortBy = (
[ languageB ]: [string, any]
) => sortOrder[ languageA ] - sortOrder[ languageB ]
-export const findLineIndex = memoize(
- ( lines: Line[], lineId: string ) => lines.findIndex( ( { id } ) => id === lineId ),
- {
- primitive: true,
- max: 5,
- normalizer: ( [ , lineId ] ) => lineId,
- },
-)
-
- type CustomiseLineParams = { lineEnding: boolean, typeId: number }
- type LineTransformer = [boolean, ( text: string ) => string]
+type CustomiseLineParams = { lineEnding: boolean, typeId: number }
+type LineTransformer = [boolean, ( text: string ) => string]
export const customiseLine = ( line: string, { lineEnding, typeId }: CustomiseLineParams ) => ( [
[ lineEnding, stripEndings ],
@@ -64,7 +54,7 @@ export const partitionLine = ( line: string, strip = true ) => classifyWords( li
}, [ [] ] )
type GetTranslationParams = {
- shabad: Shabad,
+ content: Content,
line: Line,
sources: Source,
recommendedSources: Source,
@@ -72,9 +62,9 @@ export const partitionLine = ( line: string, strip = true ) => classifyWords( li
}
export const getTranslation = (
- { shabad, line, sources, recommendedSources, languageId }: GetTranslationParams
+ { content, line, sources, recommendedSources, languageId }: GetTranslationParams
) => {
- const { sourceId } = shabad || line.shabad
+ const { sourceId } = content.shabad || line.shabad
if ( !( sources?.[ sourceId ] ) ) return null
@@ -94,7 +84,7 @@ export const getTranslation = (
type GetTranslationsParams = {
languageIds: number[],
line: Line,
- shabad: Shabad | null,
+ content: Content,
sources: RecommendedSources['sources'],
recommendedSources: RecommendedSources['recommendedSources'],
}
diff --git a/apps/frontend/src/hooks/index.ts b/apps/frontend/src/hooks/index.ts
index 43a5c7eb..e226a954 100644
--- a/apps/frontend/src/hooks/index.ts
+++ b/apps/frontend/src/hooks/index.ts
@@ -1,39 +1,19 @@
-import { Line } from '@presenter/contract'
import copy from 'copy-to-clipboard'
import { useSnackbar } from 'notistack'
import { useContext, useEffect, useRef, useState } from 'react'
import { isMac } from '~/helpers/consts'
-import { ContentContext, RecommendedSourcesContext, SettingsContext } from '~/helpers/contexts'
-import { findLineIndex, getTranslations } from '~/helpers/line'
-
-export const useCurrentLines = () => {
- const { shabad, bani } = useContext( ContentContext )
-
- const { lines = [] as Line[] } = shabad || bani || {}
-
- return lines
-}
-
-export const useCurrentLine = () => {
- const { lineId, shabad, bani } = useContext( ContentContext )
- const { lines = [] as Line[] } = shabad || bani || {}
-
- // Find the correct line in the Shabad
- const lineIndex = findLineIndex( lines, lineId )
- const line = lineIndex > -1 ? lines[ lineIndex ] : null
-
- return [ line as Line, lineIndex ] as const
-}
+import { RecommendedSourcesContext, SettingsContext } from '~/helpers/contexts'
+import { getTranslations } from '~/helpers/line'
+import { useContent } from '~/services/content'
export const useTranslations = ( languageIds: number[] ) => {
- const { shabad } = useContext( ContentContext )
- const [ line ] = useCurrentLine()
+ const { content, line } = useContent()
const recommendedSources = useContext( RecommendedSourcesContext )
const { local: { sources } = {} } = useContext( SettingsContext )
- return getTranslations( { shabad, line, recommendedSources, sources, languageIds } )
+ return getTranslations( { content, line, recommendedSources, sources, languageIds } )
}
export const useCopyToClipboard = () => {
diff --git a/apps/frontend/src/index.tsx b/apps/frontend/src/index.tsx
index b43887f6..98fe3ad3 100644
--- a/apps/frontend/src/index.tsx
+++ b/apps/frontend/src/index.tsx
@@ -5,9 +5,9 @@ import { createRoot } from 'react-dom/client'
import Empty from './components/Empty'
import { isDev } from './helpers/consts'
import { routeTree } from './routeTree.gen'
-import controller from './services/controller'
+// import controller from './services/controller'
-const settings = controller.readSettings()
+// const settings = controller.readSettings()
// if ( settings?.security?.displayAnalytics ) {
// void analytics.initialise()
diff --git a/apps/frontend/src/routeTree.gen.ts b/apps/frontend/src/routeTree.gen.ts
index d9a076d2..0e05427c 100644
--- a/apps/frontend/src/routeTree.gen.ts
+++ b/apps/frontend/src/routeTree.gen.ts
@@ -286,30 +286,215 @@ declare module '@tanstack/react-router' {
// Create and export the route tree
-export const routeTree = rootRoute.addChildren({
- IndexRoute,
- PresenterRouteRoute: PresenterRouteRoute.addChildren({
- PresenterControllerRouteRoute: PresenterControllerRouteRoute.addChildren({
- PresenterControllerIndexRoute,
+interface PresenterControllerRouteRouteChildren {
+ PresenterControllerIndexRoute: typeof PresenterControllerIndexRoute
+ PresenterControllerBookmarksIndexRoute: typeof PresenterControllerBookmarksIndexRoute
+ PresenterControllerHistoryIndexRoute: typeof PresenterControllerHistoryIndexRoute
+ PresenterControllerNavigatorIndexRoute: typeof PresenterControllerNavigatorIndexRoute
+ PresenterControllerSearchIndexRoute: typeof PresenterControllerSearchIndexRoute
+}
+
+const PresenterControllerRouteRouteChildren: PresenterControllerRouteRouteChildren =
+ {
+ PresenterControllerIndexRoute: PresenterControllerIndexRoute,
+ PresenterControllerBookmarksIndexRoute:
PresenterControllerBookmarksIndexRoute,
- PresenterControllerHistoryIndexRoute,
+ PresenterControllerHistoryIndexRoute: PresenterControllerHistoryIndexRoute,
+ PresenterControllerNavigatorIndexRoute:
PresenterControllerNavigatorIndexRoute,
- PresenterControllerSearchIndexRoute,
- }),
- }),
- SettingsRouteRoute: SettingsRouteRoute.addChildren({
- SettingsIndexRoute,
- SettingsClientCategoryRoute,
- SettingsServerCategoryRoute,
- SettingsClientHotkeysIndexRoute,
- SettingsClientSourcesIndexRoute,
- SettingsServerAboutIndexRoute,
- SettingsToolsClosedCaptionsIndexRoute,
- SettingsToolsOverlayIndexRoute,
- }),
- OverlayIndexLazyRoute,
- ScreenReaderIndexLazyRoute,
-})
+ PresenterControllerSearchIndexRoute: PresenterControllerSearchIndexRoute,
+ }
+
+const PresenterControllerRouteRouteWithChildren =
+ PresenterControllerRouteRoute._addFileChildren(
+ PresenterControllerRouteRouteChildren,
+ )
+
+interface PresenterRouteRouteChildren {
+ PresenterControllerRouteRoute: typeof PresenterControllerRouteRouteWithChildren
+}
+
+const PresenterRouteRouteChildren: PresenterRouteRouteChildren = {
+ PresenterControllerRouteRoute: PresenterControllerRouteRouteWithChildren,
+}
+
+const PresenterRouteRouteWithChildren = PresenterRouteRoute._addFileChildren(
+ PresenterRouteRouteChildren,
+)
+
+interface SettingsRouteRouteChildren {
+ SettingsIndexRoute: typeof SettingsIndexRoute
+ SettingsClientCategoryRoute: typeof SettingsClientCategoryRoute
+ SettingsServerCategoryRoute: typeof SettingsServerCategoryRoute
+ SettingsClientHotkeysIndexRoute: typeof SettingsClientHotkeysIndexRoute
+ SettingsClientSourcesIndexRoute: typeof SettingsClientSourcesIndexRoute
+ SettingsServerAboutIndexRoute: typeof SettingsServerAboutIndexRoute
+ SettingsToolsClosedCaptionsIndexRoute: typeof SettingsToolsClosedCaptionsIndexRoute
+ SettingsToolsOverlayIndexRoute: typeof SettingsToolsOverlayIndexRoute
+}
+
+const SettingsRouteRouteChildren: SettingsRouteRouteChildren = {
+ SettingsIndexRoute: SettingsIndexRoute,
+ SettingsClientCategoryRoute: SettingsClientCategoryRoute,
+ SettingsServerCategoryRoute: SettingsServerCategoryRoute,
+ SettingsClientHotkeysIndexRoute: SettingsClientHotkeysIndexRoute,
+ SettingsClientSourcesIndexRoute: SettingsClientSourcesIndexRoute,
+ SettingsServerAboutIndexRoute: SettingsServerAboutIndexRoute,
+ SettingsToolsClosedCaptionsIndexRoute: SettingsToolsClosedCaptionsIndexRoute,
+ SettingsToolsOverlayIndexRoute: SettingsToolsOverlayIndexRoute,
+}
+
+const SettingsRouteRouteWithChildren = SettingsRouteRoute._addFileChildren(
+ SettingsRouteRouteChildren,
+)
+
+interface FileRoutesByFullPath {
+ '/': typeof IndexRoute
+ '/presenter': typeof PresenterRouteRouteWithChildren
+ '/settings': typeof SettingsRouteRouteWithChildren
+ '/presenter/controller': typeof PresenterControllerRouteRouteWithChildren
+ '/settings/': typeof SettingsIndexRoute
+ '/overlay': typeof OverlayIndexLazyRoute
+ '/screen-reader': typeof ScreenReaderIndexLazyRoute
+ '/settings/client/$category': typeof SettingsClientCategoryRoute
+ '/settings/server/$category': typeof SettingsServerCategoryRoute
+ '/presenter/controller/': typeof PresenterControllerIndexRoute
+ '/presenter/controller/bookmarks': typeof PresenterControllerBookmarksIndexRoute
+ '/presenter/controller/history': typeof PresenterControllerHistoryIndexRoute
+ '/presenter/controller/navigator': typeof PresenterControllerNavigatorIndexRoute
+ '/presenter/controller/search': typeof PresenterControllerSearchIndexRoute
+ '/settings/client/hotkeys': typeof SettingsClientHotkeysIndexRoute
+ '/settings/client/sources': typeof SettingsClientSourcesIndexRoute
+ '/settings/server/about': typeof SettingsServerAboutIndexRoute
+ '/settings/tools/closedCaptions': typeof SettingsToolsClosedCaptionsIndexRoute
+ '/settings/tools/overlay': typeof SettingsToolsOverlayIndexRoute
+}
+
+interface FileRoutesByTo {
+ '/': typeof IndexRoute
+ '/presenter': typeof PresenterRouteRouteWithChildren
+ '/settings': typeof SettingsIndexRoute
+ '/overlay': typeof OverlayIndexLazyRoute
+ '/screen-reader': typeof ScreenReaderIndexLazyRoute
+ '/settings/client/$category': typeof SettingsClientCategoryRoute
+ '/settings/server/$category': typeof SettingsServerCategoryRoute
+ '/presenter/controller': typeof PresenterControllerIndexRoute
+ '/presenter/controller/bookmarks': typeof PresenterControllerBookmarksIndexRoute
+ '/presenter/controller/history': typeof PresenterControllerHistoryIndexRoute
+ '/presenter/controller/navigator': typeof PresenterControllerNavigatorIndexRoute
+ '/presenter/controller/search': typeof PresenterControllerSearchIndexRoute
+ '/settings/client/hotkeys': typeof SettingsClientHotkeysIndexRoute
+ '/settings/client/sources': typeof SettingsClientSourcesIndexRoute
+ '/settings/server/about': typeof SettingsServerAboutIndexRoute
+ '/settings/tools/closedCaptions': typeof SettingsToolsClosedCaptionsIndexRoute
+ '/settings/tools/overlay': typeof SettingsToolsOverlayIndexRoute
+}
+
+interface FileRoutesById {
+ '/': typeof IndexRoute
+ '/presenter': typeof PresenterRouteRouteWithChildren
+ '/settings': typeof SettingsRouteRouteWithChildren
+ '/presenter/controller': typeof PresenterControllerRouteRouteWithChildren
+ '/settings/': typeof SettingsIndexRoute
+ '/overlay/': typeof OverlayIndexLazyRoute
+ '/screen-reader/': typeof ScreenReaderIndexLazyRoute
+ '/settings/client/$category': typeof SettingsClientCategoryRoute
+ '/settings/server/$category': typeof SettingsServerCategoryRoute
+ '/presenter/controller/': typeof PresenterControllerIndexRoute
+ '/presenter/controller/bookmarks/': typeof PresenterControllerBookmarksIndexRoute
+ '/presenter/controller/history/': typeof PresenterControllerHistoryIndexRoute
+ '/presenter/controller/navigator/': typeof PresenterControllerNavigatorIndexRoute
+ '/presenter/controller/search/': typeof PresenterControllerSearchIndexRoute
+ '/settings/client/hotkeys/': typeof SettingsClientHotkeysIndexRoute
+ '/settings/client/sources/': typeof SettingsClientSourcesIndexRoute
+ '/settings/server/about/': typeof SettingsServerAboutIndexRoute
+ '/settings/tools/closedCaptions/': typeof SettingsToolsClosedCaptionsIndexRoute
+ '/settings/tools/overlay/': typeof SettingsToolsOverlayIndexRoute
+}
+
+interface FileRouteTypes {
+ fileRoutesByFullPath: FileRoutesByFullPath
+ fullPaths:
+ | '/'
+ | '/presenter'
+ | '/settings'
+ | '/presenter/controller'
+ | '/settings/'
+ | '/overlay'
+ | '/screen-reader'
+ | '/settings/client/$category'
+ | '/settings/server/$category'
+ | '/presenter/controller/'
+ | '/presenter/controller/bookmarks'
+ | '/presenter/controller/history'
+ | '/presenter/controller/navigator'
+ | '/presenter/controller/search'
+ | '/settings/client/hotkeys'
+ | '/settings/client/sources'
+ | '/settings/server/about'
+ | '/settings/tools/closedCaptions'
+ | '/settings/tools/overlay'
+ fileRoutesByTo: FileRoutesByTo
+ to:
+ | '/'
+ | '/presenter'
+ | '/settings'
+ | '/overlay'
+ | '/screen-reader'
+ | '/settings/client/$category'
+ | '/settings/server/$category'
+ | '/presenter/controller'
+ | '/presenter/controller/bookmarks'
+ | '/presenter/controller/history'
+ | '/presenter/controller/navigator'
+ | '/presenter/controller/search'
+ | '/settings/client/hotkeys'
+ | '/settings/client/sources'
+ | '/settings/server/about'
+ | '/settings/tools/closedCaptions'
+ | '/settings/tools/overlay'
+ id:
+ | '/'
+ | '/presenter'
+ | '/settings'
+ | '/presenter/controller'
+ | '/settings/'
+ | '/overlay/'
+ | '/screen-reader/'
+ | '/settings/client/$category'
+ | '/settings/server/$category'
+ | '/presenter/controller/'
+ | '/presenter/controller/bookmarks/'
+ | '/presenter/controller/history/'
+ | '/presenter/controller/navigator/'
+ | '/presenter/controller/search/'
+ | '/settings/client/hotkeys/'
+ | '/settings/client/sources/'
+ | '/settings/server/about/'
+ | '/settings/tools/closedCaptions/'
+ | '/settings/tools/overlay/'
+ fileRoutesById: FileRoutesById
+}
+
+interface RootRouteChildren {
+ IndexRoute: typeof IndexRoute
+ PresenterRouteRoute: typeof PresenterRouteRouteWithChildren
+ SettingsRouteRoute: typeof SettingsRouteRouteWithChildren
+ OverlayIndexLazyRoute: typeof OverlayIndexLazyRoute
+ ScreenReaderIndexLazyRoute: typeof ScreenReaderIndexLazyRoute
+}
+
+const rootRouteChildren: RootRouteChildren = {
+ IndexRoute: IndexRoute,
+ PresenterRouteRoute: PresenterRouteRouteWithChildren,
+ SettingsRouteRoute: SettingsRouteRouteWithChildren,
+ OverlayIndexLazyRoute: OverlayIndexLazyRoute,
+ ScreenReaderIndexLazyRoute: ScreenReaderIndexLazyRoute,
+}
+
+export const routeTree = rootRoute
+ ._addFileChildren(rootRouteChildren)
+ ._addFileTypes()
/* prettier-ignore-end */
diff --git a/apps/frontend/src/services/bookmarks.ts b/apps/frontend/src/services/bookmarks.ts
new file mode 100644
index 00000000..cc94adbf
--- /dev/null
+++ b/apps/frontend/src/services/bookmarks.ts
@@ -0,0 +1,5 @@
+import { useAtomValue } from 'jotai'
+
+import websocketClient from './websocket-client'
+
+export const useBookmarks = () => useAtomValue( websocketClient.getAtom( 'content:bani:list' ) )
diff --git a/apps/frontend/src/services/content.ts b/apps/frontend/src/services/content.ts
new file mode 100644
index 00000000..d84132bf
--- /dev/null
+++ b/apps/frontend/src/services/content.ts
@@ -0,0 +1,36 @@
+import { ServerEventParameters } from '@presenter/contract'
+import { atom, useAtomValue } from 'jotai'
+
+import websocketClient from './websocket-client'
+
+const linesByIdAtom = atom( ( get ) => {
+ const content = get( websocketClient.getAtom( 'content:current' ) )
+ const lines = content?.lines
+
+ return lines?.reduce(
+ ( acc, line, lineIndex ) => ( { ...acc, [ line.id ]: { line, lineIndex } } ),
+ {} as Record,
+ )
+} )
+
+const contentAtom = atom( ( get ) => {
+ const content = get( websocketClient.getAtom( 'content:current' ) )
+
+ const lines = content?.lines
+ const lineId = get( websocketClient.getAtom( 'content:line:current' ) )
+
+ const linesById = get( linesByIdAtom )
+ const line = lineId ? linesById?.[ lineId ] : undefined
+
+ return { content, lineId, lines, ...line }
+} )
+
+export const useContent = () => useAtomValue( contentAtom )
+
+export const setNextContent = () => websocketClient.json( 'content:open-next', undefined )
+export const setPreviousContent = () => websocketClient.json( 'content:open-previous', undefined )
+export const setPreviousLine = () => websocketClient.json( 'content:line:set-previous', undefined )
+export const setNextLine = () => websocketClient.json( 'content:line:set-next', undefined )
+export const setLine = ( lineId: ServerEventParameters['content:line:set-current'] ) => websocketClient.json( 'content:line:set-current', lineId )
+export const setContent = ( content: ServerEventParameters['content:open'] ) => websocketClient.json( 'content:open', content )
+export const clearLine = () => websocketClient.json( 'content:line:clear', undefined )
diff --git a/apps/frontend/src/services/controller.ts b/apps/frontend/src/services/controller.ts
index 60c49fec..ef6042ce 100644
--- a/apps/frontend/src/services/controller.ts
+++ b/apps/frontend/src/services/controller.ts
@@ -1,5 +1,4 @@
import EventEmitter from 'eventemitter3'
-import ReconnectingWebSocket from 'reconnecting-websocket'
import { getNextJumpLine } from '~/helpers/auto-jump'
import { isDev, isElectron, WS_URL } from '~/helpers/consts'
@@ -15,35 +14,23 @@ type ShabadOptions = {
}
class Controller extends EventEmitter {
- #socket: ReconnectingWebSocket
#settings: SettingsState
constructor() {
super()
- // Setup WebSocket connection to server
- this.#socket = new ReconnectingWebSocket( WS_URL, undefined, {
- reconnectionDelayGrowFactor: 1,
- minReconnectionDelay: 300 + Math.random() * 200,
- connectionTimeout: 1000,
- } )
-
// Initialise settings
this.saveLocalSettings()
this.#settings = { local: this.readSettings( true ) } as any
- this.#socket.addEventListener( 'close', this.onClose )
- this.#socket.addEventListener( 'message', this.onMessage )
- this.#socket.addEventListener( 'open', this.onOpen )
-
this.on( 'ready', this.onReady )
}
sendJSON = ( event: string, payload?: any ) => {
- const sendJSON = () => this.#socket.send( JSON.stringify( { event, payload } ) )
+ // const sendJSON = () => this.#socket.send( JSON.stringify( { event, payload } ) )
- if ( this.#socket.readyState === 1 ) sendJSON()
- else this.once( 'connected', sendJSON )
+ // if ( this.#socket.readyState === 1 ) sendJSON()
+ // else this.once( 'connected', sendJSON )
}
onOpen = () => {
@@ -75,7 +62,7 @@ class Controller extends EventEmitter {
}
/**
- essage = ( { data }: { data: any } ) => {
+ message = ( { data }: { data: any } ) => {
const { event, payload } = JSON.parse( data )
this.emit( event, payload )
}
diff --git a/apps/frontend/src/services/jotai.ts b/apps/frontend/src/services/jotai.ts
new file mode 100644
index 00000000..1ce2b50f
--- /dev/null
+++ b/apps/frontend/src/services/jotai.ts
@@ -0,0 +1,3 @@
+import { createStore } from 'jotai'
+
+export const store = createStore()
diff --git a/apps/frontend/src/services/notifications.ts b/apps/frontend/src/services/notifications.ts
new file mode 100644
index 00000000..42c776f4
--- /dev/null
+++ b/apps/frontend/src/services/notifications.ts
@@ -0,0 +1,9 @@
+import { useAtomValue } from 'jotai'
+
+import websocketClient from './websocket-client'
+
+export const useNotifications = () => {
+ const notifications = useAtomValue( websocketClient.getAtom( 'status' ) )
+
+ return notifications
+}
diff --git a/apps/frontend/src/services/search.ts b/apps/frontend/src/services/search.ts
new file mode 100644
index 00000000..3d7a87b3
--- /dev/null
+++ b/apps/frontend/src/services/search.ts
@@ -0,0 +1,15 @@
+import { ServerEventParameters } from '@presenter/contract'
+import { useAtom } from 'jotai'
+
+import websocketClient from './websocket-client'
+
+export const search = ( params: ServerEventParameters['search:query'] ) => websocketClient.json( 'search:query', params )
+
+export const useSearchResults = () => {
+ const [ results, setResults ] = useAtom( websocketClient.getAtom( 'search:results' ) )
+
+ return {
+ results,
+ clearResults: () => setResults( [] ),
+ }
+}
diff --git a/apps/frontend/src/services/status.ts b/apps/frontend/src/services/status.ts
new file mode 100644
index 00000000..fe07f9c3
--- /dev/null
+++ b/apps/frontend/src/services/status.ts
@@ -0,0 +1,30 @@
+import { atom, useAtomValue } from 'jotai'
+
+import websocketClient from './websocket-client'
+
+const connectedAtom = atom( false )
+
+connectedAtom.onMount = ( set ) => {
+ const unlistenConnected = websocketClient.listen( 'connected', () => {
+ set( true )
+ } )
+
+ const unlistenDisconnected = websocketClient.listen( 'disconnected', () => {
+ set( false )
+ } )
+
+ return () => {
+ unlistenConnected()
+ unlistenDisconnected()
+ }
+}
+
+const statusAtom = atom( ( get ) => {
+ const connected = get( connectedAtom )
+
+ return connected
+ ? { connected: true, connectedAt: new Date() } as const
+ : { connected: false, connectedAt: undefined } as const
+} )
+
+export const useStatus = () => useAtomValue( statusAtom )
diff --git a/apps/frontend/src/services/tracker.ts b/apps/frontend/src/services/tracker.ts
new file mode 100644
index 00000000..30ca74fb
--- /dev/null
+++ b/apps/frontend/src/services/tracker.ts
@@ -0,0 +1,10 @@
+import { useAtomValue } from 'jotai'
+
+import websocketClient from './websocket-client'
+
+export const useTracker = () => {
+ const mainLineId = useAtomValue( websocketClient.getAtom( 'content:tracker:main-line' ) )
+ const nextLineId = useAtomValue( websocketClient.getAtom( 'content:tracker:next-line' ) )
+
+ return { mainLineId, nextLineId }
+}
diff --git a/apps/frontend/src/services/websocket-client.ts b/apps/frontend/src/services/websocket-client.ts
new file mode 100644
index 00000000..1a7650ab
--- /dev/null
+++ b/apps/frontend/src/services/websocket-client.ts
@@ -0,0 +1,96 @@
+import { ClientEvent, ClientEventParameters, clientEvents, ServerEvent, ServerEventParameters } from '@presenter/contract'
+import { decode, encode } from '@presenter/swiss-knife'
+import EventEmitter from 'eventemitter3'
+import { atom, WritableAtom } from 'jotai'
+import { WebSocket } from 'partysocket'
+
+import { BASE_URL } from '~/helpers/consts'
+
+import { store } from './jotai'
+
+const WS_URL = `ws://${BASE_URL}/api`
+
+type ClientEvents = {
+ 'connected': [undefined],
+ 'disconnected': [undefined],
+} & {
+ [Event in ClientEvent]: [ClientEventParameters[Event]]
+}
+
+const createWebSocketClient = () => {
+ const emitter = new EventEmitter()
+
+ const socket = new WebSocket( WS_URL, undefined, {
+ minReconnectionDelay: 300 + Math.random() * 200,
+ connectionTimeout: 1000,
+ } )
+
+ socket.addEventListener( 'open', () => emitter.emit( 'connected', undefined ) )
+ socket.addEventListener( 'close', () => emitter.emit( 'disconnected', undefined ) )
+ socket.addEventListener( 'message', ( { data } ) => {
+ const { event, payload } = decode<{
+ event: ClientEvent,
+ payload: ClientEventParameters[ClientEvent],
+ }>( data as string )
+
+ emitter.emit( event, payload )
+ } )
+
+ const send = ( data: string ) => {
+ if ( socket.readyState === WebSocket.OPEN ) socket.send( data )
+ else emitter.once( 'connected', () => socket.send( data ) )
+ }
+
+ const json = (
+ event: Event,
+ payload: ServerEventParameters[Event]
+ ) => send( encode( { event, payload } ) )
+
+ const listen = (
+ event: Event,
+ listener: ( payload: ClientEvents[Event][0] ) => void
+ ) => {
+ emitter.on( event, listener )
+ return () => emitter.off( event, listener )
+ }
+
+ const atoms = new Map<
+ keyof ClientEvents,
+ WritableAtom
+ >()
+
+ const getAtom = ( event: Event ) => {
+ if ( atoms.has( event ) ) {
+ return atoms.get( event ) as WritableAtom<
+ ClientEvents[Event][0] | undefined,
+ [ClientEvents[Event][0] | undefined],
+ void
+ >
+ }
+
+ const a = atom( null )
+ atoms.set( event, a )
+
+ return a
+ }
+
+ // Listen to events and set atoms at this point so that we don't miss any events
+ clientEvents.forEach(
+ /* eslint-disable-next-line
+ @typescript-eslint/no-unsafe-argument,
+ @typescript-eslint/no-explicit-any
+ */
+ ( event ) => emitter.on( event, ( payload ) => store.set( getAtom( event ) as any, payload ) )
+ )
+
+ return {
+ json,
+ on: emitter.on.bind( emitter ),
+ once: emitter.once.bind( emitter ),
+ off: emitter.off.bind( emitter ),
+ listen,
+ getAtom,
+ }
+}
+
+export default createWebSocketClient()
diff --git a/package-lock.json b/package-lock.json
index 41fd4c98..420e0587 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -123,8 +123,251 @@
"electron-notarize": "^1.2.1"
},
"devDependencies": {
- "electron": "18.2.0",
- "npm-run-all": "^4.1.5"
+ "electron": "^32"
+ }
+ },
+ "apps/electron/node_modules/@electron/get": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/@electron/get/-/get-2.0.3.tgz",
+ "integrity": "sha512-Qkzpg2s9GnVV2I2BjRksUi43U5e6+zaQMcjoJy0C+C5oxaKl+fmckGDQFtRpZpZV0NQekuZZ+tGz7EA9TVnQtQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "debug": "^4.1.1",
+ "env-paths": "^2.2.0",
+ "fs-extra": "^8.1.0",
+ "got": "^11.8.5",
+ "progress": "^2.0.3",
+ "semver": "^6.2.0",
+ "sumchecker": "^3.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "optionalDependencies": {
+ "global-agent": "^3.0.0"
+ }
+ },
+ "apps/electron/node_modules/@sindresorhus/is": {
+ "version": "4.6.0",
+ "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz",
+ "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sindresorhus/is?sponsor=1"
+ }
+ },
+ "apps/electron/node_modules/@szmarczak/http-timer": {
+ "version": "4.0.6",
+ "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz",
+ "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "defer-to-connect": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "apps/electron/node_modules/cacheable-request": {
+ "version": "7.0.4",
+ "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.4.tgz",
+ "integrity": "sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "clone-response": "^1.0.2",
+ "get-stream": "^5.1.0",
+ "http-cache-semantics": "^4.0.0",
+ "keyv": "^4.0.0",
+ "lowercase-keys": "^2.0.0",
+ "normalize-url": "^6.0.1",
+ "responselike": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "apps/electron/node_modules/decompress-response": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz",
+ "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "mimic-response": "^3.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "apps/electron/node_modules/defer-to-connect": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz",
+ "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "apps/electron/node_modules/electron": {
+ "version": "32.2.2",
+ "resolved": "https://registry.npmjs.org/electron/-/electron-32.2.2.tgz",
+ "integrity": "sha512-c7TRE42JcgEmJ4elJyCdKk/2os0UX7YMkRDeXBkxFEoM34iX1/2x+c5T9PgeroKz8FEG7omRU5TvjulqVtXvdw==",
+ "dev": true,
+ "hasInstallScript": true,
+ "license": "MIT",
+ "dependencies": {
+ "@electron/get": "^2.0.0",
+ "@types/node": "^20.9.0",
+ "extract-zip": "^2.0.1"
+ },
+ "bin": {
+ "electron": "cli.js"
+ },
+ "engines": {
+ "node": ">= 12.20.55"
+ }
+ },
+ "apps/electron/node_modules/extract-zip": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz",
+ "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "debug": "^4.1.1",
+ "get-stream": "^5.1.0",
+ "yauzl": "^2.10.0"
+ },
+ "bin": {
+ "extract-zip": "cli.js"
+ },
+ "engines": {
+ "node": ">= 10.17.0"
+ },
+ "optionalDependencies": {
+ "@types/yauzl": "^2.9.1"
+ }
+ },
+ "apps/electron/node_modules/get-stream": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz",
+ "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "pump": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "apps/electron/node_modules/got": {
+ "version": "11.8.6",
+ "resolved": "https://registry.npmjs.org/got/-/got-11.8.6.tgz",
+ "integrity": "sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@sindresorhus/is": "^4.0.0",
+ "@szmarczak/http-timer": "^4.0.5",
+ "@types/cacheable-request": "^6.0.1",
+ "@types/responselike": "^1.0.0",
+ "cacheable-lookup": "^5.0.3",
+ "cacheable-request": "^7.0.2",
+ "decompress-response": "^6.0.0",
+ "http2-wrapper": "^1.0.0-beta.5.2",
+ "lowercase-keys": "^2.0.0",
+ "p-cancelable": "^2.0.0",
+ "responselike": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10.19.0"
+ },
+ "funding": {
+ "url": "https://github.com/sindresorhus/got?sponsor=1"
+ }
+ },
+ "apps/electron/node_modules/lowercase-keys": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz",
+ "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "apps/electron/node_modules/mimic-response": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz",
+ "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "apps/electron/node_modules/normalize-url": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz",
+ "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "apps/electron/node_modules/p-cancelable": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz",
+ "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "apps/electron/node_modules/responselike": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz",
+ "integrity": "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "lowercase-keys": "^2.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "apps/electron/node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
}
},
"apps/frontend": {
@@ -140,6 +383,7 @@
"@fortawesome/free-solid-svg-icons": "^6.6.0",
"@fortawesome/react-fontawesome": "^0.2.2",
"@mui/material": "^5.16.6",
+ "@presenter/swiss-knife": "*",
"@presenter/themes": "*",
"@sentry/browser": "^6.19.7",
"@tanstack/react-router": "^1.49.2",
@@ -150,15 +394,16 @@
"eventemitter3": "^5.0.1",
"gurmukhi-utils": "^3.2.2",
"is-mobile": "^3.1.1",
+ "jotai": "^2.10.1",
"lodash": "^4.17.21",
"memoizee": "^0.4.17",
"notistack": "^3.0.1",
+ "partysocket": "^1.0.2",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-hotkeys": "^2.0.0",
"react-idle-timer": "^5.7.2",
"react-transition-group": "^4.4.5",
- "reconnecting-websocket": "^4.4.0",
"scroll-into-view": "^1.16.0",
"zod": "^3.8.2-alpha.6"
},
@@ -2776,6 +3021,19 @@
"@types/node": "*"
}
},
+ "node_modules/@types/cacheable-request": {
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz",
+ "integrity": "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/http-cache-semantics": "*",
+ "@types/keyv": "^3.1.4",
+ "@types/node": "*",
+ "@types/responselike": "^1.0.0"
+ }
+ },
"node_modules/@types/compression": {
"version": "1.7.5",
"dev": true,
@@ -2849,6 +3107,13 @@
"@types/node": "*"
}
},
+ "node_modules/@types/http-cache-semantics": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz",
+ "integrity": "sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/@types/http-errors": {
"version": "2.0.4",
"dev": true,
@@ -2900,6 +3165,16 @@
"license": "MIT",
"peer": true
},
+ "node_modules/@types/keyv": {
+ "version": "3.1.4",
+ "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz",
+ "integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
"node_modules/@types/lodash": {
"version": "4.17.7",
"dev": true,
@@ -3032,6 +3307,16 @@
"@types/react": "*"
}
},
+ "node_modules/@types/responselike": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.3.tgz",
+ "integrity": "sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
"node_modules/@types/scroll-into-view": {
"version": "1.16.4",
"dev": true,
@@ -3110,6 +3395,17 @@
"version": "21.0.3",
"license": "MIT"
},
+ "node_modules/@types/yauzl": {
+ "version": "2.10.3",
+ "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz",
+ "integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==",
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
"node_modules/@typescript-eslint/eslint-plugin": {
"version": "7.18.0",
"dev": true,
@@ -3958,6 +4254,7 @@
"version": "1.0.3",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"array-buffer-byte-length": "^1.0.1",
"call-bind": "^1.0.5",
@@ -4592,6 +4889,16 @@
"node": ">=0.10.0"
}
},
+ "node_modules/cacheable-lookup": {
+ "version": "5.0.4",
+ "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz",
+ "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10.6.0"
+ }
+ },
"node_modules/cacheable-request": {
"version": "6.1.0",
"license": "MIT",
@@ -5338,6 +5645,7 @@
"version": "1.0.1",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"call-bind": "^1.0.6",
"es-errors": "^1.3.0",
@@ -5354,6 +5662,7 @@
"version": "1.0.1",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"call-bind": "^1.0.7",
"es-errors": "^1.3.0",
@@ -5370,6 +5679,7 @@
"version": "1.0.0",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"call-bind": "^1.0.6",
"es-errors": "^1.3.0",
@@ -6222,6 +6532,7 @@
"version": "1.23.3",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"array-buffer-byte-length": "^1.0.1",
"arraybuffer.prototype.slice": "^1.0.3",
@@ -6342,6 +6653,7 @@
"version": "1.0.0",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"es-errors": "^1.3.0"
},
@@ -6353,6 +6665,7 @@
"version": "2.0.3",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"get-intrinsic": "^1.2.4",
"has-tostringtag": "^1.0.2",
@@ -6375,6 +6688,7 @@
"version": "1.2.1",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"is-callable": "^1.1.4",
"is-date-object": "^1.0.1",
@@ -7983,6 +8297,7 @@
"version": "1.1.6",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"call-bind": "^1.0.2",
"define-properties": "^1.2.0",
@@ -8082,6 +8397,7 @@
"version": "1.0.2",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"call-bind": "^1.0.5",
"es-errors": "^1.3.0",
@@ -8677,6 +8993,20 @@
"node": ">= 6"
}
},
+ "node_modules/http2-wrapper": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz",
+ "integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "quick-lru": "^5.1.1",
+ "resolve-alpn": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=10.19.0"
+ }
+ },
"node_modules/https-proxy-agent": {
"version": "5.0.1",
"license": "MIT",
@@ -9156,6 +9486,7 @@
"version": "1.0.1",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"is-typed-array": "^1.1.13"
},
@@ -9316,6 +9647,7 @@
"version": "2.0.3",
"dev": true,
"license": "MIT",
+ "peer": true,
"engines": {
"node": ">= 0.4"
},
@@ -9488,6 +9820,7 @@
"version": "1.1.13",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"which-typed-array": "^1.1.14"
},
@@ -9527,6 +9860,7 @@
"version": "1.0.2",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"call-bind": "^1.0.2"
},
@@ -9766,6 +10100,27 @@
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
+ "node_modules/jotai": {
+ "version": "2.10.1",
+ "resolved": "https://registry.npmjs.org/jotai/-/jotai-2.10.1.tgz",
+ "integrity": "sha512-4FycO+BOTl2auLyF2Chvi6KTDqdsdDDtpaL/WHQMs8f3KS1E3loiUShQzAzFA/sMU5cJ0hz/RT1xum9YbG/zaA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12.20.0"
+ },
+ "peerDependencies": {
+ "@types/react": ">=17.0.0",
+ "react": ">=17.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "react": {
+ "optional": true
+ }
+ }
+ },
"node_modules/joycon": {
"version": "3.1.1",
"dev": true,
@@ -9880,8 +10235,7 @@
"node_modules/json-buffer": {
"version": "3.0.1",
"dev": true,
- "license": "MIT",
- "peer": true
+ "license": "MIT"
},
"node_modules/json-parse-better-errors": {
"version": "1.0.2",
@@ -9972,7 +10326,6 @@
"version": "4.5.4",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"json-buffer": "3.0.1"
}
@@ -10094,39 +10447,13 @@
"version": "1.2.4",
"license": "MIT"
},
- "node_modules/load-json-file": {
- "version": "4.0.0",
+ "node_modules/local-pkg": {
+ "version": "0.5.0",
"dev": true,
"license": "MIT",
"dependencies": {
- "graceful-fs": "^4.1.2",
- "parse-json": "^4.0.0",
- "pify": "^3.0.0",
- "strip-bom": "^3.0.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/load-json-file/node_modules/parse-json": {
- "version": "4.0.0",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "error-ex": "^1.3.1",
- "json-parse-better-errors": "^1.0.1"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/local-pkg": {
- "version": "0.5.0",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "mlly": "^1.4.2",
- "pkg-types": "^1.0.3"
+ "mlly": "^1.4.2",
+ "pkg-types": "^1.0.3"
},
"engines": {
"node": ">=14"
@@ -10440,13 +10767,6 @@
"node": ">=0.12"
}
},
- "node_modules/memorystream": {
- "version": "0.3.1",
- "dev": true,
- "engines": {
- "node": ">= 0.10.0"
- }
- },
"node_modules/merge-descriptors": {
"version": "1.0.1",
"license": "MIT"
@@ -11202,175 +11522,6 @@
"node": "^16.14.0 || >=18.0.0"
}
},
- "node_modules/npm-run-all": {
- "version": "4.1.5",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "ansi-styles": "^3.2.1",
- "chalk": "^2.4.1",
- "cross-spawn": "^6.0.5",
- "memorystream": "^0.3.1",
- "minimatch": "^3.0.4",
- "pidtree": "^0.3.0",
- "read-pkg": "^3.0.0",
- "shell-quote": "^1.6.1",
- "string.prototype.padend": "^3.0.0"
- },
- "bin": {
- "npm-run-all": "bin/npm-run-all/index.js",
- "run-p": "bin/run-p/index.js",
- "run-s": "bin/run-s/index.js"
- },
- "engines": {
- "node": ">= 4"
- }
- },
- "node_modules/npm-run-all/node_modules/ansi-styles": {
- "version": "3.2.1",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "color-convert": "^1.9.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/npm-run-all/node_modules/brace-expansion": {
- "version": "1.1.11",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "balanced-match": "^1.0.0",
- "concat-map": "0.0.1"
- }
- },
- "node_modules/npm-run-all/node_modules/chalk": {
- "version": "2.4.2",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "ansi-styles": "^3.2.1",
- "escape-string-regexp": "^1.0.5",
- "supports-color": "^5.3.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/npm-run-all/node_modules/color-convert": {
- "version": "1.9.3",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "color-name": "1.1.3"
- }
- },
- "node_modules/npm-run-all/node_modules/color-name": {
- "version": "1.1.3",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/npm-run-all/node_modules/cross-spawn": {
- "version": "6.0.5",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "nice-try": "^1.0.4",
- "path-key": "^2.0.1",
- "semver": "^5.5.0",
- "shebang-command": "^1.2.0",
- "which": "^1.2.9"
- },
- "engines": {
- "node": ">=4.8"
- }
- },
- "node_modules/npm-run-all/node_modules/escape-string-regexp": {
- "version": "1.0.5",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=0.8.0"
- }
- },
- "node_modules/npm-run-all/node_modules/has-flag": {
- "version": "3.0.0",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/npm-run-all/node_modules/minimatch": {
- "version": "3.1.2",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "brace-expansion": "^1.1.7"
- },
- "engines": {
- "node": "*"
- }
- },
- "node_modules/npm-run-all/node_modules/path-key": {
- "version": "2.0.1",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/npm-run-all/node_modules/semver": {
- "version": "5.7.2",
- "dev": true,
- "license": "ISC",
- "bin": {
- "semver": "bin/semver"
- }
- },
- "node_modules/npm-run-all/node_modules/shebang-command": {
- "version": "1.2.0",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "shebang-regex": "^1.0.0"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/npm-run-all/node_modules/shebang-regex": {
- "version": "1.0.0",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/npm-run-all/node_modules/supports-color": {
- "version": "5.5.0",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "has-flag": "^3.0.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/npm-run-all/node_modules/which": {
- "version": "1.3.1",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "isexe": "^2.0.0"
- },
- "bin": {
- "which": "bin/which"
- }
- },
"node_modules/npm-run-path": {
"version": "5.3.0",
"dev": true,
@@ -12001,6 +12152,27 @@
"node": ">= 0.8"
}
},
+ "node_modules/partysocket": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/partysocket/-/partysocket-1.0.2.tgz",
+ "integrity": "sha512-rAFOUKImaq+VBk2B+2RTBsWEvlnarEP53nchoUHzpVs8V6fG2/estihOTslTQUWHVuHEKDL5k8htG8K3TngyFA==",
+ "license": "ISC",
+ "dependencies": {
+ "event-target-shim": "^6.0.2"
+ }
+ },
+ "node_modules/partysocket/node_modules/event-target-shim": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-6.0.2.tgz",
+ "integrity": "sha512-8q3LsZjRezbFZ2PN+uP+Q7pnHUMmAOziU2vA2OwoFaKIXxlxl38IylhSSgUorWu/rf4er67w0ikBqjBFk/pomA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=10.13.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/mysticatea"
+ }
+ },
"node_modules/pascalcase": {
"version": "0.1.1",
"license": "MIT",
@@ -12114,21 +12286,10 @@
"url": "https://github.com/sponsors/jonschlinkert"
}
},
- "node_modules/pidtree": {
- "version": "0.3.1",
- "dev": true,
- "license": "MIT",
- "bin": {
- "pidtree": "bin/pidtree.js"
- },
- "engines": {
- "node": ">=0.10"
- }
- },
"node_modules/pify": {
"version": "3.0.0",
- "devOptional": true,
"license": "MIT",
+ "optional": true,
"engines": {
"node": ">=4"
}
@@ -12593,6 +12754,19 @@
"version": "4.0.4",
"license": "MIT"
},
+ "node_modules/quick-lru": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz",
+ "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/range-parser": {
"version": "1.2.1",
"license": "MIT",
@@ -12722,54 +12896,6 @@
"node": ">=6"
}
},
- "node_modules/read-pkg": {
- "version": "3.0.0",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "load-json-file": "^4.0.0",
- "normalize-package-data": "^2.3.2",
- "path-type": "^3.0.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/read-pkg/node_modules/hosted-git-info": {
- "version": "2.8.9",
- "dev": true,
- "license": "ISC"
- },
- "node_modules/read-pkg/node_modules/normalize-package-data": {
- "version": "2.5.0",
- "dev": true,
- "license": "BSD-2-Clause",
- "dependencies": {
- "hosted-git-info": "^2.1.4",
- "resolve": "^1.10.0",
- "semver": "2 || 3 || 4 || 5",
- "validate-npm-package-license": "^3.0.1"
- }
- },
- "node_modules/read-pkg/node_modules/path-type": {
- "version": "3.0.0",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "pify": "^3.0.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/read-pkg/node_modules/semver": {
- "version": "5.7.2",
- "dev": true,
- "license": "ISC",
- "bin": {
- "semver": "bin/semver"
- }
- },
"node_modules/readable-stream": {
"version": "2.3.8",
"license": "MIT",
@@ -12818,10 +12944,6 @@
"node": ">= 0.10"
}
},
- "node_modules/reconnecting-websocket": {
- "version": "4.4.0",
- "license": "MIT"
- },
"node_modules/redent": {
"version": "3.0.0",
"dev": true,
@@ -13205,6 +13327,13 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/resolve-alpn": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz",
+ "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/resolve-dir": {
"version": "1.0.1",
"license": "MIT",
@@ -13424,6 +13553,7 @@
"version": "1.1.2",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"call-bind": "^1.0.7",
"get-intrinsic": "^1.2.4",
@@ -13466,6 +13596,7 @@
"version": "1.0.3",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"call-bind": "^1.0.6",
"es-errors": "^1.3.0",
@@ -13734,14 +13865,6 @@
"node": ">=8"
}
},
- "node_modules/shell-quote": {
- "version": "1.8.1",
- "dev": true,
- "license": "MIT",
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
"node_modules/shelljs": {
"version": "0.8.3",
"license": "BSD-3-Clause",
@@ -14702,23 +14825,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/string.prototype.padend": {
- "version": "3.1.6",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "call-bind": "^1.0.7",
- "define-properties": "^1.2.1",
- "es-abstract": "^1.23.2",
- "es-object-atoms": "^1.0.0"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
"node_modules/string.prototype.repeat": {
"version": "1.0.0",
"dev": true,
@@ -14733,6 +14839,7 @@
"version": "1.2.9",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"call-bind": "^1.0.7",
"define-properties": "^1.2.1",
@@ -14750,6 +14857,7 @@
"version": "1.0.8",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"call-bind": "^1.0.7",
"define-properties": "^1.2.1",
@@ -14763,6 +14871,7 @@
"version": "1.0.8",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"call-bind": "^1.0.7",
"define-properties": "^1.2.1",
@@ -14800,6 +14909,7 @@
"version": "3.0.0",
"dev": true,
"license": "MIT",
+ "peer": true,
"engines": {
"node": ">=4"
}
@@ -15479,6 +15589,7 @@
"version": "1.0.2",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"call-bind": "^1.0.7",
"es-errors": "^1.3.0",
@@ -15492,6 +15603,7 @@
"version": "1.0.1",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"call-bind": "^1.0.7",
"for-each": "^0.3.3",
@@ -15510,6 +15622,7 @@
"version": "1.0.2",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"available-typed-arrays": "^1.0.7",
"call-bind": "^1.0.7",
@@ -15529,6 +15642,7 @@
"version": "1.0.6",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"call-bind": "^1.0.7",
"for-each": "^0.3.3",
@@ -15583,6 +15697,7 @@
"version": "1.0.2",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"call-bind": "^1.0.2",
"has-bigints": "^1.0.2",