Provide more helpful errors when trying to require non-existent modules
This commit is contained in:
parent
9eb95113c2
commit
4a1c1b7b01
4 changed files with 131 additions and 115 deletions
29
src/main/js/lib/find.js
Normal file
29
src/main/js/lib/find.js
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
'use strict';
|
||||||
|
var File = java.io.File;
|
||||||
|
module.exports = function find(dir, filter) {
|
||||||
|
var result = [];
|
||||||
|
function recurse( dir, store ) {
|
||||||
|
var files,
|
||||||
|
len,
|
||||||
|
i,
|
||||||
|
file,
|
||||||
|
dirfile = new File( dir );
|
||||||
|
|
||||||
|
if ( typeof filter == 'undefined' ) {
|
||||||
|
files = dirfile.list();
|
||||||
|
} else {
|
||||||
|
files = dirfile.list(filter);
|
||||||
|
}
|
||||||
|
len = files.length; i = 0;
|
||||||
|
for (; i < len; i++){
|
||||||
|
file = new File( dir + '/' + files[i] );
|
||||||
|
if ( file.isDirectory() ) {
|
||||||
|
recurse( file.canonicalPath, store );
|
||||||
|
} else {
|
||||||
|
store.push( ('' + file.canonicalPath).replace(/\\\\/g,'/') );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
recurse( dir, result );
|
||||||
|
return result;
|
||||||
|
};
|
|
@ -1,14 +1,15 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
/*global persist,exports,config,__plugin,require*/
|
/*global persist,exports,config,__plugin,require*/
|
||||||
var File = java.io.File,
|
var File = java.io.File,
|
||||||
FileWriter = java.io.FileWriter,
|
FileWriter = java.io.FileWriter,
|
||||||
PrintWriter = java.io.PrintWriter;
|
PrintWriter = java.io.PrintWriter,
|
||||||
|
find = require('./find');
|
||||||
/*
|
/*
|
||||||
plugin management
|
plugin management
|
||||||
*/
|
*/
|
||||||
var _plugins = {};
|
var _plugins = {};
|
||||||
|
|
||||||
var _plugin = function(/* String */ moduleName, /* Object */ moduleObject, isPersistent ) {
|
function _plugin(/* String */ moduleName, /* Object */ moduleObject, isPersistent ) {
|
||||||
//
|
//
|
||||||
// don't load plugin more than once
|
// don't load plugin more than once
|
||||||
//
|
//
|
||||||
|
@ -26,67 +27,46 @@ var _plugin = function(/* String */ moduleName, /* Object */ moduleObject, isPer
|
||||||
moduleObject.store = persist( moduleName, moduleObject.store );
|
moduleObject.store = persist( moduleName, moduleObject.store );
|
||||||
}
|
}
|
||||||
return moduleObject;
|
return moduleObject;
|
||||||
};
|
}
|
||||||
|
|
||||||
exports.plugin = _plugin;
|
function _autoload( context, pluginDir, options ) {
|
||||||
|
|
||||||
exports.autoload = function( context, pluginDir, options ) {
|
|
||||||
var _canonize = function( file ) {
|
|
||||||
return '' + file.canonicalPath.replaceAll('\\\\','/');
|
|
||||||
};
|
|
||||||
/*
|
|
||||||
recursively walk the given directory and return a list of all .js files
|
|
||||||
*/
|
|
||||||
var _listSourceFiles = function( store, dir ) {
|
|
||||||
var files = dir.listFiles(),
|
|
||||||
file;
|
|
||||||
if ( !files ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for ( var i = 0; i < files.length; i++ ) {
|
|
||||||
file = files[i];
|
|
||||||
if ( file.isDirectory( ) ) {
|
|
||||||
_listSourceFiles( store, file );
|
|
||||||
}else{
|
|
||||||
if ( file.canonicalPath.endsWith( '.js' ) ) {
|
|
||||||
store.push( file );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
/*
|
/*
|
||||||
Reload all of the .js files in the given directory
|
Reload all of the .js files in the given directory
|
||||||
*/
|
*/
|
||||||
(function( pluginDir ) {
|
var sourceFiles = [],
|
||||||
var sourceFiles = [],
|
|
||||||
property,
|
property,
|
||||||
module,
|
module,
|
||||||
pluginPath;
|
pluginPath;
|
||||||
_listSourceFiles( sourceFiles, pluginDir );
|
sourceFiles = find(pluginDir);
|
||||||
|
|
||||||
var len = sourceFiles.length;
|
var len = sourceFiles.length;
|
||||||
if ( config && config.verbose ) {
|
if ( config && config.verbose ) {
|
||||||
console.info( len + ' scriptcraft plugins found in ' + pluginDir );
|
console.info( len + ' scriptcraft plugins found in ' + pluginDir );
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( var i = 0; i < len; i++ ) {
|
||||||
|
|
||||||
|
pluginPath = sourceFiles[i];
|
||||||
|
if (!pluginPath.match(/\.js$/)){
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
module = {};
|
||||||
|
|
||||||
for ( var i = 0; i < len; i++ ) {
|
try {
|
||||||
|
module = require( pluginPath , options);
|
||||||
pluginPath = _canonize( sourceFiles[i] );
|
for ( property in module ) {
|
||||||
module = {};
|
/*
|
||||||
|
all exports in plugins become members of context object
|
||||||
try {
|
*/
|
||||||
module = require( pluginPath , options);
|
context[property] = module[property];
|
||||||
for ( property in module ) {
|
|
||||||
/*
|
|
||||||
all exports in plugins become members of context object
|
|
||||||
*/
|
|
||||||
context[property] = module[property];
|
|
||||||
}
|
|
||||||
} catch ( e ) {
|
|
||||||
var msg = 'Plugin ' + pluginPath + ' ' + e ;
|
|
||||||
console.error( msg );
|
|
||||||
}
|
}
|
||||||
|
} catch ( e ) {
|
||||||
|
var msg = 'Plugin ' + pluginPath + ' ' + e ;
|
||||||
|
console.error( msg );
|
||||||
}
|
}
|
||||||
}(pluginDir));
|
}
|
||||||
};
|
|
||||||
|
}
|
||||||
|
exports.plugin = _plugin;
|
||||||
|
exports.autoload = _autoload;
|
||||||
|
|
||||||
|
|
|
@ -66,7 +66,19 @@ module specification, the '.js' suffix is optional.
|
||||||
FileReader = java.io.FileReader,
|
FileReader = java.io.FileReader,
|
||||||
BufferedReader = java.io.BufferedReader;
|
BufferedReader = java.io.BufferedReader;
|
||||||
|
|
||||||
var readModuleFromDirectory = function( dir ) {
|
function fileExists( file ) {
|
||||||
|
if ( file.isDirectory() ) {
|
||||||
|
return readModuleFromDirectory( file );
|
||||||
|
} else {
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function _canonize(file){
|
||||||
|
return "" + file.canonicalPath.replaceAll("\\\\","/");
|
||||||
|
}
|
||||||
|
|
||||||
|
function readModuleFromDirectory( dir ) {
|
||||||
|
|
||||||
// look for a package.json file
|
// look for a package.json file
|
||||||
var pkgJsonFile = new File( dir, './package.json' );
|
var pkgJsonFile = new File( dir, './package.json' );
|
||||||
|
@ -87,19 +99,8 @@ module specification, the '.js' suffix is optional.
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
var fileExists = function( file ) {
|
|
||||||
if ( file.isDirectory() ) {
|
|
||||||
return readModuleFromDirectory( file );
|
|
||||||
} else {
|
|
||||||
return file;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var _canonize = function(file){
|
|
||||||
return "" + file.canonicalPath.replaceAll("\\\\","/");
|
|
||||||
};
|
|
||||||
|
|
||||||
/**********************************************************************
|
/**********************************************************************
|
||||||
### module name resolution
|
### module name resolution
|
||||||
|
@ -135,7 +136,7 @@ When resolving module names to file paths, ScriptCraft uses the following rules.
|
||||||
3.2 if no package.json file exists then look for an index.js file in the directory
|
3.2 if no package.json file exists then look for an index.js file in the directory
|
||||||
|
|
||||||
***/
|
***/
|
||||||
var resolveModuleToFile = function ( moduleName, parentDir ) {
|
function resolveModuleToFile( moduleName, parentDir ) {
|
||||||
var file = new File(moduleName),
|
var file = new File(moduleName),
|
||||||
i = 0,
|
i = 0,
|
||||||
pathWithJSExt,
|
pathWithJSExt,
|
||||||
|
@ -179,13 +180,11 @@ When resolving module names to file paths, ScriptCraft uses the following rules.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
};
|
}
|
||||||
var _loadedModules = {};
|
|
||||||
var _format = java.lang.String.format;
|
|
||||||
/*
|
/*
|
||||||
require() function implementation
|
require() function implementation
|
||||||
*/
|
*/
|
||||||
var _require = function( parentFile, path, options ) {
|
function _require( parentFile, path, options ) {
|
||||||
var file,
|
var file,
|
||||||
canonizedFilename,
|
canonizedFilename,
|
||||||
moduleInfo,
|
moduleInfo,
|
||||||
|
@ -209,6 +208,29 @@ When resolving module names to file paths, ScriptCraft uses the following rules.
|
||||||
if (! ( (''+path).match( /^\./ ) ) ) {
|
if (! ( (''+path).match( /^\./ ) ) ) {
|
||||||
errMsg = errMsg + ' and not found in paths ' + JSON.stringify(modulePaths);
|
errMsg = errMsg + ' and not found in paths ' + JSON.stringify(modulePaths);
|
||||||
}
|
}
|
||||||
|
var find = _require(parentFile, 'find').exports;
|
||||||
|
var allJS = [];
|
||||||
|
for (var i = 0;i < modulePaths.length; i++){
|
||||||
|
var js = find( modulePaths[i] );
|
||||||
|
for (var j = 0;j < js.length; j++){
|
||||||
|
if (js[j].match(/\.js$/)){
|
||||||
|
allJS.push( js[j].replace(modulePaths[i],'') );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var pathL = path.toLowerCase();
|
||||||
|
var candidates = [];
|
||||||
|
for (i = 0;i < allJS.length;i++){
|
||||||
|
var filenameparts = allJS[i];
|
||||||
|
var candidate = filenameparts.replace(/\.js/,'') ;
|
||||||
|
var lastpart = candidate.toLowerCase();
|
||||||
|
if (pathL.indexOf(lastpart) > -1 || lastpart.indexOf(pathL) > -1){
|
||||||
|
candidates.push(candidate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (candidates.length > 0){
|
||||||
|
errMsg += '\nBut found module/s named: ' + candidates.join(',') + ' - is this what you meant?';
|
||||||
|
}
|
||||||
throw new Error(errMsg);
|
throw new Error(errMsg);
|
||||||
}
|
}
|
||||||
canonizedFilename = _canonize(file);
|
canonizedFilename = _canonize(file);
|
||||||
|
@ -285,14 +307,16 @@ When resolving module names to file paths, ScriptCraft uses the following rules.
|
||||||
}
|
}
|
||||||
moduleInfo.loaded = true;
|
moduleInfo.loaded = true;
|
||||||
return moduleInfo;
|
return moduleInfo;
|
||||||
};
|
}
|
||||||
|
|
||||||
var _requireClosure = function( parent ) {
|
function _requireClosure( parent ) {
|
||||||
return function( path, options ) {
|
return function requireBoundToParent( path, options ) {
|
||||||
var module = _require( parent, path , options);
|
var module = _require( parent, path , options);
|
||||||
return module.exports;
|
return module.exports;
|
||||||
};
|
};
|
||||||
};
|
}
|
||||||
|
var _loadedModules = {};
|
||||||
|
var _format = java.lang.String.format;
|
||||||
return _requireClosure( new java.io.File(rootDir) );
|
return _requireClosure( new java.io.File(rootDir) );
|
||||||
// last line deliberately has no semicolon!
|
// last line deliberately has no semicolon!
|
||||||
})
|
})
|
||||||
|
|
|
@ -143,7 +143,7 @@ This can be useful if you write a plugin that needs to store location data since
|
||||||
A JSON object in the above form.
|
A JSON object in the above form.
|
||||||
|
|
||||||
***/
|
***/
|
||||||
var _locationToJSON = function( location ) {
|
function _locationToJSON( location ) {
|
||||||
var yaw = __plugin.bukkit ? location.yaw : (__plugin.canary ? location.rotation : 0);
|
var yaw = __plugin.bukkit ? location.yaw : (__plugin.canary ? location.rotation : 0);
|
||||||
return {
|
return {
|
||||||
world: ''+location.world.name,
|
world: ''+location.world.name,
|
||||||
|
@ -175,7 +175,7 @@ lookupTable[key] = player.name;
|
||||||
```
|
```
|
||||||
|
|
||||||
***/
|
***/
|
||||||
exports.locationToString = function( location ) {
|
exports.locationToString = function locationToString( location ) {
|
||||||
return JSON.stringify( _locationToJSON( location ) );
|
return JSON.stringify( _locationToJSON( location ) );
|
||||||
};
|
};
|
||||||
exports.locationToJSON = _locationToJSON;
|
exports.locationToJSON = _locationToJSON;
|
||||||
|
@ -190,7 +190,7 @@ returned by locationToJSON() and reconstructs and returns a bukkit
|
||||||
Location object.
|
Location object.
|
||||||
|
|
||||||
***/
|
***/
|
||||||
exports.locationFromJSON = function( json ) {
|
exports.locationFromJSON = function locationFromJSON( json ) {
|
||||||
var world;
|
var world;
|
||||||
if ( json.constructor == Array ) {
|
if ( json.constructor == Array ) {
|
||||||
// for support of legacy format
|
// for support of legacy format
|
||||||
|
@ -210,7 +210,7 @@ exports.locationFromJSON = function( json ) {
|
||||||
|
|
||||||
exports.player = _player;
|
exports.player = _player;
|
||||||
|
|
||||||
exports.getPlayerObject = function( player ) {
|
exports.getPlayerObject = function getPlayerObject( player ) {
|
||||||
console.warn( 'utils.getPlayerObject() is deprecated. Use utils.player() instead.' );
|
console.warn( 'utils.getPlayerObject() is deprecated. Use utils.player() instead.' );
|
||||||
return _player(player);
|
return _player(player);
|
||||||
};
|
};
|
||||||
|
@ -281,7 +281,7 @@ if (targetPos){
|
||||||
```
|
```
|
||||||
|
|
||||||
***/
|
***/
|
||||||
exports.getMousePos = function( player ) {
|
exports.getMousePos = function getMousePos( player ) {
|
||||||
|
|
||||||
player = _player(player);
|
player = _player(player);
|
||||||
if ( !player ) {
|
if ( !player ) {
|
||||||
|
@ -366,20 +366,20 @@ utils.foreach (players, function( player ) {
|
||||||
Java-style collection. This is important because many objects in the
|
Java-style collection. This is important because many objects in the
|
||||||
CanaryMod and Bukkit APIs use Java-style collections.
|
CanaryMod and Bukkit APIs use Java-style collections.
|
||||||
***/
|
***/
|
||||||
var _foreach = function( array, callback, context, delay, onCompletion ) {
|
function _foreach( array, callback, context, delay, onCompletion ) {
|
||||||
if ( array instanceof java.util.Collection ) {
|
if ( array instanceof java.util.Collection ) {
|
||||||
array = array.toArray();
|
array = array.toArray();
|
||||||
}
|
}
|
||||||
var i = 0;
|
var i = 0;
|
||||||
var len = array.length;
|
var len = array.length;
|
||||||
|
function next() {
|
||||||
|
callback(array[i], i, context, array);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
function hasNext() {
|
||||||
|
return i < len;
|
||||||
|
}
|
||||||
if ( delay ) {
|
if ( delay ) {
|
||||||
var next = function( ) {
|
|
||||||
callback(array[i], i, context, array);
|
|
||||||
i++;
|
|
||||||
};
|
|
||||||
var hasNext = function( ) {
|
|
||||||
return i < len;
|
|
||||||
};
|
|
||||||
_nicely( next, hasNext, onCompletion, delay );
|
_nicely( next, hasNext, onCompletion, delay );
|
||||||
} else {
|
} else {
|
||||||
for ( ;i < len; i++ ) {
|
for ( ;i < len; i++ ) {
|
||||||
|
@ -412,7 +412,7 @@ function and the start of the next `next()` function.
|
||||||
See the source code to utils.foreach for an example of how utils.nicely is used.
|
See the source code to utils.foreach for an example of how utils.nicely is used.
|
||||||
|
|
||||||
***/
|
***/
|
||||||
var _nicely = function( next, hasNext, onDone, delay ) {
|
function _nicely( next, hasNext, onDone, delay ) {
|
||||||
if ( hasNext() ){
|
if ( hasNext() ){
|
||||||
next();
|
next();
|
||||||
setTimeout( function() {
|
setTimeout( function() {
|
||||||
|
@ -426,11 +426,12 @@ var _nicely = function( next, hasNext, onDone, delay ) {
|
||||||
};
|
};
|
||||||
exports.nicely = _nicely;
|
exports.nicely = _nicely;
|
||||||
|
|
||||||
exports.at = function( time24hr, callback, pWorlds, repeat ) {
|
function _at( time24hr, callback, pWorlds, repeat ) {
|
||||||
console.warn("utils.at() is deprecated, use require('at') instead");
|
console.warn("utils.at() is deprecated, use require('at') instead");
|
||||||
var at = require('at');
|
var at = require('at');
|
||||||
return at( time24hr, callback, pWorlds, repeat);
|
return at( time24hr, callback, pWorlds, repeat);
|
||||||
};
|
}
|
||||||
|
exports.at = _at;
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
### utils.time( world ) function
|
### utils.time( world ) function
|
||||||
|
|
||||||
|
@ -501,27 +502,9 @@ var jsFiles = utils.find('./', function(dir,name){
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
***/
|
***/
|
||||||
exports.find = function( dir , filter ) {
|
exports.find = function( path, filter){
|
||||||
var result = [];
|
console.warn("utils.find() is deprecated, use require('find') instead");
|
||||||
var recurse = function( dir, store ) {
|
return require('find')(path, filter);
|
||||||
var files, dirfile = new File( dir );
|
|
||||||
|
|
||||||
if ( typeof filter == 'undefined' ) {
|
|
||||||
files = dirfile.list();
|
|
||||||
} else {
|
|
||||||
files = dirfile.list(filter);
|
|
||||||
}
|
|
||||||
_foreach( files, function( file ) {
|
|
||||||
file = new File( dir + '/' + file );
|
|
||||||
if ( file.isDirectory() ) {
|
|
||||||
recurse( file.canonicalPath, store );
|
|
||||||
} else {
|
|
||||||
store.push( file.canonicalPath );
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
recurse( dir, result );
|
|
||||||
return result;
|
|
||||||
};
|
};
|
||||||
/************************************************************************
|
/************************************************************************
|
||||||
### utils.serverAddress() function
|
### utils.serverAddress() function
|
||||||
|
@ -534,7 +517,7 @@ var serverAddress = utils.serverAddress();
|
||||||
console.log(serverAddress);
|
console.log(serverAddress);
|
||||||
```
|
```
|
||||||
***/
|
***/
|
||||||
exports.serverAddress = function() {
|
exports.serverAddress = function serverAddress() {
|
||||||
var interfaces = java.net.NetworkInterface.getNetworkInterfaces();
|
var interfaces = java.net.NetworkInterface.getNetworkInterfaces();
|
||||||
var current,
|
var current,
|
||||||
addresses,
|
addresses,
|
||||||
|
@ -682,7 +665,7 @@ if (__plugin.canary){
|
||||||
function getPlayerNames(){
|
function getPlayerNames(){
|
||||||
return getPlayers().map(function(p){ return p.name; });
|
return getPlayers().map(function(p){ return p.name; });
|
||||||
}
|
}
|
||||||
exports.players = function(fn){
|
exports.players = function players(fn){
|
||||||
var result = getPlayers();
|
var result = getPlayers();
|
||||||
if (fn){
|
if (fn){
|
||||||
result.forEach(fn);
|
result.forEach(fn);
|
||||||
|
|
Reference in a new issue