Skip to content

Commit

Permalink
Fix loading external plugins in embedded linear-genome-view demo (#3482)
Browse files Browse the repository at this point in the history
* Add baseUrl option to loadPlugins in linear-genome-view

* Add error handling for loadPlugins

* Small typescripting
  • Loading branch information
cmdcolin committed Jan 27, 2023
1 parent b3f0651 commit fc286e0
Show file tree
Hide file tree
Showing 4 changed files with 144 additions and 129 deletions.
48 changes: 25 additions & 23 deletions packages/core/PluginLoader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,13 @@ import ReExports from './ReExports'
import { isElectron } from './util'

export interface UMDLocPluginDefinition {
umdLoc: { uri: string; baseUri?: string }
umdLoc: {
uri: string
baseUri?: string
}
name: string
}

export interface UMDUrlPluginDefinition {
umdUrl: string
name: string
Expand Down Expand Up @@ -78,10 +82,6 @@ export interface LoadedPlugin {
default: PluginConstructor
}

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

function getGlobalObject(): Window {
// Based on window-or-global
// https://github.com/purposeindustries/window-or-global/blob/322abc71de0010c9e5d9d0729df40959e1ef8775/lib/index.js
Expand All @@ -101,13 +101,13 @@ function isInWebWorker(globalObject: ReturnType<typeof getGlobalObject>) {
export default class PluginLoader {
definitions: PluginDefinition[] = []

fetchESM?: (url: string) => Promise<unknown>
fetchESM?: (url: string) => Promise<LoadedPlugin>
fetchCJS?: (url: string) => Promise<LoadedPlugin>

constructor(
defs: PluginDefinition[] = [],
args?: {
fetchESM?: (url: string) => Promise<unknown>
fetchESM?: (url: string) => Promise<LoadedPlugin>
fetchCJS?: (url: string) => Promise<LoadedPlugin>
},
) {
Expand All @@ -133,8 +133,8 @@ export default class PluginLoader {
)
}

async loadCJSPlugin(def: CJSPluginDefinition, windowHref: string) {
const parsedUrl = new URL(def.cjsUrl, windowHref)
async loadCJSPlugin(def: CJSPluginDefinition, baseUri?: string) {
const parsedUrl = new URL(def.cjsUrl, baseUri)
if (parsedUrl.protocol !== 'http:' && parsedUrl.protocol !== 'https:') {
throw new Error(
`Cannot load plugins using protocol "${parsedUrl.protocol}"`,
Expand All @@ -147,20 +147,22 @@ export default class PluginLoader {
return this.fetchCJS(parsedUrl.href)
}

async loadESMPlugin(def: ESMPluginDefinition, windowHref: string) {
async loadESMPlugin(def: ESMPluginDefinition, baseUri?: string) {
const parsedUrl =
'esmUrl' in def
? new URL(def.esmUrl, windowHref)
? new URL(def.esmUrl, baseUri)
: 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}"`,
)
}
const plugin = (await this.fetchESM?.(parsedUrl.href)) as
| LoadedPlugin
| undefined

if (!this.fetchESM) {
throw new Error(`No ESM fetcher installed`)
}
const plugin = await this.fetchESM(parsedUrl.href)

if (!plugin) {
throw new Error(`Could not load ESM plugin: ${parsedUrl}`)
Expand All @@ -170,13 +172,13 @@ export default class PluginLoader {

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

if (parsedUrl.protocol !== 'http:' && parsedUrl.protocol !== 'https:') {
Expand All @@ -200,14 +202,14 @@ export default class PluginLoader {
return plugin
}

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

async load(windowHref = '') {
async load(baseUri?: string) {
return Promise.all(
this.definitions.map(async definition => ({
plugin: await this.loadPlugin(definition, windowHref),
plugin: await this.loadPlugin(definition, baseUri),
definition,
})),
)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import PluginLoader from '@jbrowse/core/PluginLoader'
import PluginLoader, { LoadedPlugin } from '@jbrowse/core/PluginLoader'

interface PluginDefinition {
name: string
Expand All @@ -7,9 +7,12 @@ interface PluginDefinition {

export default async function loadPlugins(
pluginDefinitions: PluginDefinition[],
args?: { fetchESM: (url: string) => Promise<unknown> },
args?: {
fetchESM?: (url: string) => Promise<LoadedPlugin>
baseUrl?: string
},
) {
const pluginLoader = new PluginLoader(pluginDefinitions, args)
pluginLoader.installGlobalReExports(window)
return pluginLoader.load('')
return pluginLoader.load(args?.baseUrl)
}
9 changes: 6 additions & 3 deletions products/jbrowse-react-linear-genome-view/src/loadPlugins.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import PluginLoader from '@jbrowse/core/PluginLoader'
import PluginLoader, { LoadedPlugin } from '@jbrowse/core/PluginLoader'

interface PluginDefinition {
name: string
Expand All @@ -7,9 +7,12 @@ interface PluginDefinition {

export default async function loadPlugins(
pluginDefinitions: PluginDefinition[],
args?: { fetchESM: (url: string) => Promise<unknown> },
args?: {
fetchESM?: (url: string) => Promise<LoadedPlugin>
baseUrl?: string
},
) {
const pluginLoader = new PluginLoader(pluginDefinitions, args)
pluginLoader.installGlobalReExports(window)
return pluginLoader.load('')
return pluginLoader.load(args?.baseUrl)
}
Loading

0 comments on commit fc286e0

Please sign in to comment.