Skip to content
This repository has been archived by the owner on Jul 2, 2020. It is now read-only.

Commit

Permalink
feat: add dev pack (#134)
Browse files Browse the repository at this point in the history
* fix: support dev pack

* fix: support dev pack
  • Loading branch information
echosoar committed Apr 17, 2020
1 parent b089adf commit cd08f54
Show file tree
Hide file tree
Showing 76 changed files with 1,946 additions and 25 deletions.
9 changes: 0 additions & 9 deletions docs/guide/yml.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,15 +61,6 @@ functions:
- GET
- POST


layers:
test:
path: npm:@ali/market-layer@latest

custom:
customDomain:
domainName: midway-fc.alibaba-inc.com

```


Expand Down
45 changes: 41 additions & 4 deletions packages/faas-cli-command-core/src/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export class CommandHookCore implements ICommandHooksCore {
private npmPlugin: string[] = [];
private loadNpm: any;
private preDebugTime: any;
private execId: number = Math.ceil(Math.random() * 1000);

store = new Map();

Expand Down Expand Up @@ -432,15 +433,51 @@ export class CommandHookCore implements ICommandHooksCore {
}

debug(...args) {
if (!this.options.options.V && !this.options.options.verbose) {
return;

const verbose = this.options.options.V || this.options.options.verbose;
if (!verbose) {
return;
}

const now = Date.now();
if (!this.preDebugTime) {
this.preDebugTime = now;
this.preDebugTime = now;
}
const { type, path, line } = this.getStackTrace();
let stack = '';
if (type) {
if (typeof verbose === 'string' && type !== verbose) {
return;
}
stack = `(${type}:${path}:${line})`;
}
const diffTime = Number((now - this.preDebugTime) / 1000).toFixed(2);
this.preDebugTime = now;
this.getLog().log('[Verbose]', `${diffTime}s`, ...args);
this.getLog().log('[Verbose]', this.execId, `+${diffTime}s`, ...args, stack);
}

getStackTrace() {
if (!Error.captureStackTrace) {
return {};
}
const obj: any = {};
Error.captureStackTrace(obj, this.getStackTrace);
if (!obj.stack || !obj.stack.split) {
return {};
}
const stackStr = obj.stack.split('\n');
if (!stackStr || !stackStr[2]) {
return {};
}
const matchReg = /(?:-plugin-|\/faas-cli-command-)(\w+)\/(.*?):(\d+):\d+/;
if (!matchReg.test(stackStr[2])) {
return {};
}
const matchResult = matchReg.exec(stackStr[2]);
return {
type: matchResult[1],
path: matchResult[2],
line: matchResult[3]
}
}
}
2 changes: 1 addition & 1 deletion packages/faas-cli-plugin-invoke/src/invoke.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export interface InvokeOptions {
sourceDir?: string; // 一体化目录结构下,函数的目录,比如 src/apis,这个影响到编译
clean?: boolean; // 清理调试目录
incremental?: boolean; // 增量编译
verbose?: boolean; // 输出更多信息
verbose?: boolean | string; // 输出更多信息
}

export async function invoke (options: InvokeOptions) {
Expand Down
2 changes: 1 addition & 1 deletion packages/faas-cli-plugin-invoke/test/apigw.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ describe('/test/apigw.test.ts', () => {
]
});
const resultBody = JSON.parse(result.body);
assert(resultBody.headers['Content-Type'] === 'text/json' && resultBody.method === 'POST' && resultBody.path === '/test' && resultBody.body.name === 'test' && resultBody.params.id === 'id');
assert(resultBody.headers['Content-Type'] === 'text/json' && resultBody.query.q === 'testq' && resultBody.method === 'POST' && resultBody.path === '/test' && resultBody.body.name === 'test' && resultBody.params.id === 'id');
});

it('tencent', async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export class HelloHttpService {
headers: this.ctx.headers,
method: this.ctx.method,
path: this.ctx.path,
query: this.ctx.query,
body: this.ctx.request.body,
params: this.ctx.params
}
Expand Down
5 changes: 4 additions & 1 deletion packages/faas-cli-plugin-invoke/test/http.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,16 @@ describe('/test/http.test.ts', () => {
headers: { 'Content-Type': 'text/json' },
method: 'POST',
path: '/test',
query: {
name: 'q',
},
body: {
name: 'test'
}
}
]
});
const resultBody = JSON.parse(result.body);
assert(resultBody.headers['Content-Type'] === 'text/json' && resultBody.method === 'POST' && resultBody.path === '/test' && resultBody.body.name === 'test');
assert(resultBody.headers['Content-Type'] === 'text/json' && resultBody.query.name === 'q' && resultBody.method === 'POST' && resultBody.path === '/test' && resultBody.body.name === 'test');
});
});
2 changes: 1 addition & 1 deletion packages/faas-cli-plugin-invoke/test/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ describe('/test/index.test.ts', () => {
data: [{name: 'params'}],
sourceDir: 'src/apis',
incremental: false,
verbose: true
verbose: 'invoke'
});
assert(result && result.body === 'hello http world');
await remove(join(__dirname, 'fixtures/ice-faas-ts-standard/.faas_debug_tmp'));
Expand Down
2 changes: 1 addition & 1 deletion packages/faas-cli-plugin-invoke/test/multi.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ describe('/test/multi.test.ts', () => {
headers: { 'Content-Type': 'text/json'},
method: 'GET',
path: '/test/xxx',
queries: {name: 123},
query: {name: 123},
body: {
name: 'test'
}
Expand Down
3 changes: 2 additions & 1 deletion packages/faas-cli-plugin-package/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -441,14 +441,15 @@ export class PackagePlugin extends BasePlugin {
if (!existsSync(pkgJson)) {
writeFileSync(pkgJson, '{}');
}
const register = this.options.register ? ` --registry=${this.options.register}` : '';
exec(
`${this.options.npm || 'npm'} install ${
options.npmList
? `${options.npmList.join(' ')}`
: options.production
? '--production'
: ''
}`,
}${register}`,
{ cwd: installDirectory },
err => {
if (err) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@ module.exports = {
{
locales: ['zh-cn'],
},
],
'@ali/ice-plugin-faas',
'@ali/ice-plugin-fake-page',
]
],
};
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"version": "1.0.0",
"main": "src/index.ts",
"dependencies": {
"@ali/midway-faas": "^2.4.14",
"@midwayjs/faas": "*",
"request": "^2.88.0",
"request-promise": "^4.2.5"
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {
func,
inject,
FaaSContext,
} from '@ali/midway-faas';
} from '@midwayjs/faas';

