Skip to content

Commit

Permalink
Merge pull request #22 from NickRimmer/fix/navigation-new-implementation
Browse files Browse the repository at this point in the history
Fix/navigation new implementation
  • Loading branch information
NickRimmer authored Sep 1, 2023
2 parents 076fc63 + af0e2a2 commit 608c13a
Show file tree
Hide file tree
Showing 23 changed files with 274 additions and 242 deletions.
11 changes: 8 additions & 3 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
import * as insomnia from './services/insomnia/connector'
import * as ui from './ui'
import { cleanupWorkspacesAsync } from './services/db'
import { database } from './services/db'
import { getRouter } from './services/insomnia/connector/refs-router'

const initAsync = async () => {
// initialize ui components
await ui.renderAsync()
await cleanupWorkspacesAsync()
console.log('[plugin-navigator]', 'initialized')
// await cleanupWorkspacesAsync()

window.dev = {
router: getRouter(),
database: database,
}
}

let tries = 0
Expand Down
14 changes: 0 additions & 14 deletions src/services/db/cleanup.ts

This file was deleted.

1 change: 0 additions & 1 deletion src/services/db/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
export * from './db'
export * from './db.types'
export * from './cleanup'
4 changes: 2 additions & 2 deletions src/services/helpers/insomnia-requests.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { DocBaseModel } from '../insomnia/types'
import { InsomniaDocBase } from '../insomnia/types'

