Repository: artusjs/core (ts)

Issue:
[RFC] startPipeline 缺少对 ctx.container 操作的时机
```ts
async initContext(input: Input): Promise<Context> {
  const ctx = new Context(input, new Output());
  ctx.container = new ExecutionContainer(ctx, this.app.getContainer())
  return ctx;
}

async startPipeline(input: Input = new Input()): Promise<Context> {
  const ctx = await this.initContext(input);
  await this.pipeline.run(ctx);
  return ctx;
}
```

以上是目前的 `startPipeline` 的实现。

这个过程其实把初始化 `Context` 以及执行流水线耦合到一起，这会导致无法在执行流水线之前往 `Conext` 提供的 `ExecutionContainer` 中设置 `EXECUTION` 实体（或者类）。

一种改动办法是：

```ts
async initContext(input: Input = new Input()): Promise<Context> {
  const ctx = new Context(input, new Output());
  ctx.container = new ExecutionContainer(ctx, this.app.getContainer())
  return ctx;
}

async startPipeline(ctx: Context): Promise<Context> {
  await this.pipeline.run(ctx);
  return ctx;
}
```

将流水线执行和 Context 初始化解耦，当然也可以使用 `??=` 兼容以前的无参数流水线逻辑：

```ts
async startPipeline(ctx: Context): Promise<Context> {
  ctx ??= await this.initContext();
  await this.pipeline.run(ctx);
  return ctx;
}
```

Pull request:
refactor: decoupling ctx & pipeline
close #113 

Patch:
diff --git a/src/trigger/index.ts b/src/trigger/index.ts
index fd4d26a..75ccadb 100644
--- a/src/trigger/index.ts
+++ b/src/trigger/index.ts
@@ -21,15 +21,13 @@ export default class Trigger implements TriggerType {
     this.pipeline.use(middleware);
   }
 
-  async initContext(input: Input, output: Output): Promise<Context> {
+  async initContext(input: Input = new Input(), output = new Output()): Promise<Context> {
     const ctx = new Context(input, output);
     ctx.container = new ExecutionContainer(ctx, this.app.getContainer());
     return ctx;
   }
 
-  async startPipeline(input: Input = new Input(), output = new Output()): Promise<Context> {
-    const ctx = await this.initContext(input, output);
+  async startPipeline(ctx: Context): Promise<void> {
     await this.pipeline.run(ctx);
-    return ctx;
   }
 }
diff --git a/src/types.ts b/src/types.ts
index 5ca1935..7e4760e 100644
--- a/src/types.ts
+++ b/src/types.ts
@@ -33,7 +33,7 @@ export interface Application {
 export interface TriggerType {
   use(...args): Promise<void>;
   initContext(...args): Promise<BaseContext>;
-  startPipeline(...args): Promise<BaseContext>;
+  startPipeline(...args): Promise<void>;
 }
 
 export * from './loader/types';


Test patch:
diff --git a/test/fixtures/app_koa_with_ts/src/app.ts b/test/fixtures/app_koa_with_ts/src/app.ts
index cb5806a..f9bcba6 100644
--- a/test/fixtures/app_koa_with_ts/src/app.ts
+++ b/test/fixtures/app_koa_with_ts/src/app.ts
@@ -41,7 +41,8 @@ export default class MyLifecycle implements ApplicationLifecycle {
       const input = new Input();
       const { req, res } = koaCtx;
       input.params = { koaCtx, req, res };
-      await this.app.trigger.startPipeline(input);
+      const ctx = await this.app.trigger.initContext(input);
+      await this.app.trigger.startPipeline(ctx);
     });
   }
 
diff --git a/test/fixtures/frameworks/layer/foo/foo1/src/lifecycle.ts b/test/fixtures/frameworks/layer/foo/foo1/src/lifecycle.ts
index bec5146..c910d37 100644
--- a/test/fixtures/frameworks/layer/foo/foo1/src/lifecycle.ts
+++ b/test/fixtures/frameworks/layer/foo/foo1/src/lifecycle.ts
@@ -23,7 +23,8 @@ export default class MyLifecycle implements ApplicationLifecycle {
       .createServer(async (req: http.IncomingMessage, res: http.ServerResponse) => {
         const input = new Input();
         input.params = { req, res, config, app: this.app };
-        await this.app.trigger.startPipeline(input);
+        const ctx = await this.app.trigger.initContext(input);
+        await this.app.trigger.startPipeline(ctx);
       })
       .listen(port);
   }
diff --git a/test/fixtures/frameworks/layer/foo/foo2/src/lifecycle.ts b/test/fixtures/frameworks/layer/foo/foo2/src/lifecycle.ts
index bec5146..c910d37 100644
--- a/test/fixtures/frameworks/layer/foo/foo2/src/lifecycle.ts
+++ b/test/fixtures/frameworks/layer/foo/foo2/src/lifecycle.ts
@@ -23,7 +23,8 @@ export default class MyLifecycle implements ApplicationLifecycle {
       .createServer(async (req: http.IncomingMessage, res: http.ServerResponse) => {
         const input = new Input();
         input.params = { req, res, config, app: this.app };
-        await this.app.trigger.startPipeline(input);
+        const ctx = await this.app.trigger.initContext(input);
+        await this.app.trigger.startPipeline(ctx);
       })
       .listen(port);
   }
diff --git a/test/fixtures/trigger/event/app.ts b/test/fixtures/trigger/event/app.ts
index c1fe442..7485773 100644
--- a/test/fixtures/trigger/event/app.ts
+++ b/test/fixtures/trigger/event/app.ts
@@ -43,14 +43,16 @@ export default class MyLifecycle implements ApplicationLifecycle {
       const input = new Input();
       input.params.type = 'e1';
       input.params.payload = payload;
-      await this.app.trigger.startPipeline(input);
+      const ctx = await this.app.trigger.initContext(input);
+      await this.app.trigger.startPipeline(ctx);
     });
 
     event.on('e2', async payload => {
       const input = new Input();
       input.params.type = 'e2';
       input.params.payload = payload;
-      await this.app.trigger.startPipeline(input);
+      const ctx = await this.app.trigger.initContext(input);
+      await this.app.trigger.startPipeline(ctx);
     });
   }
 
diff --git a/test/fixtures/trigger/http/app.ts b/test/fixtures/trigger/http/app.ts
index 18f28b0..65d3696 100644
--- a/test/fixtures/trigger/http/app.ts
+++ b/test/fixtures/trigger/http/app.ts
@@ -28,7 +28,8 @@ export default class MyLifecycle implements ApplicationLifecycle {
       .createServer(async (req: http.IncomingMessage, res: http.ServerResponse) => {
         const input = new Input();
         input.params = { req, res };
-        await this.app.trigger.startPipeline(input);
+        const ctx = await this.app.trigger.initContext(input);
+        await this.app.trigger.startPipeline(ctx);
       })
       .listen(3001)
   }
diff --git a/test/fixtures/trigger/timer/app.ts b/test/fixtures/trigger/timer/app.ts
index 22b3067..f21a937 100644
--- a/test/fixtures/trigger/timer/app.ts
+++ b/test/fixtures/trigger/timer/app.ts
@@ -47,13 +47,15 @@ export default class MyLifecycle implements ApplicationLifecycle {
     timers.push(setInterval(async () => {
       const input = new Input();
       input.params = { task: '1', execution };
-      await this.app.trigger.startPipeline(input);
+      const ctx = await this.app.trigger.initContext(input);
+      await this.app.trigger.startPipeline(ctx);
     }, 100));
 
     timers.push(setInterval(async () => {
       const input = new Input();
       input.params = { task: '2', execution };
-      await this.app.trigger.startPipeline(input);
+      const ctx = await this.app.trigger.initContext(input);
+      await this.app.trigger.startPipeline(ctx);
     }, 200));
   }