@provide()
@func('ping.handler')
Expand Down
38 changes: 38 additions & 0 deletions packages/faas-dev-pack/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Midway FaaS Dev

本模块用于 faas 代码的本地调试,用于接入现有的前端 DevServer,提供一个统一的中间件调用。


## Usage

```ts
import { useExpressDevPack } from '@midwayjs/faas-dev-pack';

// dev server 代码
app = express();

// 加载中间件
app.use(
useExpressDevPack({
functionDir: join(__dirname, './fixtures/ice-demo-repo'),
sourceDir: 'src/apis',
})
);
```

## API

暴露出两个中间件方法,用于上层集成。

- `useExpressDevPack(options: DevOptions)`
- `useKoaDevPack(options: DevOptions)`

DevOptions

```ts
export interface DevOptions {
functionDir: string; // 本地目录,默认 process.cwd()
sourceDir?: string; // 一体化调用是,需要知道当前的函数目录结构
}
```

3 changes: 3 additions & 0 deletions packages/faas-dev-pack/gateway.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"http": "@midwayjs/gateway-http"
}
43 changes: 43 additions & 0 deletions packages/faas-dev-pack/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
{
"name": "@midwayjs/faas-dev-pack",
"version": "0.2.76",
"main": "dist/index",
"typings": "dist/index.d.ts",
"dependencies": {
"@midwayjs/serverless-invoke": "^0.2.76",
"@midwayjs/gateway-core": "^0.2.76",
"@midwayjs/serverless-spec-builder": "^0.2.76",
"@midwayjs/gateway-http": "^0.2.76",
"body-parser": "^1.19.0",
"compose-middleware": "^5.0.1",
"koa-bodyparser": "^4.2.1",
"koa-compose": "^4.1.0"
},
"devDependencies": {
"@midwayjs/faas": "^0.2.76",
"@types/express": "^4.17.0",
"@types/koa": "^2.0.49",
"express": "^4.17.1",
"fs-extra": "^8.0.0",
"koa": "^2.11.0",
"midway-bin": "2",
"supertest": "^4.0.2"
},
"files": [
"dist",
"src",
"gateway.json"
],
"scripts": {
"build": "midway-bin build -c",
"test": "NODE_ENV=test midway-bin test --ts --full-trace",
"debug": "NODE_ENV=test midway-bin test --ts --full-trace --inspect-brk=9229",
"cov": "NODE_ENV=unittest midway-bin cov --ts",
"clean": "midway-bin clean",
"autod": "midway-bin autod"
},
"license": "MIT",
"publishConfig": {
"registry": "http://registry.npm.alibaba-inc.com"
}
}
50 changes: 50 additions & 0 deletions packages/faas-dev-pack/src/common.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { transform } from '@midwayjs/serverless-spec-builder';
import { join } from 'path';
import { invoke } from '@midwayjs/serverless-invoke';