export const getRequestMethodName = (requestInfo: DocBaseModel) => {
export const getRequestMethodName = (requestInfo: InsomniaDocBase) => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
let method = (requestInfo as any).method
if (!method) {
Expand Down
50 changes: 4 additions & 46 deletions src/services/insomnia/connector/index.ts
Original file line number Diff line number Diff line change
@@ -1,53 +1,11 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import { getReactRefs, subscribeForRoutePushed } from './refs-react'
import { subscibeForDbChangeEvents } from './refs-events'
import { DocBaseModel } from '../types'
import { notifyRequestSelected } from '../events/request-selected'
import { notifyRequestUpdated } from '../events/request-updated'
import { notifyRequestDeleted } from '../events/request-deleted'
import { notifyRouteChanged } from '../events/route-changed'
import { initConnection } from './refs-common'
import { initRouter } from './refs-router'
import { initEvents } from './refs-events'

export const connect = (): boolean => {
console.log('[plugin-navigator]', 'connecting to insomnia')
initConnection()

// get react references
const reactRefs = getReactRefs()
if (!reactRefs) {
console.warn('[plugin-navigator]', 'react resources not found')
return false
}

storeInternal = reactRefs.store
routerInternal = reactRefs.router

// connect to router
subscribeForRoutePushed(routerInternal, (path: string) => notifyRouteChanged(path))

// connect to db changes
subscibeForDbChangeEvents((doc, method) => {
if (method === 'update' && doc.type === 'WorkspaceMeta') notifyRequestSelected(doc)
if (method === 'update' && (doc.type === 'Request' || doc.type === 'GrpcRequest')) notifyRequestUpdated(doc)
if (method === 'remove' && (doc.type === 'Request' || doc.type === 'GrpcRequest')) notifyRequestDeleted(doc)
})
if (!initRouter()) return false
initEvents()

return true
}

// react store
let storeInternal: any = {}
export const getStore = (): any => storeInternal
export const getState = (): any => storeInternal.getState().entities
export const getAllRequests = (): Record<string, DocBaseModel> => {
const result = {}

Object.assign(result, getState().requests)
Object.assign(result, getState().grpcRequests)

return result
}

// react router
let routerInternal: any = {}
export const getRouter = (): any => routerInternal
2 changes: 0 additions & 2 deletions src/services/insomnia/connector/refs-common.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
let currentInsomniaConnectionId: string | null = null

// export const getCurrentInsomniaConnectionId = (): string | null => currentInsomniaConnectionId

export const initConnection = (): void => {
currentInsomniaConnectionId = Math.random().toString(36).substring(2)
localStorage.setItem('insomniaConnectionId', currentInsomniaConnectionId)
Expand Down
11 changes: 11 additions & 0 deletions src/services/insomnia/connector/refs-data.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { InsomniaDocBase, InsomniaRouter } from '../types'
import { getRouter } from './refs-router'

export const getData = (): InsomniaRouter['state']['loaderData'] => getRouter().state.loaderData
export const getAllRequests = (): InsomniaDocBase[] => getData()[':workspaceId']['collection'].map(x => x.doc)
export const getRequestOrUndefined = (requestId: string): InsomniaDocBase | undefined => getAllRequests().find(x => x._id === requestId)
export const getActiveRequest = (): InsomniaDocBase | undefined => getData()['request/:requestId']['activeRequest']
export const getActiveWorkspace = (): InsomniaDocBase | undefined => getData()[':workspaceId'] && getData()[':workspaceId']['activeWorkspace']
export const getActiveProject = (): InsomniaDocBase | undefined => getData()[':workspaceId']['activeProject']
export const getActiveOrgId = (): string | undefined => getRouter().state.location.pathname.match(/^\/organization\/(org_[^/]+)/)?.[1]
export const getAllWorkspaces = (): InsomniaDocBase[] => getData()['/project/:projectId']?.workspaces
62 changes: 48 additions & 14 deletions src/services/insomnia/connector/refs-events.ts
Original file line number Diff line number Diff line change
@@ -1,36 +1,70 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import { DocBaseModel } from '../types'
import { notifyRequestDeleted } from '../events/request-deleted'
import { notifyRequestUpdated } from '../events/request-updated'
import { InsomniaDocBase } from '../types'
import { isCurrentConnectionStillActive } from './refs-common'
import { subscribeForRouteChanged } from './refs-router'
import { getRequestOrUndefined } from './refs-data'
import { notifyRequestSelected } from '../events/request-selected'
import { notifyDebugPageOpenChanged } from '../events/debug-page-opened'

export const subscibeForEvents = (channelName: string, callback: (data: any) => void): void => {
const unsubscribeMethod = (window as any).main.on(channelName, (_: never, data: any) => {
if (!isCurrentConnectionStillActive()) {
unsubscribeMethod()
return
}
export const initEvents = (): void => {
subscibeForDbChangeEvents((doc, method) => {
if (method === 'update' && (doc.type === 'Request' || doc.type === 'GrpcRequest')) notifyRequestUpdated(doc)
if (method === 'remove' && (doc.type === 'Request' || doc.type === 'GrpcRequest')) notifyRequestDeleted(doc)
})

callback(data)
subscribeForRouteChanged((path: string) => {
if (isRouteDebugView(path)) {
notifyDebugPageOpenChanged(true)
const requestId = extractRequestId(path)
if (!requestId) {
console.warn('[plugin-navigator]', 'cannot extract request id from router path', path)
return
}

const doc = getRequestOrUndefined(requestId)
if (!doc) {
console.warn('[plugin-navigator]', 'request not found', requestId)
return
}

notifyRequestSelected(doc)
} else {
notifyDebugPageOpenChanged(false)
}
})
}

export const subscibeForDbChangeEvents = (callback: (data: DocBaseModel, method: string) => void): void => {
subscibeForEvents('db.changes', (changes: any[][]) => changes.forEach((data) => {
// console.log('[plugin-navigator]', 'db.changes', data)

const subscibeForDbChangeEvents = (callback: (data: InsomniaDocBase, method: string) => void): void => {
subscribeForChannelEvents('db.changes', (changes: any[][]) => changes.forEach((data) => {
if (data.length != 3) {
console.warn('[plugin-navigator]', 'unexpected data recevied in db.changes channel', data)
return
}

const method = data[0]
const doc = data[1] as DocBaseModel
const doc = data[1] as InsomniaDocBase

if (!method || !doc) {
console.warn('[plugin-navigator]', 'unexpected method or doc recevied in db.changes channel', data)
return
}

// console.log('[plugin-navigator]', 'db.changes', method, doc)
callback(doc, method)
}))
}

const subscribeForChannelEvents = (channelName: string, callback: (data: any) => void): void => {
const unsubscribeMethod = (window as any).main.on(channelName, (_: never, data: any) => {
if (!isCurrentConnectionStillActive()) {
unsubscribeMethod()
return
}

callback(data)
})
}

const isRouteDebugView = (route: string) => /\/organization\/org_[^/]+\/project\/proj_[^/]+\/workspace\/wrk_[^/]+\/debug/.test(route)
const extractRequestId = (route: string) => route.match(/\/((req_|greq_)[0-9a-z]+)$/)?.[1]
Original file line number Diff line number Diff line change
@@ -1,36 +1,35 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import { InsomniaRouter, InsomniaRouterEvent } from '../types'
import { isCurrentConnectionStillActive } from './refs-common'

export type ReactRefs = {
store: any;
router: any;
}
let internalRouter: InsomniaRouter = {} as InsomniaRouter

export const getReactRefs = (): ReactRefs | null => {
export const initRouter = (): boolean => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const rootElement = document.querySelector('#root') as any
if (!rootElement) {
console.error('[plugin-navigator]', 'root element not found')
return null
return false
}

const containerElement = Object.getOwnPropertyNames(rootElement).findLast(x => x.startsWith('__reactContainer'))
if (!containerElement) {
console.warn('[plugin-navigator]', 'store container element not found')
return null
return false
}

return {
store: rootElement[containerElement].memoizedState.element.props.store,
router: rootElement[containerElement].memoizedState.element.props.children.props.router
}
internalRouter = rootElement[containerElement].memoizedState.element.props.router
return true
}

export const subscribeForRoutePushed = (router: any, callback: (path: string) => void): void => {
const routerUnsubscribeMethod = router.subscribe((data: any) => {
export const getRouter = (): InsomniaRouter => internalRouter

export const subscribeForRouteChanged = (callback: (path: string) => void): void => {
const routerUnsubscribeMethod = internalRouter.subscribe((data: InsomniaRouterEvent) => {
if (!isCurrentConnectionStillActive()) {
routerUnsubscribeMethod()
return
}

if (data.historyAction === 'PUSH') callback(data.location?.pathname)
})
}
15 changes: 15 additions & 0 deletions src/services/insomnia/events/debug-page-opened.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
let lastValue: boolean | undefined = undefined
type Listener = (opened: boolean) => void
const listeners = new Set<Listener>()

export const notifyDebugPageOpenChanged = (opened: boolean) => {
if (lastValue === opened) return

listeners.forEach((listener) => listener(opened))
lastValue = opened
}

export const onDebugPageOpenChanged = (listener: Listener): (() => void) => {
listeners.add(listener)
return () => listeners.delete(listener)
}
4 changes: 2 additions & 2 deletions src/services/insomnia/events/request-deleted.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import { DocBaseModel } from '../types'
import { InsomniaDocBase } from '../types'

type Listener = (doc: DocBaseModel) => void
type Listener = (doc: InsomniaDocBase) => void
const listeners = new Set<Listener>()

export const notifyRequestDeleted = (doc: any) => {
Expand Down
12 changes: 5 additions & 7 deletions src/services/insomnia/events/request-selected.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,18 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import { DocBaseModel } from '../types'
import { InsomniaDocBase } from '../types'

let lastValue = ''
type Listener = (doc: DocBaseModel) => void
type Listener = (doc: InsomniaDocBase) => void
const listeners = new Set<Listener>()

export const notifyRequestSelected = (doc: DocBaseModel) => {
const activeRequestId = (doc as any).activeRequestId
if (!activeRequestId) return

export const notifyRequestSelected = (doc: InsomniaDocBase) => {
const activeRequestId = doc._id
if (activeRequestId === lastValue) {
return
}

listeners.forEach((listener) => listener(doc))
lastValue = doc._id
listeners.forEach((listener) => listener(doc))
}

export const onRequestSelected = (listener: Listener): (() => void) => {
Expand Down
4 changes: 2 additions & 2 deletions src/services/insomnia/events/request-updated.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import { DocBaseModel } from '../types'
import { InsomniaDocBase } from '../types'

let lastValue: any = {}
type Listener = (doc: DocBaseModel) => void
type Listener = (doc: InsomniaDocBase) => void
const listeners = new Set<Listener>()

export const notifyRequestUpdated = (doc: any) => {
Expand Down
15 changes: 0 additions & 15 deletions src/services/insomnia/events/route-changed.ts

This file was deleted.

Loading

0 comments on commit 608c13a

Please sign in to comment.