Skip to content

Commit

Permalink
Test
Browse files Browse the repository at this point in the history
  • Loading branch information
cmdcolin committed Oct 12, 2022
1 parent 2125886 commit ada36fd
Show file tree
Hide file tree
Showing 15 changed files with 148 additions and 130 deletions.
82 changes: 50 additions & 32 deletions packages/core/PluginLoader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@ import { PluginConstructor } from './Plugin'
import ReExports from './ReExports'
import { isElectron } from './util'

export interface UMDPluginDefinition {
export interface UMDLocPluginDefinition {
umdLoc: { uri: string; baseUri?: string }
name: string
}
export interface UMDUrlPluginDefinition {
umdUrl: string
name: string
}
Expand All @@ -14,24 +18,37 @@ export interface LegacyUMDPluginDefinition {
name: string
}

type UMDPluginDefinition = UMDLocPluginDefinition | UMDUrlPluginDefinition

export function isUMDPluginDefinition(
def: PluginDefinition,
): def is UMDPluginDefinition | LegacyUMDPluginDefinition {
return (
((def as UMDPluginDefinition).umdUrl !== undefined ||
(def as LegacyUMDPluginDefinition).url !== undefined) &&
((def as UMDUrlPluginDefinition).umdUrl !== undefined ||
(def as LegacyUMDPluginDefinition).url !== undefined ||
(def as UMDLocPluginDefinition).umdLoc !== undefined) &&
(def as LegacyUMDPluginDefinition | UMDPluginDefinition).name !== undefined
)
}

export interface ESMPluginDefinition {
export interface ESMLocPluginDefinition {
esmLoc: { uri: string; baseUri?: string }
}
export interface ESMUrlPluginDefinition {
esmUrl: string
}

export type ESMPluginDefinition =
| ESMLocPluginDefinition
| ESMUrlPluginDefinition

export function isESMPluginDefinition(
def: PluginDefinition,
): def is ESMPluginDefinition {
return (def as ESMPluginDefinition).esmUrl !== undefined
return (
(def as ESMUrlPluginDefinition).esmUrl !== undefined ||
(def as ESMLocPluginDefinition).esmLoc !== undefined
)
}

export interface CJSPluginDefinition {
Expand All @@ -45,9 +62,11 @@ export function isCJSPluginDefinition(
}

export interface PluginDefinition
extends Partial<UMDPluginDefinition>,
extends Partial<UMDUrlPluginDefinition>,
Partial<UMDLocPluginDefinition>,
Partial<LegacyUMDPluginDefinition>,
Partial<ESMPluginDefinition>,
Partial<ESMLocPluginDefinition>,
Partial<ESMUrlPluginDefinition>,
Partial<CJSPluginDefinition> {}

export interface PluginRecord {
Expand All @@ -59,8 +78,8 @@ export interface LoadedPlugin {
default: PluginConstructor
}

export function getWindowPath(configPath: string) {
return window.location.href + configPath
export function getWindowPath(windowHref: string) {
return window.location.href + windowHref
}

function getGlobalObject(): Window {
Expand Down Expand Up @@ -99,7 +118,6 @@ export default class PluginLoader {

async loadScript(scriptUrl: string): Promise<void> {
const globalObject = getGlobalObject()
console.log({ scriptUrl }, isInWebWorker(globalObject))
if (!isInWebWorker(globalObject)) {
return domLoadScript(scriptUrl)
}
Expand All @@ -115,14 +133,8 @@ export default class PluginLoader {
)
}

async loadCJSPlugin(def: CJSPluginDefinition, configPath: string) {
let parsedUrl: URL
try {
parsedUrl = new URL(def.cjsUrl, configPath)
} catch (error) {
console.error(error)
throw new Error(`Error parsing URL: ${def.cjsUrl}`)
}
async loadCJSPlugin(def: CJSPluginDefinition, windowHref: string) {
const parsedUrl = new URL(def.cjsUrl, windowHref)
if (parsedUrl.protocol !== 'http:' && parsedUrl.protocol !== 'https:') {
throw new Error(
`Cannot load plugins using protocol "${parsedUrl.protocol}"`,
Expand All @@ -135,14 +147,17 @@ export default class PluginLoader {
return this.fetchCJS(parsedUrl.href)
}

async loadESMPlugin(def: ESMPluginDefinition, configPath: string) {
const parsedUrl = new URL(def.esmUrl, configPath)
async loadESMPlugin(def: ESMPluginDefinition, windowHref: string) {
const parsedUrl =
'esmUrl' in def
? new URL(def.esmUrl, windowHref)
: new URL(def.esmLoc.uri, def.esmLoc.baseUri)

if (parsedUrl.protocol !== 'http:' && parsedUrl.protocol !== 'https:') {
throw new Error(
`cannot load plugins using protocol "${parsedUrl.protocol}"`,
)
}
console.log({ parsedUrl })
const plugin = (await this.fetchESM?.(parsedUrl.href)) as
| LoadedPlugin
| undefined
Expand All @@ -155,17 +170,20 @@ export default class PluginLoader {

async loadUMDPlugin(
def: UMDPluginDefinition | LegacyUMDPluginDefinition,
configPath: string,
windowHref: string,
) {
const umdUrl = 'url' in def ? def.url : def.umdUrl
console.log({ umdUrl })
const parsedUrl = new URL(umdUrl, getWindowPath(configPath))
const parsedUrl =
'url' in def
? new URL(def.url, windowHref)
: 'umdUrl' in def
? new URL(def.umdUrl, windowHref)
: new URL(def.umdLoc.uri, def.umdLoc.baseUri)

if (parsedUrl.protocol !== 'http:' && parsedUrl.protocol !== 'https:') {
throw new Error(
`cannot load plugins using protocol "${parsedUrl.protocol}"`,
)
}
console.log(`${parsedUrl}`)
await this.loadScript(parsedUrl.href)
const moduleName = def.name
const umdName = `JBrowsePlugin${moduleName}`
Expand All @@ -182,14 +200,14 @@ export default class PluginLoader {
return plugin
}

async loadPlugin(def: PluginDefinition, configPath: string) {
async loadPlugin(def: PluginDefinition, windowHref: string) {
let plugin: LoadedPlugin
if (isElectron && isCJSPluginDefinition(def)) {
plugin = await this.loadCJSPlugin(def, configPath)
plugin = await this.loadCJSPlugin(def, windowHref)
} else if (isESMPluginDefinition(def)) {
plugin = await this.loadESMPlugin(def, configPath)
plugin = await this.loadESMPlugin(def, windowHref)
} else if (isUMDPluginDefinition(def)) {
plugin = await this.loadUMDPlugin(def, configPath)
plugin = await this.loadUMDPlugin(def, windowHref)
} else if (!isElectron && isCJSPluginDefinition(def)) {
throw new Error(
`CommonJS plugin found, but not in a NodeJS environment: ${JSON.stringify(
Expand All @@ -211,10 +229,10 @@ export default class PluginLoader {
)
}

async load(configPath: string) {
async load(windowHref: string) {
return Promise.all(
this.definitions.map(async definition => ({
plugin: await this.loadPlugin(definition, configPath),
plugin: await this.loadPlugin(definition, windowHref),
definition,
})),
)
Expand Down
7 changes: 4 additions & 3 deletions packages/core/PluginManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -218,8 +218,11 @@ export default class PluginManager {
if (this.configured) {
throw new Error('JBrowse already configured, cannot add plugins')
}

// if 'load' is an object with a 'plugin' attrbute, then we assume
// 'plugin' is the plugin class. else, 'load' itself is the plugin class
const [plugin, metadata = {}] =
load instanceof Plugin ? [load, {}] : [load.plugin, load.metadata]
'plugin' in load ? [load.plugin, load.metadata] : [load, {}]

if (this.plugins.includes(plugin)) {
throw new Error('plugin already installed')
Expand Down Expand Up @@ -265,8 +268,6 @@ export default class PluginManager {

this.configured = true

// console.log(JSON.stringify(getSnapshot(model)))

return this
}

Expand Down
5 changes: 4 additions & 1 deletion packages/core/rpc/RpcManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,10 @@ export default class RpcManager {
}
newDriver = new WebWorkerRpcDriver(
{ ...backendConfiguration, config },
{ plugins: this.pluginManager.runtimePluginDefinitions },
{
plugins: this.pluginManager.runtimePluginDefinitions,
windowHref: window.location.href,
},
)
} else {
throw new Error(`requested RPC driver "${backendName}" is not installed`)
Expand Down
5 changes: 4 additions & 1 deletion packages/core/rpc/WebWorkerRpcDriver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,10 @@ export default class WebWorkerRpcDriver extends BaseRpcDriver {

constructor(
args: WebWorkerRpcDriverConstructorArgs,
public workerBootConfiguration: { plugins: PluginDefinition[] },
public workerBootConfiguration: {
plugins: PluginDefinition[]
windowHref: string
},
) {
super(args)
this.makeWorkerInstance = args.makeWorkerInstance
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

exports[`HierarchicalTrackSelector widget renders nothing with no assembly 1`] = `
<button
class="MuiButtonBase-root MuiFab-root MuiFab-circular MuiFab-sizeSmall MuiFab-secondary tss-805w6w-fab css-10w0o2e-MuiButtonBase-root-MuiFab-root"
class="MuiButtonBase-root MuiFab-root MuiFab-circular MuiFab-sizeSmall MuiFab-secondary MuiFab-root MuiFab-circular MuiFab-sizeSmall MuiFab-secondary tss-805w6w-fab css-10w0o2e-MuiButtonBase-root-MuiFab-root"
tabindex="0"
type="button"
>
Expand Down
5 changes: 2 additions & 3 deletions products/jbrowse-desktop/src/StartScreen/util.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ const defaultInternetAccounts = [

export async function loadPluginManager(configPath: string) {
const snap = await ipcRenderer.invoke('loadSession', configPath)
const pm = await createPluginManager(snap, configPath)
const pm = await createPluginManager(snap)
// @ts-ignore
pm.rootModel?.setSessionPath(configPath)
return pm
Expand All @@ -53,7 +53,6 @@ export async function loadPluginManager(configPath: string) {
export async function createPluginManager(
// eslint-disable-next-line @typescript-eslint/no-explicit-any
configSnapshot: any,
configPath: string,
initialTimestamp = +Date.now(),
) {
const pluginLoader = new PluginLoader(configSnapshot.plugins, {
Expand Down Expand Up @@ -102,7 +101,7 @@ export async function createPluginManager(
},
})
pluginLoader.installGlobalReExports(window)
const runtimePlugins = await pluginLoader.load(configPath)
const runtimePlugins = await pluginLoader.load(window.location.href)
const pm = new PluginManager([
...corePlugins.map(P => ({
plugin: new P(),
Expand Down
14 changes: 6 additions & 8 deletions products/jbrowse-desktop/src/rootModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -542,24 +542,22 @@ export default function rootModelFactory(pluginManager: PluginManager) {
},

afterCreate() {
document.addEventListener('keydown', event => {
document.addEventListener('keydown', e => {
if (self.history.canRedo) {
if (
// ctrl+shift+z or cmd+shift+z
((event.ctrlKey || event.metaKey) &&
event.shiftKey &&
event.code === 'KeyZ') ||
((e.ctrlKey || e.metaKey) && e.shiftKey && e.code === 'KeyZ') ||
// ctrl+y
(event.ctrlKey && !event.shiftKey && event.code === 'KeyY')
(e.ctrlKey && !e.shiftKey && e.code === 'KeyY')
) {
self.history.redo()
}
} else if (self.history.canUndo) {
if (
// ctrl+z or cmd+z
(event.ctrlKey || event.metaKey) &&
!event.shiftKey &&
event.code === 'KeyZ'
(e.ctrlKey || e.metaKey) &&
!e.shiftKey &&
e.code === 'KeyZ'
) {
self.history.undo()
}
Expand Down
15 changes: 15 additions & 0 deletions products/jbrowse-web/public/umd_plugin.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
function MyComponent() {
return 'Hello world'
}

class MyClass2 {
name = 'UMDUrlPlugin'
install(pluginManager) {}
configure() {}
}

// the plugin will be included in both the main thread and web worker, so
// install plugin to either window or self (webworker global scope)
;(typeof self !== 'undefined' ? self : window).JBrowsePluginUMDUrlPlugin = {
default: MyClass2,
}
26 changes: 9 additions & 17 deletions products/jbrowse-web/src/SessionLoader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ function addRelativeUris(config: Config, base: URL) {

// raw readConf alternative for before conf is initialized
function readConf(
{ configuration = {} }: { configuration?: { [key: string]: string } },
{ configuration = {} }: { configuration?: Config },
attr: string,
def: string,
) {
Expand All @@ -53,32 +53,25 @@ async function checkPlugins(pluginsToCheck: PluginDefinition[]) {
if (isUMDPluginDefinition(p)) {
return Boolean(
storePlugins.plugins.find(
storePlugin =>
isUMDPluginDefinition(storePlugin) &&
(('url' in storePlugin &&
'url' in p &&
storePlugin.url === p.url) ||
('umdUrl' in storePlugin &&
'umdUrl' in p &&
storePlugin.umdUrl === p.umdUrl)),
p =>
isUMDPluginDefinition(p) &&
(('url' in p && 'url' in p && p.url === p.url) ||
('umdUrl' in p && 'umdUrl' in p && p.umdUrl === p.umdUrl)),
),
)
}
if (isESMPluginDefinition(p)) {
return Boolean(
storePlugins.plugins.find(
storePlugin =>
isESMPluginDefinition(storePlugin) &&
storePlugin.esmUrl === p.esmUrl,
p =>
isESMPluginDefinition(p) && 'esmUrl' in p && p.esmUrl === p.esmUrl,
),
)
}
if (isCJSPluginDefinition(p)) {
return Boolean(
storePlugins.plugins.find(
storePlugin =>
isCJSPluginDefinition(storePlugin) &&
storePlugin.cjsUrl === p.cjsUrl,
p => isCJSPluginDefinition(p) && p.cjsUrl === p.cjsUrl,
),
)
}
Expand Down Expand Up @@ -212,8 +205,7 @@ const SessionLoader = types
fetchESM: url => import(/* webpackIgnore:true */ url),
})
pluginLoader.installGlobalReExports(window)
const runtimePlugins = await pluginLoader.load(self.configPath || '')
console.log({ runtimePlugins })
const runtimePlugins = await pluginLoader.load(window.location.href)
self.setRuntimePlugins([...runtimePlugins])
} catch (e) {
console.error(e)
Expand Down
14 changes: 12 additions & 2 deletions products/jbrowse-web/src/__snapshots__/jbrowseModel.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,6 @@ Object {
},
],
"formatAbout": Object {
"conf": "jexl:{extraField:'important data'}",
"hideUris": true,
},
"metadata": Object {
Expand Down Expand Up @@ -280,7 +279,18 @@ Object {
"type": "GoogleDriveOAuthInternetAccount",
},
],
"plugins": Array [],
"plugins": Array [
Object {
"name": "UMDLocPlugin",
"umdLoc": Object {
"uri": "umd_plugin.js",
},
},
Object {
"name": "UMDUrlPlugin",
"umdUrl": "umd_plugin.js",
},
],
"tracks": Array [
Object {
"adapter": Object {
Expand Down
Loading

0 comments on commit ada36fd

Please sign in to comment.