kopia lustrzana https://gitlab.com/rysiekpl/libresilient
service-worker: plugin loader rewritten, enabling using the same plugin multiple times (ref. #15); any-of: using the "uses" config field instead of old "plugins"
rodzic
bcf7ed4c32
commit
5f6552e322
|
@ -19,7 +19,7 @@
|
|||
// sane defaults
|
||||
let defaultConfig = {
|
||||
// list of plugins to run simultaneously
|
||||
plugins: [{
|
||||
uses: [{
|
||||
name: "alt-fetch"
|
||||
},{
|
||||
name: "gun-ipfs"
|
||||
|
@ -33,9 +33,9 @@
|
|||
* getting content using regular HTTP(S) fetch()
|
||||
*/
|
||||
let fetchContent = (url) => {
|
||||
LR.log(pluginName, `using: [${config.plugins.map(p=>p.name).join(', ')}]!`)
|
||||
LR.log(pluginName, `using: [${config.uses.map(p=>p.name).join(', ')}]!`)
|
||||
return Promise.any(
|
||||
config.plugins.map(p=>p.fetch(url))
|
||||
config.uses.map(p=>p.fetch(url))
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -43,10 +43,10 @@
|
|||
// with some additional metadata
|
||||
return {
|
||||
name: pluginName,
|
||||
description: `Running simultaneously: [${config.plugins.map(p=>p.name).join(', ')}]`,
|
||||
description: `Running simultaneously: [${config.uses.map(p=>p.name).join(', ')}]`,
|
||||
version: 'COMMIT_UNKNOWN',
|
||||
fetch: fetchContent,
|
||||
uses: config.plugins
|
||||
uses: config.uses
|
||||
}
|
||||
|
||||
})
|
||||
|
|
|
@ -110,61 +110,97 @@ try {
|
|||
|
||||
// get the config
|
||||
self.importScripts("./config.js")
|
||||
self.log('service-worker', 'config loaded.')
|
||||
|
||||
// create the LibResilientPluginConstructors map
|
||||
var LibResilientPluginConstructors = new Map()
|
||||
|
||||
// this is the stash for plugins that need dependencies instantiated first
|
||||
var dependentPlugins = new Array()
|
||||
|
||||
// only now load the plugins (config.js could have changed the defaults)
|
||||
for (var pluginConfig of self.LibResilientConfig.plugins) {
|
||||
while (self.LibResilientConfig.plugins.length > 0) {
|
||||
|
||||
// load a plugin script, only if not yet loaded
|
||||
// get the first plugin config from the array
|
||||
let pluginConfig = self.LibResilientConfig.plugins.shift()
|
||||
self.log('service-worker', `handling plugin type: ${pluginConfig.name}`)
|
||||
|
||||
// load the relevant plugin script (if not yet loaded)
|
||||
if (!LibResilientPluginConstructors.has(pluginConfig.name)) {
|
||||
self.log('service-worker', `${pluginConfig.name}: loading plugin's source`)
|
||||
self.importScripts(`./plugins/${pluginConfig.name}.js`)
|
||||
}
|
||||
|
||||
// instantiate the plugin
|
||||
self.LibResilientPlugins.push(
|
||||
LibResilientPluginConstructors.get(pluginConfig.name)(self, pluginConfig)
|
||||
)
|
||||
|
||||
// check if it loaded properly
|
||||
// TODO: should be done in a tad less resource-intensive way perhaps? then again, this is a short array anyway
|
||||
var plugin = self.LibResilientPlugins.find(p=>p.name===pluginConfig.name)
|
||||
if (plugin === undefined) {
|
||||
throw new Error(`Plugin not found: ${pluginConfig.name} (available plugins: ${self.LibResilientPlugins.map(p=>p.name).join(', ')})`)
|
||||
}
|
||||
|
||||
// handling "uses" plugins
|
||||
|
||||
// make sure that the indirect flag is set if needed
|
||||
if (self.LibResilientConfig.plugins[plugin.name].indirect===true) {
|
||||
plugin.indirect=true
|
||||
self.log('service-worker', `Loaded plugin: ${plugin.name} (indirect)`)
|
||||
} else {
|
||||
self.log('service-worker', `Loaded plugin: ${plugin.name}`)
|
||||
}
|
||||
// make sure plugins used by the just-loaded plugin are also added to the list
|
||||
// but don't load a plugin twice
|
||||
if (typeof plugin.uses !== "undefined") {
|
||||
for (var p in plugin.uses) {
|
||||
if (plugins.indexOf(p) < 0) {
|
||||
// okay, this plugin has not been added to the plugins list yet
|
||||
// let's do that
|
||||
plugins.push(p)
|
||||
// but also, let's make sure that the config for them is available for use
|
||||
var pConfig = {...self.LibResilientConfig.plugins[p], ...plugin.uses[p]}
|
||||
// set the indirect flag,
|
||||
// since we only have this plugin here to facilitate use by other plugins
|
||||
pConfig.indirect = true
|
||||
// set the config
|
||||
self.LibResilientConfig.plugins[p] = pConfig
|
||||
}
|
||||
// do we have any dependencies we should handle first?
|
||||
if (typeof pluginConfig.uses !== "undefined") {
|
||||
self.log('service-worker', `${pluginConfig.name}: ${pluginConfig.uses.length} dependencies found`)
|
||||
|
||||
// move the dependency plugin configs to LibResilientConfig to be worked on next
|
||||
for (var i=(pluginConfig.uses.length); i--; i>=0) {
|
||||
self.log('service-worker', `${pluginConfig.name}: dependency found: ${pluginConfig.uses[i].name}`)
|
||||
// put the plugin config in front of the plugin configs array
|
||||
self.LibResilientConfig.plugins.unshift(pluginConfig.uses[i])
|
||||
// set each dependency plugin config to false so that we can keep track
|
||||
// as we fill those gaps later with instantiated dependency plugins
|
||||
pluginConfig.uses[i] = false
|
||||
}
|
||||
|
||||
// stash the plugin config until we have all the dependencies handled
|
||||
self.log('service-worker', `${pluginConfig.name}: not instantiating until dependencies are ready`)
|
||||
dependentPlugins.push(pluginConfig)
|
||||
|
||||
// move on to the next plugin config, which at this point will be
|
||||
// the first of dependencies for the plugin whose config got stashed
|
||||
continue;
|
||||
}
|
||||
|
||||
do {
|
||||
|
||||
// instantiate the plugin
|
||||
self.log('service-worker', `${pluginConfig.name}: instantiated`)
|
||||
let plugin = LibResilientPluginConstructors.get(pluginConfig.name)(self, pluginConfig)
|
||||
|
||||
// do we have a stashed plugin that requires dependencies?
|
||||
if (dependentPlugins.length === 0) {
|
||||
// no we don't; so, this plugin goes directly to the plugin list
|
||||
self.LibResilientPlugins.push(plugin)
|
||||
// we're done here
|
||||
self.log('service-worker', `${pluginConfig.name}: no dependent plugins, pushing directly to LibResilientPlugins`)
|
||||
break;
|
||||
}
|
||||
|
||||
// at this point clearly there is at least one element in dependentPlugins
|
||||
// so we can safely assume that the freshly instantiated plugin is a dependency
|
||||
//
|
||||
// in that case let's find the first empty spot for a dependency
|
||||
let didx = dependentPlugins[dependentPlugins.length - 1].uses.indexOf(false)
|
||||
// assign the freshly instantiated plugin as that dependency
|
||||
dependentPlugins[dependentPlugins.length - 1].uses[didx] = plugin
|
||||
self.log('service-worker', `${pluginConfig.name}: assigning as dependency (#${didx}) to ${dependentPlugins[dependentPlugins.length - 1].name}`)
|
||||
|
||||
// was this the last one?
|
||||
if (didx >= dependentPlugins[dependentPlugins.length - 1].uses.length - 1) {
|
||||
// yup, last one!
|
||||
self.log('service-worker', `${pluginConfig.name}: this was the last dependency of ${dependentPlugins[dependentPlugins.length - 1].name}`)
|
||||
// we can now proceed to instantiate the last element of dependentPlugins
|
||||
pluginConfig = dependentPlugins.pop()
|
||||
continue
|
||||
}
|
||||
|
||||
// it is not the last one, so there should be more dependency plugins to instantiate first
|
||||
// before we can instantiate the last of element of dependentPlugins
|
||||
// but that requires the full treatment, including checing the `uses` field for their configs
|
||||
self.log('service-worker', `${pluginConfig.name}: not yet the last dependency of ${dependentPlugins[dependentPlugins.length - 1].name}`)
|
||||
pluginConfig = false
|
||||
|
||||
// if pluginConfig is not false, rinse-repeat the plugin instantiation steps
|
||||
// since we are dealing with the last element of dependentPlugins
|
||||
} while (pluginConfig !== false)
|
||||
|
||||
}
|
||||
|
||||
// inform
|
||||
self.log('service-worker', `DEBUG: Strategy in use: ${self.LibResilientPlugins.filter(p=>(!p.indirect)).map(p=>p.name).join(', ')}`)
|
||||
self.log('service-worker', `DEBUG: Strategy in use: ${self.LibResilientPlugins.map(p=>p.name).join(', ')}`)
|
||||
|
||||
} catch(e) {
|
||||
// we only get a cryptic "Error while registering a service worker"
|
||||
|
@ -436,7 +472,7 @@ let getResourceThroughLibResilient = (request, clientId, useStashed=true, doStas
|
|||
|
||||
// filter out stash plugins if need be
|
||||
var LibResilientPluginsRun = self.LibResilientPlugins.filter((plugin)=>{
|
||||
return ( (!plugin.indirect) && (useStashed || typeof plugin.stash !== 'function') )
|
||||
return ( useStashed || typeof plugin.stash !== 'function')
|
||||
})
|
||||
|
||||
/**
|
||||
|
@ -627,7 +663,7 @@ self.addEventListener('fetch', event => {
|
|||
if (client !== null) {
|
||||
client.postMessage({
|
||||
clientId: clientId,
|
||||
plugins: self.LibResilientPlugins.filter(p=>(!p.indirect)).map((p)=>{return p.name}),
|
||||
plugins: self.LibResilientPlugins.map((p)=>{return p.name}),
|
||||
serviceWorker: 'COMMIT_UNKNOWN'
|
||||
})
|
||||
}
|
||||
|
|
Ładowanie…
Reference in New Issue