work.suroh.tk/node_modules/module-definition/index.js

129 lines
2.7 KiB
JavaScript

'use strict';
const Walker = require('node-source-walk');
const types = require('ast-module-types');
const fs = require('fs');
/**
* Determines the type of the module from the supplied source code or AST
*
* @param {String|Object} source - The string content or AST of a file
* @return {String}
*/
function fromSource(source) {
if (typeof source === 'undefined') {
throw new Error('source not supplied');
}
const walker = new Walker();
let type = 'none';
let hasDefine = false;
let hasAMDTopLevelRequire = false;
let hasRequire = false;
let hasExports = false;
let hasES6Import = false;
let hasES6Export = false;
let hasDynamicImport = false;
// Walker accepts as AST to avoid reparsing
walker.walk(source, function(node) {
if (types.isDefine(node)) {
hasDefine = true;
}
if (types.isRequire(node)) {
hasRequire = true;
}
if (types.isExports(node)) {
hasExports = true;
}
if (types.isAMDDriverScriptRequire(node)) {
hasAMDTopLevelRequire = true;
}
if (types.isES6Import(node)) {
hasES6Import = true;
}
if (types.isES6Export(node)) {
hasES6Export = true;
}
if (hasES6Import || hasES6Export || hasDynamicImport) {
type = 'es6';
walker.stopWalking();
return;
}
if (hasDefine || hasAMDTopLevelRequire) {
type = 'amd';
walker.stopWalking();
return;
}
if (hasExports || (hasRequire && !hasDefine)) {
type = 'commonjs';
walker.stopWalking();
return;
}
});
return type;
}
/**
* Synchronously determine the module type for the contents of the passed filepath
*
* @param {String} file
* @param {Object} options
* @return {String}
*/
function sync(file, options) {
if (!file) {
throw new Error('filename missing');
}
var fileSystem = options ? (options.fileSystem || fs) : fs;
const data = fileSystem.readFileSync(file, 'utf8');
return fromSource(data.toString());
}
/**
* Asynchronously determines the module type for the contents of the given filepath
*
* @param {String} filepath
* @param {Function} cb - Executed with (err, type)
*/
module.exports = function(filepath, cb, options) {
if (!filepath) {
throw new Error('filename missing');
}
if (!cb) {
throw new Error('callback missing');
}
const opts = {encoding: 'utf8'};
var fileSystem = options ? (options.fileSystem || fs) : fs;
fileSystem.readFile(filepath, opts, function(err, data) {
if (err) {
return cb(err);
}
let type;
try {
type = fromSource(data);
} catch (error) {
return cb(error);
}
cb(null, type);
});
};
module.exports.sync = sync;
module.exports.fromSource = fromSource;