Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
},
"homepage": "https://github.com/nxus/core",
"engines": {
"node": "~6"
"node": "~6,~8,~10~,~12"
},
"dependencies": {
"async": "^2.0.1",
Expand Down
14 changes: 8 additions & 6 deletions src/Application.js
Original file line number Diff line number Diff line change
Expand Up @@ -367,17 +367,19 @@ export default class Application extends Dispatcher {
* @return {[type]}
*/
_bootPlugin(plugin) {
var name = plugin._pluginInfo.name
let path = plugin._pluginInfo.modulePath
let pluginInfo = plugin._pluginInfo

if(plugin.default)
plugin = plugin.default

let name = (plugin._moduleName && plugin._moduleName()) || pluginInfo.name
let pluginInstance = null
let promise = null
//if (this.config.debug) console.log(' ------- ', plugin)

if (this._pluginInstances[name] !== undefined) {
this.log.error('Duplicate module found', name)
process.exit()
}
if(plugin.default)
plugin = plugin.default

if(plugin.__appRef && plugin.__appRef() !== this) {
this.log.error('Separate Nxus Core module detected in', name)
Expand All @@ -393,7 +395,7 @@ export default class Application extends Dispatcher {
this._pluginInstances[name] = pluginInstance
promise = Promise.resolve(pluginInstance)
} catch(e) {
this.log.error('Error booting module '+name+' from '+path, e)
this.log.error('Error booting module '+name+' from '+pluginInfo.modulePath, e)
this.log.error(e.stack)
process.exit()
}
Expand Down
66 changes: 56 additions & 10 deletions src/NxusModule.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,51 @@
import morph from 'morph'
import path from 'path'
import fs from 'fs'
import stackTrace from 'stack-trace'
import ModuleProxy from './ModuleProxy'
import {application} from './Application'
import Logger from './Logger'
import deepExtend from 'deep-extend'

function __dirName(constructorName) {
function _filenameOf(construct) {
for (let [k,v] of Object.entries(require.cache)) {
let exports = v.exports && v.exports.default ? v.exports : {default: v.exports}
for (let [,ex] of Object.entries(exports)) {
if (ex == construct) {
return v.filename
}
}
}
for (let site of stackTrace.get()) {
if(site.getFunctionName() == constructorName) {
return path.dirname(site.getFileName())
if(site.getFunctionName() == construct.name) {
return site.getFileName()
}
}
}

const EXCLUDE_DIRNAMES = ['src', 'lib', 'test', 'modules']

function _modulePrefix(filename) {
let dirname = path.dirname(filename)
let dirs = dirname.split(path.sep)
let isIndex = path.basename(filename) == 'index.js'
let result = []
let root
while (!root && dirs.length) {
let testFile = dirs.concat(['package.json']).join(path.sep)
if (fs.existsSync(testFile)) {
root = true
} else {
let p = dirs.pop()
if (!EXCLUDE_DIRNAMES.includes(p)) {
result.unshift(p)
}
}
}
if (isIndex) {
result.pop()
}
return result.join('/')
}

/**
Expand All @@ -23,6 +57,7 @@ function __dirName(constructorName) {
class NxusModule {

constructor(app) {
this._dirName = path.dirname(_filenameOf(this.constructor))
this.__name = this.constructor._moduleName()
this.__config_name = this.constructor._configName()
this.log = Logger(this.__name)
Expand All @@ -32,15 +67,18 @@ class NxusModule {
application.setUserConfig(this.__config_name, userConfig)
}

this._dirName = __dirName(this.constructor.name)

this.__proxy = application.get(this.__name)
this.__proxy.use(this)
}

get config() {
let _defaultConfig = this._defaultConfig() || {}
if(!this._config) this._config = Object.assign({}, deepExtend(_defaultConfig, application.config[this.__config_name]))
if (!this._config) {
this._config = Object.assign(
{},
deepExtend(_defaultConfig, application.config[this.__config_name])
)
}
return this._config
}

Expand All @@ -61,15 +99,23 @@ class NxusModule {
}

static _configName() {
return morph.toSnake(this.name)
return morph.toSnake(this._moduleName())
}

static _moduleName() {
return morph.toDashed(this.name)
static _moduleName(filename) {
if (filename === undefined) {
filename = _filenameOf(this)
}
let prefix = _modulePrefix(filename)
// this logic of ignoring class name for modules
// is in part to match src/PluginManager:_loadModulesFromDirectory
let name = prefix ? prefix + "/" + this.name : this.name
return morph.toDashed(name)
}

static getProxy() {
return application.get(this._moduleName())
// force to caller file, assuming getProxy is called in same file as class definition
return application.get(this._moduleName(stackTrace.get()[1].getFileName()))
}

deregister() {
Expand Down
16 changes: 9 additions & 7 deletions src/PluginManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,25 +89,27 @@ class PluginManager {
* @param {[type]} matches [description]
* @return {[type]} [description]
*/
_loadModulesFromDirectory(dir, isLocal, matches) {
_loadModulesFromDirectory(dir, isLocal, matches, prefix='') {

if (!fs.existsSync(dir)) return

var moduleDirs = fs.readdirSync(dir)

moduleDirs.forEach((name) => {
if(matches) name = multimatch([name], matches)[0]
if(!name || (name && name[0] == ".")) return
this.app.log.debug('Loading module', name, isLocal ? "(app)": "(dep)")
let modName = prefix+name
this.app.log.debug('Loading module', modName, isLocal ? "(app)": "(dep)")
let modulePath = path.resolve(path.join(dir, name))
try {
var pkg = require(modulePath)
pkg._pluginInfo = {name, modulePath, isLocal}
pkg._pluginInfo = {name: modName, modulePath, isLocal}
this.packages.push(pkg)
// this module prefix naming matches src/NxusModule:_moduleName we hope
let newPrefix = modName+"/"
// Recurse for module modules
this._loadModulesFromDirectory(path.join(dir, name, 'modules'), isLocal)
this._loadModulesFromDirectory(path.join(dir, name, 'lib', 'modules'), isLocal)
//if(fs.existsSync(dir + "/" + name + "/node_modules"))
//this._loadModulesFromDirectory(dir + "/" + name + "/node_modules", matches)
this._loadModulesFromDirectory(path.join(dir, name, 'modules'), isLocal, null, newPrefix)
this._loadModulesFromDirectory(path.join(dir, name, 'lib', 'modules'), isLocal, null, newPrefix)
} catch (e) {
// kludgy message text match to distinguish subsidiary modules from primary
if ((e.code === 'MODULE_NOT_FOUND') && e.message.includes(`'${modulePath}'`))
Expand Down
24 changes: 24 additions & 0 deletions test/lib/NxusModule.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@

import {NxusModule, application} from '../../lib/'

import OneModule from './modules/one'
import NestedSub from './modules/one/modules/sub'

class SubModule extends NxusModule {

_defaultConfig() {
Expand Down Expand Up @@ -40,6 +43,8 @@ describe("NxusModule", () => {

it("should set itself in app modules with the config name (dashed)", () => {
application._moduleProxies.should.have.property('sub-module')
// NestedSub
application._moduleProxies.should.have.property('one/nested-sub')
})

it("should set defaultConfig", () => {
Expand Down Expand Up @@ -78,4 +83,23 @@ describe("NxusModule", () => {
})
})

describe("_moduleName", () => {
it("should be the module name dashed", () => {
// SubModule isn't exported so not available
//SubModule._moduleName().should.equal('sub-module')
instance.__name.should.equal('sub-module')
})
it("should not duplicate module name when index module", () => {
OneModule._moduleName().should.equal('one')
})
it("should include nested directories and use module class name", () => {
NestedSub._moduleName().should.equal('one/nested-sub')
})
it("should include nested directories for arbitrary internal modules", () => {
let n = new NestedSub()
n.controller.__name.should.equal('one/sub/controllers/nested-controller')
application._moduleProxies.should.have.property('one/sub/controllers/nested-controller')
})
})

})
5 changes: 5 additions & 0 deletions test/lib/modules/one/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import {NxusModule} from '../../../../lib'

export default class One extends NxusModule {

}
5 changes: 5 additions & 0 deletions test/lib/modules/one/modules/sub/controllers/nested.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import {NxusModule} from '../../../../../../../lib'

export default class NestedController extends NxusModule {

}
14 changes: 14 additions & 0 deletions test/lib/modules/one/modules/sub/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import {NxusModule} from '../../../../../../lib'

import NestedController from './controllers/nested'

class NestedSub extends NxusModule {
constructor() {
super()
this.controller = new NestedController()
}

}

let nestedSub = NestedSub.getProxy()
export {NestedSub as default, nestedSub}