module.exports = function ( config ) { config = config || require( './config' ); serverConfig = config; var port = config.port || 80; var documentRoot = config.documentRoot; var injectResource = config.injectResource || config.injectRes; injectResource && injectResource( require( './resource' ) ); var connect = require( 'connect' ); var http = require( 'http' ); var app = connect(); // 采用connect连接各个中间件 app.use(require('./buffer')(serverConfig)) .use(require('./logger')(serverConfig)) .use(require('./route')(serverConfig)) // .use(connect.compress()) .use(require('./handler')(serverConfig)); var server = http.createServer(app).listen(port); var accessUrl = 'http://' + require( './util/ip' ) + ( port === 80 ? '' : ':' + port ); edp.log.info( 'EDP WebServer start, %s', accessUrl); edp.log.info( 'root = [%s], listen = [%s] ', documentRoot, port); return server; };
module.exports = exports = function processAndWriteCSS(processOptions, docRoot, pathname, content, context) { var filePath = path.join(docRoot, pathname); var css = filecache.check(filePath); if (css) { edp.log.info('Read From Cache: ' + pathname); context.header['content-type'] = mimeType.css; context.content = css; return; } context.stop(); var postcss = context.conf.postcss || require('postcss'); try { var plugins = processOptions.plugins || []; var options = processOptions.options || {}; postcss(plugins) .process(content, options) .then(function (result) { // inline内容会由插件生成,这里不太好处理 filecache.set(filePath, [], result.css); handleResult(result.css, context); }, function (error) { handleError(error, context); }); } catch (ex) { edp.log.error(ex.message); context.status = 500; context.start(); } };
/** * 调整 karma 的配置项以便兼容 * * @param {Object} config karma 配置对象 */ function comb(config) { edp.log.info('检测到使用 karma 配置文件,执行兼容处理...'); var files = []; config.files.forEach(function (file) { // 对象方式只取 pattern 属性值 var pattern = typeof file === 'string' ? file : file.pattern; // 只保留样式及 spec 的 js if (/(test\/.*spec|\.css|\.less|\.sass|\.styl)/i.test(pattern)) { files.push(pattern); } else { edp.log.warn('移除文件匹配规则:%s', JSON.stringify(file)); } }); config.files = files; var reporter = config.coverageReporter; if (reporter && reporter.type && reporter.type.indexOf('text') < 0) { reporter.type += '|text'; edp.log.info('增加控制台报告输出'); } edp.log.info('兼容处理完成'); }
/** * 格式化文件的函数 * * @param {string} sourceFile 输入文件名 * @param {Object} options 美化选项参数 * @return {string} 格式化后的字符串 */ function beautify(sourceFile, options) { options = options || {}; var extname = path.extname(sourceFile); var fileType = extname.slice(1); // 如果没有指定文件类型,那么就根据后缀名判断 options.fileType = options.fileType || fileType; var data = fs.readFileSync(sourceFile, 'utf-8'); var output = ''; try { switch(options.fileType) { case 'htm': case 'html': output = require('./beautify-html.js')(data, options); break; case 'json': output = JSON.stringify(JSON.parse(data), null, (options.indent || 4)); break; case 'js': output = require('./beautify-js.js')(data, options); break; case 'css': output = require('./beautify-css.js')(data, options); break; default: edp.log.warn('暂不支持该类型文件的格式化'); return; } } catch ( err ) { edp.log.error('文件解析错误: [' + sourceFile + ']'); return; } var outputFile = options.output; // 如果没有指定输出文件,那么自动生成<filename>.format.<fileType>文件 if (!outputFile) { var fileInfo = path.basename(sourceFile).split('.'); outputFile = fileInfo[0] + '.format' + extname; } // 将内容写入输出文件 fs.writeFileSync(outputFile, output, 'UTF-8'); edp.log.info('Success beautify file [' + sourceFile + '] to [' + outputFile + ']'); }
return function (context) { context.stop(); var req = context.request; var res = context.response; var filePath = path.join(context.conf.documentRoot, req.pathname); var stat = fs.statSync(filePath); var total = stat.size; var extname = path.extname(filePath).slice(1).toLowerCase(); var contentType = mimeType[extname] || mimeType.mpg; if (req.headers.range) { var range = req.headers.range; var parts = range.replace(/bytes=/, '').split('-'); var partialstart = parts[0]; var partialend = parts[1]; var start = parseInt(partialstart, 10); var end = partialend ? parseInt(partialend, 10) : total - 1; var chunksize = (end - start) + 1; edp.log.info('RANGE: ' + start + ' - ' + end + ' = ' + chunksize); var file = fs.createReadStream(filePath, { start: start, end: end }); res.writeHead(206, { 'Content-Range': 'bytes ' + start + '-' + end + '/' + total, 'Accept-Ranges': 'bytes', 'Content-Length': chunksize, 'Content-Type': contentType }); file.pipe(res); } else { edp.log.info('ALL: ' + total); res.writeHead(200, { 'Content-Length': total, 'Content-Type': contentType }); fs.createReadStream(filePath).pipe(res); } };
/** * 开启server */ function startWs() { log.info('start web server ...'); var conf = gerServerConfig(opts); require('edp-webserver').start(conf); // 如果是同构的项目需要再启动node if (isISO) { log.info('start node server ...'); spawn('nodemon', ['app.js', '-w', 'lib', '-w', 'app.js', '-w', 'config', '-e', 'js,tpl,json']); } }
params.fontType.split(',').forEach(function (type) { if (params[type]) { var filePath = path.resolve(fontPath, params.fontName + '.' + type); try { fs.writeFileSync(filePath, new Buffer(params[type], 'base64')); successType.push(type); edp.log.info('>> Sync font data to: ' + edp.chalk.yellow.bold(filePath)); } catch (exp) { edp.log.error('>> Error syncing font data to: ' + edp.chalk.yellow.bold(filePath) + '\n' + exp.message); } } });
function ( invalidRes ) { if ( invalidRes.type == 1 ) { edp.log.warn( '' + 'Only packages.manifest is allowed ' + 'in the dep directory.' ); } else if ( invalidRes.type == 2 ) { edp.log.warn( '→ No such file %s', invalidRes.path ); } else if ( invalidRes.type == 3 ) { edp.log.warn( '%s is invalid semver', invalidRes.path ); } }
export function getCandidates(args, patterns) { let candidates = []; args = args.filter(item => item !== '.'); if (!args.length) { candidates = glob.sync(patterns); } else { let i = -1; let len = args.length; while (++i < len) { let target = args[i]; if (!existsSync(target)) { log.warn('No such file or directory %s', target); continue; } let stat = statSync(target); if (stat.isDirectory()) { target = target.replace(/[\/|\\]+$/, ''); candidates.push.apply( candidates, glob.sync(target + '/' + patterns[0]) ); } /* istanbul ignore else */ else if (stat.isFile()) { candidates.push(target); } } } return candidates; }
module.exports = exports = function( args, opts ) { console.log(''); edp.log.info( 'Checking dep directory...' ); if ( fs.existsSync( 'dep' ) ) { fs.readdirSync( 'dep' ).forEach( checkDep ); } };
const report = errors => { let t12 = true; if (errors.length) { errors.forEach(error => { log.info(error.path); error.messages.sort((left, right) => { return left.line - right.line; }); error.messages.forEach(message => { const ruleName = message.ruleName || ''; let msg = '→ ' + (ruleName ? chalk.bold(ruleName) + ': ' : ''); // 全局性的错误可能没有位置信息 if (typeof message.line === 'number') { msg += ('line ' + message.line); if (typeof message.col === 'number') { msg += (', col ' + message.col); } msg += ': '; } msg += message.colorMessage || message.message; log.warn(msg); }); }); t12 = false; } if (t12) { log.info('Congratulations! Everything gone well, you are T12!'); } else { process.exit(1); } };
return function(name, callback) { var file = path.resolve(process.cwd(), name); var method = null; var args = name; if ( /\.(gz|tgz|zip)$/.test(name) && fs.existsSync(file)) { args = file; edp.log.info('GET file://%s', path.normalize(file)); method = require('../lib/import-from-file'); } else if (/^https?:\/\/(.+)/.test(name)) { method = require('../lib/import-from-remote'); } else { dependencies = dependencies || {}; // 如果调用的是 edp import er // 如果metadata里面配置了版本依赖,自动追加 if (args.indexOf('@') === -1 && dependencies[name]) { args += '@' + dependencies[name]; } method = require('../lib/import-from-registry'); } method(context, args, callback); };
module.exports = function (context, url, callback) { var depDir = context.getShadowDependenciesDir(); // http://git.baidu.com/bec/web/repository/archive.tar.gz?ref=1.0.0 var pathname = require('url').parse(url).pathname; var file = pathname.slice(pathname.lastIndexOf('/') + 1); var fullPath = path.resolve(depDir, file); var dirname = path.dirname(fullPath); if (!fs.existsSync(dirname)) { require('mkdirp').sync(dirname); } edp.log.info('GET %s', url); var stream = fs.createWriteStream(fullPath); http.get(url, function(res) { res.pipe(stream); }).on('error', callback); stream.on('close', done); function done() { require('./import-from-file')( context, fullPath, function(err, pkg) { if (fs.existsSync(fullPath)) { fs.unlinkSync(fullPath); } callback(err, pkg); } ); } };
exports.getCandidates = function(args, patterns) { var candidates = []; args = args.filter(function(item) { return item !== '.'; }); if (!args.length) { candidates = edp.glob.sync(patterns); } else { for (var i = 0; i < args.length; i++) { var target = args[i]; if (!fs.existsSync(target)) { edp.log.warn('No such file or directory %s', target); continue; } var stat = fs.statSync(target); if (stat.isDirectory()) { target = target.replace(/[\/|\\]+$/, ''); candidates.push.apply( candidates, edp.glob.sync(target + '/' + patterns[0])); } else if (stat.isFile()) { candidates.push(target); } } } return candidates; };
dirs.forEach(function (dir) { var dirPath = path.resolve(projectPath, dir); if (!fs.existsSync(dirPath)) { fs.mkdirSync(dirPath); } edp.log.info('>> `%s` create success.', dirPath); });
LessCompiler.prototype.process = function (file, processContext, callback) { var paths = []; paths.push(edp.path.dirname(file.fullPath)); paths.push(edp.path.join(process.cwd(), 'dep')); var options = u.extend({ relativeUrls: true, compress: true, paths: paths, filename: file.fullPath }, this.compileOptions); try { // this.less说明是从外部传递过来的,如果不存在,就用默认的 helper.compileLess(this.less || less, file.data, options) .then(function (css) { file.setData(css); file.outputPath = file.outputPath.replace(/\.less$/, '.css'); processContext.addFileLink(file.path, file.outputPath); }) .fail(function (err) { edp.log.warn('Compile less failed, file = [%s], msg = [%s]', file.path, err.toString()); file.outputPath = null; }) .fin(callback); } catch (ex) { edp.log.fatal('Compile less failed, file = [%s], msg = [%s]', file.path, ex.toString()); file.outputPath = null; callback(); } };
/** * 获取webserver 配置 * * @param {Object} opts cli配置 * @return {Object} */ function gerServerConfig(opts) { var port = opts.port; var docRoot = opts['document-root']; var conf = opts.config; conf = loadConf(conf); if (!conf) { log.error('Cannot load server config.'); return; } if (docRoot) { conf.documentRoot = path.resolve(process.cwd(), docRoot); } if (port) { conf.port = port; } // 注入扩展资源处理器 if (conf.injectResource) { var resPath = path.resolve(__dirname, '../../lib/server'); conf.injectResource(getExtraResource(resPath)); } return conf; }
cli.main = function (args, opts) { var stdin = process.stdin; var root = opts.root ? (util.getAbsPath(opts.root) || process.cwd()) : process.cwd(); opts.root = root; if (args[0]) { var rl = require('readline').createInterface({ input: process.stdin, output: process.stdout }); rl.question('>> Do you really want to init `' + args[0] + '` project in `' + root + '` ?(y/n)', function (a) { if ('Y' === a.trim().toUpperCase()) { rl.close(); initFiles(args, opts); } else { rl.close(); } } ); } else { edp.log.fatal('>> Please input a card_project_name.'); } };
StylusCompiler.prototype.process = function (file, processContext, callback) { var compileOptions = this.compileOptions || {}; var options = u.extend({ paths: [path.dirname(file.fullPath)], pathname: file.fullPath, use: compileOptions }, compileOptions); try { helper.compileStylus(this.stylus || stylus, file.data, options) .then(function (css) { file.setData(css); file.outputPath = file.outputPath.replace(/\.styl$/, '.css'); processContext.addFileLink(file.path, file.outputPath); }) .fail(function (err) { edp.log.fatal('Compile stylus failed, file = [%s], msg = [%s]', file.path, err.toString()); file.outputPath = null; }) .fin(callback); } catch (ex) { edp.log.fatal('Compile stylus failed, file = [%s], msg = [%s]', file.path, ex.toString()); file.outputPath = null; callback(); } };
req.on('error', function (err) { edp.log.error( chalk.yellow( 'PROXY' ) + ' %s to %s - - %s ms', chalk.green(request.url), chalk.green(targetHost + request.url), Date.now() - start ); context.status = 500; context.content = ''; context.start(); });
module.exports = exports = function compileAndWriteLess(compileOptions, docRoot, pathname, content, context) { context.stop(); var includePaths = context.conf.lessIncludePaths || []; if (fs.existsSync(path.join(docRoot, 'dep'))) { includePaths.push(path.join(docRoot, 'dep')); } var importPath = docRoot + path.dirname(pathname).replace(/\/$/, ''); var paths = [ importPath ]; includePaths.forEach( function(p) { paths.push(path.resolve(docRoot, p)); } ); var less = context.conf.less || require('less'); try { var options = require('../util/extend')( {}, { filename: docRoot + pathname, paths: paths, relativeUrls: true }, compileOptions ); if (less.version[0] >= 2) { // 2.0.0 and above less.render(content, options) .then(function (output) { handleResult(output.css, context); }, function (error) { handleError(error, context); }); } else { var parser = new(less.Parser)(options); parser.parse( content, function (error, tree) { if (error) { handleError(error, context); } else { handleResult(tree.toCSS(), context); } } ); } } catch (ex) { edp.log.error(ex.message); context.status = 500; context.start(); } };
server.on('error', function (e) { if (~'EADDRINUSE,EACCES'.indexOf(e.code)) { log.warn('Port %d not available, test next: %d', config.port, ++config.port); server.listen(config.port); } else { callback(e); } });
/** * require with try catch * * @param {string} mod modname * @return {any} mod */ function requireSafely(mod) { try { return require(mod); } catch (e) { log.error(e); return; } }
function leaveRootMode() { if ( process.env.SUDO_GID ) { try { process.setgid( parseInt( process.env.SUDO_GID, 10 ) ); } catch( ex ) { edp.log.warn( 'setgid failed, msg = %s', ex.toString() ); } } if ( process.env.SUDO_UID ) { try { process.setuid( parseInt( process.env.SUDO_UID, 10 ) ); } catch( ex ) { edp.log.warn( 'setuid failed, msg = %s', ex.toString() ); } } }
/** * 处理出错的情况 * * @param {Object} error less错误对象 * @param {Object} context 请求环境对象 */ function handleError(error, context) { context.status = 500; edp.log.error('' + error.message + ' Line: ' + error.line + ' Column: ' + error.column + ' Extract: ' + error.extract ); context.start(); }
npm.load( base.getNpmConfig(), function( er ) { if ( er ) { all.reject( er ); return; } edp.log.debug( 'Launch base.publish and base.gendocs job' ); Deferred.all( base.publish( pkgloc ), base.gendocs( pkgloc, body ) ) .done( function(){ all.resolve() } ) .fail( function( e ){ all.reject( e ) } ); });
cli.main = function(args, opts) { var project = require('edp-project'); var projectInfo = project.getInfo(); var projectRoot = projectInfo.dir; var conf = require(path.resolve(projectRoot, 'edp-build-config.js')); var buildOutputDir = path.resolve(projectRoot, conf.output); if (!fs.existsSync(buildOutputDir)) { edp.log.warn('没有`edp health build`后的目录,请先`build`后,再`release`'); return; } var dist = require( path.resolve(projectRoot, "release.conf") ).dist; if (!dist) { edp.log.error("请在`release.conf`中配置`dist`目标路径"); return; } dist = path.resolve(projectRoot, dist); var glob = require('glob'); glob('**/*', { cwd: buildOutputDir }, function(err, files) { files.forEach(function(file) { var srcFile = path.resolve(buildOutputDir, file); var distFile = path.resolve(dist, file); if (fs.statSync(srcFile).isFile()) { require('../../index').assertDir(distFile); fs.renameSync(srcFile, distFile); } }); edp.util.rmdir(buildOutputDir); }); }
unluckyPackages.forEach(function(item) { var pkgDir = path.join(bizDir, kDependencyDir, item.name, item.version); if (fs.existsSync(pkgDir)) { edp.log.info('Cleanup %s', path.join(kDependencyDir, item.name, item.version)); edp.util.rmdir(pkgDir); } var md5sum = path.join(bizDir, kDependencyDir, item.name, item.version + '.md5'); if (fs.existsSync(md5sum)) { fs.unlinkSync(md5sum); } });
function done() { edp.log.debug( 'Successfully downloaded %s', url ); // 解压zip var target = zipfile.replace( /\.zip$/, '' ); base.unzip( zipfile, target ); // 检查package.json是否存在,以及package.json中的版本跟tag的版本是否一致. var pkgloc = path.join( target, body.repository.name + '-' + body.ref ); var file = path.join( pkgloc, '', 'package.json' ); if ( !fs.existsSync( file ) ) { all.reject( new Error( 'No such file ' + path.join( target, 'package.json' ) ) ); return; } var pkg = JSON.parse( fs.readFileSync( file, 'utf-8' ) ); if ( !pkg ) { all.reject( new Error( 'Invalid package.json format' ) ); return; } if ( pkg.version !== body.ref ) { all.reject( new Error( 'Package version ' + pkg.version + ' mismatch with the tag version ' + body.ref ) ); return; } // 1. 上传到edp edp.log.debug( 'Launch npm.load job' ); npm.load( base.getNpmConfig(), function( er ) { if ( er ) { all.reject( er ); return; } edp.log.debug( 'Launch base.publish and base.gendocs job' ); Deferred.all( base.publish( pkgloc ), base.gendocs( pkgloc, body ) ) .done( function(){ all.resolve() } ) .fail( function( e ){ all.reject( e ) } ); }); }
/** * 更新文件的config * * @inner * @param {string} file 文件路径 * @param {string=} encoding 文件编码 */ function updateFileConfig(file, encoding) { encoding = encoding || 'UTF-8'; var fileContent = fs.readFileSync(file, encoding); var confInfo = require('./util/read-loader-config')(fileContent, file); // FIXME(user) 基本不会用到这个功能吧 var fileMetadata = {}; try { fileMetadata = require('./util/get-file-metadata')(file); } catch (ex) {} if (confInfo && fileMetadata.loaderAutoConfig !== false) { var projectData = exports.getConfig(file); if (!projectData) { return; } var configData = confInfo.data; // 两份儿数据merge起来,不应该直接用module.conf的内容覆盖 configData.paths = edp.util.extend(configData.paths || {}, projectData.paths); // 两份儿数据merge起来,不应该直接用module.conf的内容覆盖 // configData里面的优先级应该更高一些,如果有不一致的地方,给出warning信息 if (!configData.packages || configData.packages.length <= 0) { configData.packages = projectData.packages; } else { exports.mergePackages(configData.packages, projectData.packages, file); } // 如果文件的meta data里面设置过 preserveBaseUrl ,那么不需要修改baseUrl了 // 但是packages的路径还是需要修改的 if (configData.baseUrl && fileMetadata.preserveBaseUrl !== true) { // 如果以前存在baseUrl,才覆盖,否则不要给我追加baseUrl // esui的demo/loader/config.js里面没有baseUrl,如果给追加了,就不对了. if (configData.baseUrl !== projectData.baseUrl) { edp.log.info('Set baseUrl from [%s] to [%s] @ [%s]', configData.baseUrl, projectData.baseUrl, file); configData.baseUrl = projectData.baseUrl; } } fs.writeFileSync( file, require('./util/replace-loader-config')(configData, confInfo), encoding ); } }