Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

edp

Package Overview
Dependencies
Maintainers
2
Versions
52
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

edp - npm Package Compare versions

Comparing version 0.7.0 to 1.0.0-beta.1

lib/cmd.js

430

lib/cli.js
/**
* @file 命令行功能模块
*
* @author errorrik[errorrik@gmail.com]
* leeight[liyubei@baidu.com]
*/
/**
* 获取具有命令行功能的模块列表
*
* @inner
* @param {string} baseDir 基础目录
* @return {Array}
*/
function getModules( baseDir ) {
var fs = require( 'fs' );
var path = require( 'path' );
var commandModules = [];
fs.readdirSync( baseDir ).forEach(
function ( file ) {
file = path.resolve( baseDir, file );
if ( fs.statSync( file ).isFile()
&& path.extname( file ).toLowerCase() === '.js'
) {
var module = require( file );
if ( module.cli ) {
commandModules.push( module );
}
}
}
);
var fs = require( 'fs' );
var path = require( 'path' );
return commandModules;
}
var edp = require( 'edp-core' );
/**
* 获取内建模块列表
*
* @return {Array}
*/
exports.getBuiltinModules = function () {
return getModules( __dirname );
};
// edp.pkg.install的时候需要切换到这个目录
process.env[ 'EDP_ROOT_PATH' ] = path.join( __dirname, '..' );
/**
* 获取用户定义模块列表
*
* @return {Array}
* Mac OS X下面有的同学是通过*.pkg安装的nodejs,这样子可能会有一些问题
* 例如:必须使用`sudo npm install <pkg>`的方式来安装,而无法使用`npm install <pkg>`
*/
exports.getExtensionModules = function () {
var modules = [];
require( './extension' ).get().forEach( function ( ext ) {
modules.push( getModules( ext ) );
} );
return Array.prototype.concat.apply( [], modules );
};
/**
* 显示默认命令行信息
*
* @inner
*/
function defaultInfo() {
var moduleNames = [];
function readName( mod ) {
moduleNames.push( mod.cli.command );
function checkEnv() {
if ( process.platform === 'win32' ) {
return;
}
function pad(msg, length) {
length = length || 16;
if (msg.length < length) {
return msg + new Array(length - msg.length).join(' ');
}
return msg;
var cmd = process.execPath;
if ( !fs.existsSync( cmd ) ) {
edp.log.warn( 'No such file %s', cmd );
return;
}
console.log( 'Usage: edp <command> [<args>] [<options>]\n' );
console.log( 'Builtin Commands:\n' );
exports.getBuiltinModules().forEach(
function( mod ) {
var cli = mod.cli;
var alias = cli.alias;
console.log( '%s %s',
pad( cli.command + (alias ? '(' + alias + ')' : '' ) ),
(cli.description || '').replace(/(。|\.)$/, '')
);
}
);
console.log();
moduleNames = [];
exports.getExtensionModules().forEach( readName );
if (moduleNames.length) {
console.log( 'User Commands:' );
console.log( moduleNames.join( ', ' ) );
console.log();
var stats = fs.lstatSync( cmd );
var uid = process.getuid();
if ( stats.uid !== uid ) {
edp.log.warn( 'Recommended using `homebrew`' +
' install `nodejs`, otherwise you may encounter' +
' some weird problems.' );
}
console.log( 'See "edp help <command>" for more information.' );
}
/**
* 命令节点类
*
* @inner
* @constructor
* @param {Object} mod 模块对象
*/
function CommandNode( mod ) {
this.children = {};
this.module = mod || null;
}
/**
* 获取子节点
*
* @inner
* @param {string} name 子节点名称
* @return {CommandNode}
*/
CommandNode.prototype.getChild = function ( name ) {
return this.children[ name ] || null;
};
/**
* 添加子节点
*
* @inner
* @param {Object} child 子节点模块
*/
CommandNode.prototype.addChild = function ( child ) {
var mod = child.module;
var cli = mod.cli;
if ( cli ) {
this.children[ cli.command ] = child;
if ( cli.alias ) {
this.children[ cli.alias ] = child;
}
if ( process.env.SUDO_UID ) {
edp.log.warn( 'Never using root to run `edp`, ' +
'otherwise you may corrupt your system.' );
}
};
/**
* 获取子节点的模块
*
* @inner
* @param {string} name 子节点名称
* @return {Object}
*/
CommandNode.prototype.getChildModule = function ( name ) {
var node = this.getChild( name );
if ( node ) {
return node.module;
}
return null;
};
/**
* 命令模块索引
*
* @inner
* @type {Object}
*/
var rootCommandNode = new CommandNode();
/**
* 扫瞄目录,用于建立命令模块索引
*
* @param {string} dir 目录路径名
* @param {string=} commandPath 命令路径
*/
function scanDir( dir, parentNode ) {
parentNode = parentNode || rootCommandNode;
var fs = require( 'fs' );
var path = require( 'path' );
fs.readdirSync( dir )
.sort(
function( file ) {
var fullPath = path.resolve( dir, file );
if ( fs.statSync( fullPath ).isDirectory() ) {
return 1;
}
return -1;
}
)
.forEach(
function ( file ) {
var fullPath = path.resolve( dir, file );
var stat = fs.statSync( fullPath );
var extName = path.extname( file );
var name = path.basename( file, extName );
if ( stat.isFile() && /^\.js$/i.test( extName ) ) {
try {
var module = require( fullPath );
var cli = module.cli;
if ( cli ) {
var commandNode = new CommandNode( module );
parentNode.addChild( commandNode );
}
}
catch ( ex ) {
// do nothing
}
}
else if ( stat.isDirectory() && name != 'node_modules' ) {
scanDir( fullPath, parentNode.getChild( name ) );
}
}
);
}
// create module index
scanDir( __dirname );
require( './extension' ).get().forEach( function ( ext ) {
scanDir( ext );
} );
/**
* 解析选项信息。选项信息格式示例:
*
* + `h`: -h
* + `help`: -h 或 --help
* + `output:`: -o xxx 或 --output xxx 或 --output=xxx
*
* @inner
* @param {string|Object} option 选项信息
* @return {Object}
*/
function parseOption( option ) {
if ( typeof option === 'string' ) {
if ( /^([-_a-zA-Z0-9]+)(:)?$/i.test( option ) ) {
var name = RegExp.$1;
option = {};
option.requireValue = !!RegExp.$2;
if ( name.length > 1 ) {
option.name = name.charAt( 0 );
option.fullname = name;
}
else {
option.name = name;
}
function leaveRootMode() {
if ( process.env.SUDO_UID ) {
try {
process.setuid( parseInt( process.env.SUDO_UID, 10 ) );
}
else {
throw new Error( 'Option string is invalid: ' + option );
catch( ex ) {
edp.log.warn( 'setuid failed, msg = %s', ex.toString() );
}
}
return option;
}
/**
* 纪录edp的运行历史
*
* @inner
*/
function saveCommandHistory() {
var fs = require('fs');
var historyFile = require('./edp').getConfig('.edp_history');
var commandLog = '[' + new Date() + ']: ' + process.argv.join(' ') + '\n';
fs.appendFile(historyFile, commandLog);
}
/**
* 获取模块
*
* @param {string} command 命令名称
* @return {Object}
*/
exports.getModule = function ( command ) {
return rootCommandNode.getChildModule( command );
};
/**
* 获取子模块列表
*
* @param {string} command 命令名称
* @return {Array}
*/
exports.getSubModules = function ( command ) {
var node = rootCommandNode.getChild( command );
var modules = [];
Object.keys( node.children ).forEach(
function ( key ) {
modules.push( node.getChildModule( key ) );
}
);
return modules;
};
/**
* 解析参数。作为命令行执行的入口

@@ -304,5 +65,6 @@ *

var help = require( './help' );
// 无参数时显示默认信息
if ( args.length === 0 ) {
defaultInfo();
help.defaultInfo();
return;

@@ -313,103 +75,75 @@ }

if ( args[ 0 ] === '--version' || args[ 0 ] === '-v' ) {
console.log( 'edp version ' + require('./edp').version );
help.dumpVersion();
return;
}
var skipChkEnv = false;
if ( args[ 0 ] === '--nobody' ) {
skipChkEnv = true;
// 这个参数貌似已经没用了
args.shift();
}
// 查找命令模块
var commandNode = rootCommandNode;
var commandName;
while ( args.length ) {
commandName = args[ 0 ];
if ( commandNode.getChild( commandName ) ) {
commandNode = commandNode.getChild( commandName );
args.shift();
}
else {
break;
}
}
var cmd = require( './cmd' );
var mainCommand = args[ 0 ];
var providerPackage = cmd.lookupPackage( mainCommand );
// 无命令模块时直接错误提示并退出
var commandModule = commandNode.module;
if ( !commandModule ) {
console.log( 'Error command' );
return;
}
// 解析参数
var commandArgs = [];
var commandOptions = {};
while ( args.length ) {
var seg = args.shift();
function done() {
// 确定default command或者sub command
var commandNode = cmd.getCommand( args );
var commandModule = commandNode.module;
if ( /^-(-)?([-_a-zA-Z0-9]+)(=([^=]+))?$/i.test( seg ) ) {
var optionInfo = {};
optionInfo[ RegExp.$1 ? 'fullname' : 'name' ] = RegExp.$2;
optionInfo.value = RegExp.$4;
if ( !commandModule || !commandModule.cli ) {
edp.log.error( 'Can not find the specified `%s\' ' +
'command module from `%s\'.',
mainCommand, providerPackage );
edp.log.error( 'DEBUG INFO: → %s',
require.resolve( providerPackage ) );
var moduleOptions = commandModule.cli.options || [];
for ( var i = 0; i < moduleOptions.length; i++ ) {
var opt = parseOption( moduleOptions[ i ] );
if ( opt.fullname === optionInfo.fullname
|| opt.name === optionInfo.name
) {
var value = true;
if ( opt.requireValue ) {
value = optionInfo.value || args.shift();
}
return;
}
commandOptions[ opt.name ] = value;
opt.fullname && (commandOptions[ opt.fullname ] = value);
break;
}
var x = cmd.getCommandArguments( commandModule.cli.options, args );
// 扫描剩余的args,确定commandArgs和commandOptions
if ( commandModule.cli
&& typeof commandModule.cli.main === 'function' ) {
// 运行命令
if ( x.opts.help === true ) {
help.displayCommandHelp( commandNode );
}
else {
// 运行命令之前,切换到正常的用户,否则可能导致创建的文件是属于root的
leaveRootMode();
commandModule.cli.main( x.args, x.opts );
}
}
else {
commandArgs.push( seg );
edp.log.error( 'Invalid edp module, ' +
'There is no cli.main entry point.' );
}
}
// 检查user.name和user.email的配置,确保这两个配置项存在
if ( !skipChkEnv && commandName !== 'config' ) {
var configModule = rootCommandNode.getChildModule( 'config' );
if( configModule && !checkEnv() ) {
return;
}
function fail( er ) {
edp.log.error( er.toString() );
}
// 记录运行的历史
saveCommandHistory();
checkEnv();
// 运行命令
commandModule.cli.main( commandArgs, commandOptions );
try {
require( providerPackage );
} catch ( ex ) {
edp.log.warn( ex.toString() );
// 检查当前运行的edp版本号
require( './util/check-update' )();
var dir = path.join( __dirname, '..', 'node_modules', providerPackage );
if ( !fs.existsSync( dir ) ) {
edp.pkg.install( providerPackage ).then( done, fail );
}
return;
}
done();
};
function checkEnv() {
var edpConfig = require( 'edp-config' );
var pass = edpConfig.get('user.name') && edpConfig.get('user.email');
var read = require('read');
if (!edpConfig.get('user.name')) {
console.log('For the first time, please enter your user name and email.');
read({prompt: 'user.name> '}, function(er, name){
edpConfig.set('user.name', name);
checkEnv();
});
} else if (!edpConfig.get('user.email')) {
read({prompt: 'user.email> '}, function(er, name){
edpConfig.set('user.email', name);
checkEnv();
});
}
return pass;
if ( module === require.main ) {
exports.parse( process.argv );
}
/**
* 命令行配置项
* @file 命令信息提示帮助模块
*
* @inner
* @type {Object}
* @author leeight[liyubei@baidu.com]
* errorrik[errorrik@gmail.com]
*/
var cli = {};
var edp = require( 'edp-core' );
var path = require( 'path' );
var fs = require( 'fs' );
var cmd = require( './cmd' );
function getPackages( pattern, dir ) {
dir = dir || path.join( __dirname, '..', 'node_modules' );
var pkgs = fs.readdirSync( dir )
.filter( function( item ){
return pattern.test( item );
});
return pkgs;
}
/**
* 命令名称
* 获取内置的命令列表
*
* @type {string}
* @param {string=} dir 需要查询的目录.
* @return {Array.<CommandNode>}
*/
cli.command = 'help';
exports.getBuiltinCommands = function( dir ) {
var pkgs = getPackages( /^edp-/, dir );
// 扫描每个node_modules/pkg,获取提供的commands.
var builtinCommands = [];
pkgs.forEach( function( pkg ) {
var pkgCommands = cmd.getPackageCommands( pkg );
for ( var key in pkgCommands ) {
builtinCommands.push( pkgCommands[ key ] );
}
});
return builtinCommands;
};
/**
* 命令描述信息
* 获取扩展的命令列表
*
* @type {string}
* @param {string=} dir 需要查询的目录.
* @return {Array.<CommandNode>}
*/
cli.description = '显示帮助信息';
exports.getUserCommands = function( dir ) {
var pkgs = getPackages( /^edpx-/, dir );
var userCommands = [];
pkgs.forEach( function( pkg ) {
var pkgCommands = cmd.getPackageCommands( pkg );
for ( var key in pkgCommands ) {
userCommands.push( pkgCommands[ key ] );
}
});
return userCommands;
};
/**
* 模块命令行运行入口
*
* @param {Array} args 命令运行参数
* 显示默认的帮助信息.
*/
cli.main = function ( args ) {
var fs = require( 'fs' );
var path = require( 'path' );
var msee = require( 'msee' );
var cliModule = require( './cli' );
var command = args[ 0 ] || 'help';
var module = cliModule.getModule( command );
exports.defaultInfo = function() {
var builtinCommands = exports.getBuiltinCommands();
if ( module ) {
var docPaths = require( './extension' ).get();
docPaths.unshift( __dirname );
for ( var i = 0; i < docPaths.length; i++ ) {
var docFile = path.resolve(
docPaths[ i ],
'../doc/cli',
module.cli.command + '.md'
// 输出builtinCommands和userCommands的内容
console.log( 'Builtin Commands:' );
displayHelpInfo( builtinCommands );
var userCommands = exports.getUserCommands();
if ( userCommands.length ) {
console.log( '\nUser Commands:' );
displayHelpInfo( userCommands );
}
};
/**
* 显示多命令的描述信息
*
* @param {Array.<CommandNode>} commands 命令集合
*/
function displayHelpInfo( commands ) {
commands.forEach( function( cmd ) {
exports.displayCommandDescription( cmd );
});
}
/**
* 显示命令的描述信息
*
* @param {CommandNode} node command节点的实例
* @param {number=} level 显示层级
*/
exports.displayCommandDescription = function ( node, level ) {
level = level || 0;
var prefixWhiteLetter = ' ';
if ( level > 0 ) {
prefixWhiteLetter += (new Array( level )).join( ' ' ) + ' |- ';
}
var sprintf = require( 'sprintf' ).sprintf;
if ( node ) {
var module = node.module;
var cli = module.cli;
var isProxy = ( module.proxy === true );
var isValid = ( cli && cli.main );
if ( isProxy || isValid ) {
console.log( prefixWhiteLetter
+ sprintf( '%-20s %s', edp.util.colorize( cli.command, 'success' ),
cli.description || '' )
);
if ( fs.existsSync( docFile ) ) {
var docText = msee.parseFile( docFile );
console.log( docText );
return;
var childLevel = level + 1;
for ( var key in node.children ) {
exports.displayCommandDescription(
node.children[ key ],
childLevel
);
}
}
}
};
var cliInfo = module.cli;
// 显示用法帮助信息
if ( cliInfo.usage ) {
console.log( 'Usage: ' + cliInfo.usage + '\n' );
}
/**
* 显示command的帮助信息.
*
* @param {CommandNode} node command节点的实例
*/
exports.displayCommandHelp = function( node ) {
var msee = require( 'msee' );
var docFile = node.fullPath.replace( /\.js$/, '.md' );
// 显示命令描述信息
if (cliInfo.description) {
console.log( cliInfo.description );
}
if ( fs.existsSync( docFile ) ) {
var docText = msee.parseFile( docFile );
console.log( docText );
}
else {
var cli = node.module.cli;
var docText = msee.parse(
cli.command + '\n' +
'---------\n' +
'### Description\n\n' +
cli.description || 'There is nothing left here.'
);
console.log( docText );
}
};
// 显示子命令帮助信息
var subModules = cliModule.getSubModules( command );
if ( subModules.length ) {
console.log( 'Sub Command:' );
var maxlength = 0;
subModules.forEach( function ( module ) {
maxlength = Math.max( maxlength, module.cli.command );
} );
subModules.forEach( function ( module ) {
var cliInfo = module.cli;
var command = cliInfo.command;
var gap = ' ';
for ( var i = command.length; i < maxlength; i++ ) {
gap += ' ';
}
/**
* 打印已经安装的各个模块的信息
*/
exports.dumpVersion = function() {
console.log( 'edp version ' + require('./edp').version );
console.log( command + gap + cliInfo.description );
} );
function getVersion( pkg ) {
var config = path.join( __dirname, '..', 'node_modules', pkg, 'package.json' );
if ( fs.existsSync( config ) ) {
config = JSON.parse( fs.readFileSync( config, 'utf-8' ) );
}
else {
config = { version: '0.0.0' };
}
return ' ' + edp.util.colorize( pkg, 'success' ) + ' (' + config.version + ')';
}
else {
console.log( command + ' is an error command!' );
var builtinPackages = getPackages( /^edp-/ ).map( getVersion );
var userPackages = getPackages( /^edpx-/ ).map( getVersion );
console.log( 'Builtin Commands:' );
console.log( builtinPackages.join( '\n' ) );
if ( userPackages.length ) {
console.log( '\nUser Commands:' );
console.log( userPackages.join( '\n' ) );
}
};
/**
* 命令行配置项
*
* @type {Object}
*/
exports.cli = cli;
/* vim: set ts=4 sw=4 sts=4 tw=100: */
{
"name": "edp",
"description": "Enterprise Develop Platform (dev)",
"version": "0.7.0",
"description": "Enterprise Develop Platform",
"version": "1.0.0-beta.1",
"contributors": [

@@ -20,29 +20,11 @@ { "name": "errorrik", "email": "errorrik@gmail.com" },

"scripts": {
"prepare": "npm ln edp-core edp-config edp-build edp-package edp-project edp-webserver edp-watch edp-htmlhint edp-test",
"test": "make -C test"
},
"dependencies": {
"edp-core": "~0.0.18",
"edp-config": "~0.4.4",
"edp-build": "~0.6.0",
"edp-package": "~0.4.11",
"edp-project": "~0.4.31",
"edp-webserver": "~0.5.0",
"edp-watch": "~0.1.2",
"edp-htmlhint": "~0.1.3",
"read": "~1.0",
"jshint": "~2.4.4",
"html-minifier": "~0.5.4",
"uglify-js": "~2.4.12",
"chalk": "~0.4.0",
"csslint": "~0.10.0",
"uglifycss": "~0.0.5",
"semver": "~2.2.1",
"npm-registry-client": "~0.4.4",
"npmconf": "~0.1.1",
"msee": "~0.1.0"
"edp-core": "~1.0.12",
"edp-config": "~1.0.2",
"msee": "~0.1.1",
"sprintf": "~0.1.3"
},
"devDependencies": {
"mocha": "~1.9",
"should": "~1.2"
},

@@ -52,3 +34,19 @@ "repository": "git://github.com/ecomfe/edp",

"edp": "./bin/edp-cli"
},
"edp": {
"extensions": {
"edp-core": [ "install", "link", "unlink" ],
"edp-config": [ "config" ],
"edp-build": [ "build" ],
"edp-package": [ "import", "search", "update" ],
"edp-project": [ ],
"edp-webserver": [ ],
"edp-watch": [ ],
"edp-lint": [ "htmlhint", "csslint", "jshint" ],
"edp-beautify": [ "beautify" ],
"edp-doctor": [ "doctor" ],
"edp-minify": [ "minify" ],
"edp-test": [ "test" ]
}
}
}

@@ -1,89 +0,27 @@

EDP [![NPM version](https://badge.fury.io/js/edp.png)](https://npmjs.org/package/edp) [![Dependencies Status](https://david-dm.org/ecomfe/edp.png)](https://david-dm.org/ecomfe/edp)
EDP
==========
EDP是一个企业级前端应用的开发平台,提供了常用的项目管理工具、包管理工具、调试工具、构建工具、代码生成工具、代码检测工具等一系列开发时的支持,并允许用户自定义自己的扩展。
[![Build Status](https://travis-ci.org/ecomfe/edp.png?branch=1.0.0-dev)](https://travis-ci.org/ecomfe/edp) [![Dependencies Status](https://david-dm.org/ecomfe/edp.png)](https://david-dm.org/ecomfe/edp)
EDP是一个基于Node.JS与NPM的企业级前端应用的开发平台,主要通过命令行的方式使用。EDP提供了前端应用开发时常用的一系列工具:
安装与更新
-------
+ 项目管理
+ 包管理
+ 调试
+ 构建
+ 代码生成
+ 代码检测
+ ......
edp已经发布到npm上,可以通过下面的npm命令安装。`-g`选项是必须选项,使用`-g`全局安装后,可以获得command line的`edp`命令。在Linux/Mac平台下,全局安装可能需要`sudo`。
EDP允许用户自定义自己的扩展。当默认提供的工具无法完全满足开发的需求时,用户可以开发自己的扩展命令。
$ [sudo] npm install -g edp
更加详细了解EDP,请阅读下面的文档:
如果想要升级当前edp的版本,请运行如下命令。在Linux/Mac平台下,升级可能需要`sudo`。
$ [sudo] npm update -g edp
准备
------
在使用之前,您需要先配置下个人的名字和邮箱。方法如下:(请替换掉`[]`部分)
$ edp config user.name [your_name]
"user.name" is setted.
$ edp config user.email [your_email@example.com]
"user.email" is setted.
使用
------
我们推荐通过命令行的方式使用edp。直接命令行下执行edp将显示可以调用的命令,包含内建命令和用户定制的命令。
$ edp
Usage: edp <command> [<args>] [<options>]
Builtin Commands:
addhtml 添加html文件
addjs 添加javascript文件
beautify 格式化JS、CSS和JSON文件
build 构建目录或项目
config 读取和设置edp用户配置
csslint 使用csslint检测当前目录下所有CSS文件
extension 扩展管理相关功能
help 显示帮助信息
htmlhint 使用htmllint检测当前目录下所有HTML文件
import 导入包
jshint 使用jshint检测当前目录下所有Javascript文件
minify 使用minify命令来让js、css、json文件获得最小化的输出
project 项目管理相关功能
search 查询现有的包
update 更新依赖包
webserver(ws) 用于开发时调试的WebServer
User Commands:
riaproject
See "edp help <command>" for more information.
`--version`将显示当前EDP的版本号。
$ edp --version
edp version 0.6.0
命令手册
------
在命令行下,我们可以通过`edp help <command>`查看命令的帮助信息。也可以通过下面的链接查看命令帮助:
- [addhtml](doc/cli/addhtml.md)
- [addjs](doc/cli/addjs.md)
- [beautify](doc/cli/beautify.md)
- [build](doc/cli/build.md)
- [config](doc/cli/config.md)
- [csslint](doc/cli/csslint.md)
- [extension](doc/cli/extension.md)
- [help](doc/cli/help.md)
- [import](doc/cli/import.md)
- [jshint](doc/cli/jshint.md)
- [minify](doc/cli/minify.md)
- [project](doc/cli/project.md)
- [search](doc/cli/search.md)
- [update](doc/cli/update.md)
- [watch](doc/cli/watch.md)
- [webserver](doc/cli/webserver.md)
- [安装](https://github.com/ecomfe/edp/wiki/Install)
- [Package的查找、导入与更新](https://github.com/ecomfe/edp/wiki/Package-Management)
- [项目管理](https://github.com/ecomfe/edp/wiki/Project-Management)
- [项目构建](https://github.com/ecomfe/edp/wiki/Build)
- [对前端代码进行静态检测](https://github.com/ecomfe/edp/wiki/Lint)
- [使用WebServer进行调试](https://github.com/ecomfe/edp/wiki/WebServer)
- [扩展自己的EDP命令](https://github.com/ecomfe/edp/wiki/Edp-Commands#user-commands)
- [诊断工具](https://github.com/ecomfe/edp/wiki/Doctor)

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc