Repository: aliyun/fun
Pull request #220 (2019-05-16 07:16:09)

Sunfeiyu/fun local invoke
#180 fun local invoke 不填写参数 默认调用 yml 中第一个


Patch:
diff --git a/README-en.md b/README-en.md
index 78db1d1..bef558e 100644
--- a/README-en.md
+++ b/README-en.md
@@ -27,6 +27,7 @@ We have prepared a series of tutorials to help you use the Fun tool more easily:
     - **Third-party templates**: Third-party templates that can be quickly initialized directly by `fun init [repo]`.
       - [puppeteer 模板项目](https://github.com/vangie/puppeteer-example/): Screenshot service based on puppeteer deployment on `Function Compute` service.
       - [函数计算 R 语言模板项目](https://github.com/vangie/rlang-example)：Template project for R language, can be used directly.
+      - [开发函数计算的正确姿势——支持 ES6 语法和 webpack 压缩](https://yq.aliyun.com/articles/701714)：Help quickly build a Function-Compute of nodejs project skeleton, support es6 code compiled into es5.
   - **Dependences installation**: Articles on how to use fun install to quickly install  dependencies.
     - [开发函数计算的正确姿势 —— 安装第三方依赖](https://yq.aliyun.com/articles/688062): introduce the basic usage of fun install.
     - [函数运行环境系统动态链接库版本太低？函数计算 fun 神助力分忧解难](https://yq.aliyun.com/articles/690856): Introduce how to use fun install to upgrade the system Dynamic-link libraries.
@@ -41,6 +42,8 @@ We have prepared a series of tutorials to help you use the Fun tool more easily:
     - [开发函数计算的正确姿势 —— Api 本地运行调试](https://yq.aliyun.com/articles/683685):  Demonstrates how to run and debug functions locally through the API.
   - **Deploy**: Articles on how to quickly deploy Function Compute.
     - [开发函数计算的正确姿势 —— 部署 API 网关](https://yq.aliyun.com/articles/689185): Introduce how to deploy the API Gateway + Function Compute application.
+    - [Guidelines for Function Compute Development —— OSS Trigger](https://yq.aliyun.com/articles/702667): Introduce how to deploy the OSS Trigger + Function Compute application.
+    - [开发函数计算的正确姿势 —— CDN 触发器](https://yq.aliyun.com/articles/700808)：Introduce how to deploy the OSS Trigger + Function Compute application.
   - **Fun in action**:
     - [Guidelines for Function Compute Development - Crawler](https://yq.aliyun.com/articles/686340): How to use the Fun tool to develop a Serverless application from scratch.
     - [Guidelines for Function Compute Development - Troubleshoot Timeout Issues](https://yq.aliyun.com/articles/686349): Demonstrates how to solve a series of bugs and introduces the tricks of debug.
diff --git a/README.md b/README.md
index 8902c54..4cb5fd6 100644
--- a/README.md
+++ b/README.md
@@ -27,6 +27,7 @@ Fun 作为一个命令行工具，内置了多个子命令，比如 config、loc
     - **第三方模板**: 第三方模板，可以直接通过 `fun init [repo]` 的方式快速初始化一个项目。
       - [puppeteer 模板项目](https://github.com/vangie/puppeteer-example/)：基于 puppeteer 的部署在函数计算上的截图服务。
       - [函数计算 R 语言模板项目](https://github.com/vangie/rlang-example)：R 语言的模板项目，可以直接使用。
+      - [开发函数计算的正确姿势——支持 ES6 语法和 webpack 压缩](https://yq.aliyun.com/articles/701714)：帮助快速搭建一个函数计算 nodejs 项目骨架，支持 es6 代码编译成 es5。
   - **依赖安装**：关于如何使用 fun install 快速安装函数依赖的文章。
     - [开发函数计算的正确姿势 —— 安装第三方依赖](https://yq.aliyun.com/articles/688062)：介绍了 fun install 的基本用法。
     - [函数运行环境系统动态链接库版本太低？函数计算 fun 神助力分忧解难](https://yq.aliyun.com/articles/690856)：介绍了如何利用 fun install，升级系统动态链接库。
diff --git a/bin/fun-local-invoke.js b/bin/fun-local-invoke.js
index 1feadcb..b795bcb 100644
--- a/bin/fun-local-invoke.js
+++ b/bin/fun-local-invoke.js
@@ -28,13 +28,7 @@ program
                              reading event from stdin`)
   .parse(process.argv);
 
-if (!program.args.length) {
-  console.error();
-  console.error("  error: missing required argument '%s'", '[service/]function');
-  program.help();
-}
-
-if (!program.args.length > 1) {
+if (program.args.length > 1) {
   console.error();
   console.error("  error: unexpected argument '%s'", program.args[1]);
   program.help();
diff --git a/lib/commands/local/invoke.js b/lib/commands/local/invoke.js
index f373e42..3bf6e92 100644
--- a/lib/commands/local/invoke.js
+++ b/lib/commands/local/invoke.js
@@ -12,7 +12,7 @@ const getVisitor = require('../../visitor').getVisitor;
 
 const { detectTplPath, getTpl } = require('../../tpl');
 
-const { red } = require('colors');
+const { red, yellow } = require('colors');
 
 function parseInvokeName(invokeName) {
   let serviceName = null;
@@ -37,6 +37,17 @@ function parseInvokeName(invokeName) {
 async function localInvoke(invokeName, tpl, debugPort, event, debugIde, tplPath) {
   debug(`invokeName: ${invokeName}`);
 
+  if (!invokeName) {
+
+    invokeName = definition.findFirstFunction(tpl);
+
+    if (!invokeName) {
+      throw new Error(red(`Missing function definition in template.yml`)); 
+    }
+    
+    console.log(`\nMissing invokeName argument, Fun will use the first function ${yellow(invokeName)} as invokeName\n`);
+  }
+
   const [parsedServiceName, parsedFunctionName] = parseInvokeName(invokeName);
 
   debug(`parse service name ${parsedServiceName}, functionName ${parsedFunctionName}`);
diff --git a/lib/definition.js b/lib/definition.js
index d6b42e9..31d3d31 100644
--- a/lib/definition.js
+++ b/lib/definition.js
@@ -184,8 +184,21 @@ function findHttpTriggersInTpl(tpl) {
   return httpTriggers;
 }
 
+function findFirstFunction(tpl) {
+  var firstInvokeName;
+  const resources = tpl.Resources;
+  for (let { serviceName, serviceRes } of findServices(resources)) {
+    for (let { functionName } of findFunctions(serviceRes)) {
+      firstInvokeName = serviceName + '/' + functionName;
+      break;
+    }
+  }
+  return firstInvokeName;
+}
+
 module.exports = {
   findFunctionInTpl, findHttpTriggersInTpl,
   findFunctionsInTpl, findNasConfigInService,
-  findHttpTriggersInFunction
+  findHttpTriggersInFunction, findServices,
+  findFunctions, findFirstFunction
 };
\ No newline at end of file


Test patch:
diff --git a/test/local/local-invoke.test.js b/test/local/local-invoke.test.js
index 2bcda77..68f8718 100644
--- a/test/local/local-invoke.test.js
+++ b/test/local/local-invoke.test.js
@@ -14,6 +14,12 @@ const fs = require('fs');
 const streams = require('memory-streams');
 
 const Inovke = require('../../lib/local/invoke');
+const definition = require('../../lib/definition');
+
+const util = require('util');
+const yaml = require('js-yaml');
+const readFile = util.promisify(fs.readFile);
+
 let LocalInvoke = require('../../lib/local/local-invoke');
 
 const { functionName, functionRes,
@@ -73,8 +79,15 @@ describe('test local invoke init', async () => {
       invoke.envs,
       invoke.dockerUser);
   });
-});
 
+  it('default first function when fun local invoke', async () => {
+    var tplPath = path.join('./examples', 'local', 'template.yml');
+    const tplContent = await readFile(tplPath, 'utf8');
+    const tpl = yaml.safeLoad(tplContent);
+    var firstFuntionName = definition.findFirstFunction(tpl);
+    expect(firstFuntionName).equal('localdemo/php72');
+  });
+});
 
 (hasDocker ? describe : describe.skip)('Integration::invoke', () => {