Skip to content
This repository has been archived by the owner on Aug 28, 2021. It is now read-only.

Commit

Permalink
basic implementation for front end plugin registration (see #77)
Browse files Browse the repository at this point in the history
  • Loading branch information
didimitrie committed Oct 22, 2018
1 parent 871c3ab commit 5d1b192
Show file tree
Hide file tree
Showing 9 changed files with 129 additions and 214 deletions.
4 changes: 4 additions & 0 deletions .env-base
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ SERVER_NAME="Default Server"
# by default.
PUBLIC_STREAMS=true

# PLUGIN_DIRS: Dirs to scan for speckle plugins (comma separated). For example, if you install
# some other modules in `./test` and `./wonderful`, you could use PLUGIN_DIRS="./test,./wonderful"
PLUGIN_DIRS="./node_modules/@speckle,./plugins"

# PORT: The port you want the speckle server to run on. Make sure the port is accesible
# if you have any firewalls set up (ie, ufw).
PORT=3000
Expand Down
9 changes: 3 additions & 6 deletions app/api/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -155,14 +155,11 @@ module.exports = function ( app, express, urlRoot ) {

let serverDescription = {
serverName: process.env.SERVER_NAME,
maxRequestSize: process.env.REQ_SIZE
version: '1.x.x',
api: routes,
}

r.get( '/', ( req, res ) => {
serverDescription.routes = routes
serverDescription.version = '1.x.x'
res.json( serverDescription )
} )
r.get( '/', ( req, res ) => res.json( serverDescription ) )

// mount all these routes up
app.use( urlRoot, r )
Expand Down
169 changes: 0 additions & 169 deletions app/api/v1/index.js

This file was deleted.

48 changes: 48 additions & 0 deletions plugins.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
const fs = require( 'fs' )
const path = require( 'path' )
const winston = require( 'winston' )

const isDirectory = source => fs.lstatSync( source ).isDirectory( )
const getDirectories = source => fs.readdirSync( source ).map( name => path.join( source, name ) ).filter( isDirectory )

module.exports = ( ) => {
winston.debug( 'Scanning for speckle plugins...' )

// gather potential plugin subdirectories
const rootDirs = process.env.PLUGIN_DIRS.split( `,` )
let pluginDirs = [ ]
rootDirs.forEach( dir => {
if ( fs.existsSync( dir ) ) {
let dirs = getDirectories( dir )
pluginDirs = [ ...dirs, pluginDirs ]

This comment has been minimized.

Copy link
@logan12358

logan12358 Jan 14, 2019

Does this do what it's supposed to?

[ ...[ 1, 2 ], [ 3, 4 ] ] evaluates to [ 1, 2, [ 3, 4 ] ]. Should it be pluginDirs.push(...dirs)?

This comment has been minimized.

Copy link
@didimitrie

didimitrie Jan 14, 2019

Author Member

i think it was meant to catch the root dir as well. ie, if you add to .env a dir called hello-plugin, it will try to check if that dir is itself hosting a plugin and/or any of its subdirs. uh... does that make sense? I think it did to me at the time...

This comment has been minimized.

Copy link
@logan12358

logan12358 Jan 14, 2019

I think I get what you mean, and that behaviour makes sense.

Currently, if we set PLUGIN_DIRS="./a,./b", with an actual plugin in a folder within each, then at line 21 of this file we have pluginDirs equal to [ 'b/plugin-b', [ 'a/plugin-a', [] ] ]. It should be [ 'a/plugin-a', 'a', 'b/plugin-b', 'b' ] (or some permutation).

We could achieve this with pluginDirs.push(...dirs, dir).

} else
winston.warn( `specified plugin directory does not exist: ${dir}` )
} )

// read in manifest files
let plugins = []
pluginDirs.forEach( dir => {
let file = path.normalize( `${dir}//speckle-plugin-manifest.json` )
if ( fs.existsSync( file ) ) {
let obj = JSON.parse( fs.readFileSync( file, 'utf8' ) )
obj.sourceDir = dir
plugins.push( obj )
} else
winston.warn( `No plugin manifest file found in ${dir}.` )
} )

// check for conflicts
let serveLocations = []
plugins.forEach( pl => {
if ( serveLocations.indexOf( pl.serveFrom ) < 0 )
serveLocations.push( pl.serveFrom )
else {
winston.warn( `Conflicting plugin endpoint found at: ${pl.serveFrom} in folder ${pl.sourceDir}.
It will load from ${pl.serveFrom + '-dupe'} instead.` )
pl.serveFrom += '-dupe'
}
} )
winston.debug( `Found ${plugins.length} plugin(s):${plugins.map( p => ' ' + p.name )}` )

return plugins
}
27 changes: 27 additions & 0 deletions plugins/speckle-sample-plugin/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<h1>Sample Speckle Frontend Plugin</h1>
<p>This is just an example of how you can register a speckle frontend plugin. Its manifest file looks something like this:</p>
<pre>
{
"name": "Sample Plugin",
"version":"",
"desc": "This plugin tests plugins",
"serveFrom": "/sample-plugin",
"author": "DAS",
"contact":"[email protected]",
"homepage":"https://dimitrie.org"
}
</pre>
<p>
This file (`speckle-plugin-manifest.json`) is picked up by the server which then serves the plugin statically from the location specified.
</p>
<p>
Thanks for watching 👋 <a href="https://speckle.works">Speckle!</a>
</p>
<style type="text/css">
a,p,h1 {
font-family: sans-serif;
}
h1 {
color: royalblue;
}
</style>
9 changes: 9 additions & 0 deletions plugins/speckle-sample-plugin/speckle-plugin-manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"name": "Sample Plugin",
"version":"0.1.0",
"desc": "This plugin tests plugins",
"serveFrom": "/sample-plugin",
"author": "DAS",
"contact":"[email protected]",
"homepage":"https://dimitrie.org"
}
Loading

0 comments on commit 5d1b192

Please sign in to comment.