const matchTrigger = (
config: any,
functionName: string,
triggerType: string
): boolean => {
// 拿到函数名,通用 mtop 的情况
if (config.functions?.[functionName]?.events?.[0]?.[triggerType]) {
return true;
}

return false;
};

export async function getGatewayFromConfig(
baseDir: string,
sourceDir: string,
req
) {
const config: any = transform(join(baseDir, 'f.yml'));
const gatewayType = config?.apiGateway?.type;
if (gatewayType) {
// mtop 自定义网关
return gatewayType;
} else {
const functionName = req.query['functionName'];
// 拿到函数名,通用 mtop 的情况
if (functionName && matchTrigger(config, functionName, 'mtop')) {
return 'mtop';
}

return 'http';
}
}

export function resolveModule(gatewayName: string) {
const gatewayJSON = require('../gateway.json');
if (gatewayJSON[gatewayName]) {
return require(gatewayJSON[gatewayName]);
} else {
throw new Error(`unsupport gateway type ${gatewayName}`);
}
}

export async function invokeFunction(options) {
return invoke(options);
}
64 changes: 64 additions & 0 deletions packages/faas-dev-pack/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { getGatewayFromConfig, resolveModule, invokeFunction } from './common';
import {
DevPackOptions,
CreateExpressGateway,
CreateKoaGateway,
} from '@midwayjs/gateway-core';
import { NextFunction, Request, Response } from 'express';
import { Context } from 'koa';
import * as koaBodyParser from 'koa-bodyparser';
import * as expressBodyParser from 'body-parser';
import * as compose from 'koa-compose';
import { compose as expressCompose } from 'compose-middleware';

export function useExpressDevPack(options: DevPackOptions) {
options.functionDir = options.functionDir || process.cwd();

return expressCompose([
expressBodyParser.urlencoded({ extended: false }),
expressBodyParser.json(),
async (req: Request, res: Response, next: NextFunction) => {
const gatewayName = await getGatewayFromConfig(
options.functionDir,
options.sourceDir,
req
);
if (!gatewayName) {
return next();
}
const createExpressGateway: CreateExpressGateway = resolveModule(
gatewayName
).createExpressGateway;
options.originGatewayName = gatewayName;
const gateway = createExpressGateway(options);
gateway.transform(req, res, next, invokeFunction);
},
]);
}

export function useKoaDevPack(options: DevPackOptions) {
options.functionDir = options.functionDir || process.cwd();

return compose([
koaBodyParser({
enableTypes: ['form', 'json'],
}),
async (ctx: Context, next: () => Promise<any>) => {
const gatewayName = await getGatewayFromConfig(
options.functionDir,
options.sourceDir,
ctx.request
);
if (!gatewayName) {
await next();
} else {
const createKoaGateway: CreateKoaGateway = resolveModule(gatewayName)
.createKoaGateway;

options.originGatewayName = gatewayName;
const gateway = createKoaGateway(options);
await gateway.transform(ctx, next, invokeFunction);
}
},
]);
}
7 changes: 7 additions & 0 deletions packages/faas-dev-pack/src/interface.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export interface InvokeParams {
functionName: string;
data?: any;
contextData?: string;
eventType?: string;
verbose?: boolean;
}

0 comments on commit cd08f54

Please sign in to comment.