Skip to content

Commit

Permalink
feat: add Initialization hook
Browse files Browse the repository at this point in the history
  • Loading branch information
hal-wang committed Apr 11, 2024
1 parent a3208a2 commit 93528a0
Show file tree
Hide file tree
Showing 20 changed files with 112 additions and 54 deletions.
1 change: 1 addition & 0 deletions packages/alifc/src/startup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ Startup.prototype.useAlifc = function () {
get: () => aliRes,
});

await this["initialize"]();
const halspRes = await this["invoke"](ctx);
aliRes.statusCode = halspRes.status;
Object.keys(halspRes.headers)
Expand Down
9 changes: 9 additions & 0 deletions packages/core/src/hook/hook.exec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
BeginingHook,
BooleanResultHook,
UnhandledMdHook,
InitializationHook,
} from "./hook.item";
import { HookManager } from "./hook.manager";

Expand Down Expand Up @@ -91,6 +92,14 @@ export async function execBeginingHooks(ctx: Context) {
}
}

export async function execInitializationHooks(startup: Startup, args: any[]) {
const hooks = HookManager.getGlobalHooks(startup, HookType.Initialization);
for (const hookItem of hooks) {
const hook = hookItem.hook as InitializationHook;
await hook(args);
}
}

export async function execHooks(
ctx: Context,
type: HookType,
Expand Down
7 changes: 5 additions & 2 deletions packages/core/src/hook/hook.item.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,21 @@ export type ContextHook = (
export type BeginingHook = (
ctx: Context,
) => boolean | Promise<boolean | void> | void;
export type InitializationHook = (args: any[]) => Promise<void> | void;

export type MdHook<T extends Middleware | MiddlewareConstructor = any> =
| MiddlewareResultHook<T>
| BooleanResultHook<T>
| ErrorMdHook<T>
| UnhandledMdHook<T>
| BeginingHook
| ContextHook;
| ContextHook
| InitializationHook;

export enum HookType {
Begining,
Initialization,
Context,
Begining,
BeforeInvoke,
AfterInvoke,
BeforeNext,
Expand Down
7 changes: 5 additions & 2 deletions packages/core/src/hook/hook.manager.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Context } from "../context";
import { HookItem, HookType } from "./hook.item";
import { Startup } from "../startup";
import { isUndefined } from "..";

const MIDDLEWARE_HOOK_BAG = "@halsp/core/middlewareHooksBag";
const hookMap = new WeakMap<Startup | Context, HookItem[]>();
Expand All @@ -10,7 +11,9 @@ export class HookManager {
if (!hookMap.has(startup)) {
hookMap.set(startup, []);
}
return hookMap.get(startup)!.filter((h) => !type || h.type == type);
return hookMap
.get(startup)!
.filter((h) => isUndefined(type) || h.type == type);
}

public static addGlobalHook(startup: Startup, hook: HookItem) {
Expand All @@ -25,7 +28,7 @@ export class HookManager {
const globalHooks = this.getGlobalHooks(ctx.startup, type);

const hooks = (ctx.get<HookItem[]>(MIDDLEWARE_HOOK_BAG) ?? []).filter(
(h) => !type || h.type == type,
(h) => isUndefined(type) || h.type == type,
);
return [...globalHooks, ...hooks];
}
Expand Down
19 changes: 17 additions & 2 deletions packages/core/src/startup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,11 @@ import { Register } from "./register";
import { ObjectConstructor } from "./utils";
import { HookManager } from "./hook/hook.manager";
import { HookType, MdHook } from "./hook";
import { execBeginingHooks, execContextHooks } from "./hook/hook.exec";
import {
execBeginingHooks,
execContextHooks,
execInitializationHooks,
} from "./hook/hook.exec";

export class Startup {
constructor() {
Expand Down Expand Up @@ -139,6 +143,9 @@ export class Startup {
mh: (...args: any[]) => Promise<Context | void>,
): this;

hook(type: HookType.Initialization, mh: (args: any[]) => void): this;
hook(type: HookType.Initialization, mh: (args: any[]) => Promise<void>): this;

hook<T extends Middleware = Middleware>(
mh: (ctx: Context, middleware: T) => void,
isGlobal?: true,
Expand Down Expand Up @@ -167,7 +174,11 @@ export class Startup {
isGlobal = arg3 as true | undefined;
}

if (type == HookType.Context || type == HookType.Begining) {
if (
type == HookType.Context ||
type == HookType.Begining ||
type == HookType.Initialization
) {
isGlobal = true;
}

Expand Down Expand Up @@ -202,6 +213,10 @@ export class Startup {
return ctx.res;
}

protected async initialize(...args: any[]) {
await execInitializationHooks(this, args);
}

logger: ILogger = new BaseLogger();

public extend<T extends keyof this>(name: T, fn: (typeof this)[T]): this {
Expand Down
14 changes: 14 additions & 0 deletions packages/core/test/hook/initialization.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { HookType, Startup } from "../../src";
import "../test-startup";

describe("initialization hook", () => {
it("shoud initializa before invoke", async () => {
let testArgs: any;
await new Startup()
.hook(HookType.Initialization, (args) => {
testArgs = args;
})
.run(1, 2, 3);
expect(testArgs).toEqual([1, 2, 3]);
});
});
1 change: 1 addition & 0 deletions packages/core/test/test-startup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,6 @@ declare module "../src" {
}

Startup.prototype.run = async function (...args: any[]) {
await this["initialize"](...args);
return await this["invoke"](...args);
};
6 changes: 6 additions & 0 deletions packages/koa/src/halsp.middleware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export function koaHalsp(config: (startup: Startup) => void) {
await koaNext();
await koaResToHalspRes(koaCtx, halspCtx.res);
});
let initialize = false;

return async function (koaCtx: KoaContext, koaNext: Next) {
const ctx = new Context();
Expand All @@ -36,6 +37,11 @@ export function koaHalsp(config: (startup: Startup) => void) {
ctx.set(KOA_NEXT, koaNext);

await koaResToHalspRes(koaCtx, ctx.res);

if (!initialize) {
initialize = true;
await startup["initialize"]();
}
const res = await startup["invoke"](ctx);
await halspResToKoaRes(res, koaCtx);
};
Expand Down
1 change: 1 addition & 0 deletions packages/lambda/src/startup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ Startup.prototype.useLambda = function () {
event.path || event.rowPath || event.requestPath || event.url || "",
);

await this["initialize"]();
await this["invoke"](ctx);
return await getStruct(ctx);
}).useHttp();
Expand Down
2 changes: 1 addition & 1 deletion packages/micro-grpc/src/server/startup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ function initStartup(this: Startup, options: MicroGrpcOptions) {
let server: grpc.Server | undefined = undefined;
this.extend("listen", async () => {
await close.call(this, server);
await this["initialize"]();
server = new grpc.Server();

const opt: MicroGrpcOptions = { ...options };
Expand Down Expand Up @@ -62,7 +63,6 @@ function initStartup(this: Startup, options: MicroGrpcOptions) {
);
});

server.start();
this.logger.info(`Server started, listening port: ${bindPort}`);

return server;
Expand Down
4 changes: 2 additions & 2 deletions packages/micro-grpc/test/client/error.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ describe("emit error", () => {
const server = new grpc.Server();
await new Promise<number>((resolve, reject) => {
server.bindAsync(
"0.0.0.0:5031",
"0.0.0.0:5033",
grpc.ServerCredentials.createInsecure(),
(err, port) => {
if (err) {
Expand All @@ -164,7 +164,7 @@ describe("emit error", () => {

const client = new MicroGrpcClient({
protoFiles: "./test/protos/test.proto",
port: 5031,
port: 5033,
});
client.logger = console as any;
await client["connect"]();
Expand Down
2 changes: 1 addition & 1 deletion packages/micro-grpc/test/client/service.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ describe("service", () => {

const testService = client.getService<TestService>(
"test",
"TestService",
"TestServicE",
) as TestService;
const result = await testService.testMethod({
reqMessage: "abc",
Expand Down
1 change: 1 addition & 0 deletions packages/micro-mqtt/src/server/startup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ function initStartup(this: Startup, options: MicroMqttOptions = {}) {

this.extend("listen", async () => {
await closeInner();
await this["initialize"]();

const opt: MicroMqttOptions = { ...options };
if (!("servers" in options) && !("port" in options)) {
Expand Down
1 change: 1 addition & 0 deletions packages/micro-nats/src/server/startup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ function initStartup(this: Startup, options: MicroNatsOptions = {}) {
let connection: nats.NatsConnection | undefined = undefined;
this.extend("listen", async () => {
await close.call(this, connection);
await this["initialize"]();

const opt: MicroNatsOptions = { ...options };
if (!("servers" in options) && !("port" in options)) {
Expand Down
1 change: 1 addition & 0 deletions packages/micro-redis/src/server/startup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ function initStartup(this: Startup, options?: MicroRedisOptions) {
let pub: redis.RedisClientType | undefined = undefined;
this.extend("listen", async () => {
await close.call(this, sub, pub);
await this["initialize"]();

const opt: MicroRedisOptions = { ...options };
if (!("url" in opt)) {
Expand Down
1 change: 1 addition & 0 deletions packages/micro-tcp/src/server/startup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ function initStartup(this: Startup, options?: MicroTcpOptions) {

this.extend("listen", async () => {
await closeServer(server);
await this["initialize"]();

if (options?.handle) {
await new Promise<void>((resolve) => {
Expand Down
1 change: 1 addition & 0 deletions packages/native/src/startup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ function initStartup(this: Startup, options?: NativeOptions) {
() => resolve(),
);
});
await this["initialize"]();
return server;
});

Expand Down
86 changes: 42 additions & 44 deletions packages/router/src/startup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,60 +17,58 @@ import * as fs from "fs";
import { BlankMiddleware } from "./blank.middleware";

export function initRouterMap(this: Startup, options?: RouterOptions) {
return this.hook(HookType.Begining, async (ctx) => {
if (this.routerMap) return;
const mapOptions = readMap();
const opts: RouterOptionsMerged = {
map: mapOptions?.map ?? [],
dir: getDir(mapOptions?.dir),
prefix: options?.prefix,
decorators: options?.decorators,
};

const mapOptions = readMap();
const opts: RouterOptionsMerged = {
map: mapOptions?.map ?? [],
dir: getDir(mapOptions?.dir),
prefix: options?.prefix,
decorators: options?.decorators,
};
ctx.set(ROUTER_INITED_OPTIONS_BAG, opts);

await registerMap(ctx, opts);
}).add(async (ctx) => {
if (!ctx.actionMetadata) {
return BlankMiddleware;
} else {
return await ctx.actionMetadata.getAction();
}
});
}
return this.hook(HookType.Initialization, async () => {
const routerMap = await new MapParser(opts).getMap();
Object.defineProperty(this, "routerMap", {
configurable: true,
enumerable: false,
get: () => {
return routerMap;
},
});

async function registerMap(ctx: Context, opts: RouterOptionsMerged) {
const routerMap = await new MapParser(opts).getMap();
Object.defineProperty(ctx.startup, "routerMap", {
configurable: true,
enumerable: false,
get: () => {
return routerMap;
},
});
Object.defineProperty(ctx, "routerMap", {
configurable: true,
enumerable: false,
get: () => {
return routerMap;
},
});
routerMap.forEach((item) => {
const url = (opts?.prefix ?? "") + item.url;
const methods = item.methods.join(",");
const pattern = methods ? methods + "//" + url : url;

routerMap.forEach((item) => {
const url = (opts?.prefix ?? "") + item.url;
const methods = item.methods.join(",");
const pattern = methods ? methods + "//" + url : url;
this.register(pattern, (ctx: Context) => {
Object.defineProperty(ctx, "actionMetadata", {
configurable: true,
enumerable: false,
get: () => {
return item;
},
});
});
});
})
.hook(HookType.Begining, async (ctx) => {
ctx.set(ROUTER_INITED_OPTIONS_BAG, opts);

ctx.startup.register(pattern, (ctx: Context) => {
Object.defineProperty(ctx, "actionMetadata", {
Object.defineProperty(ctx, "routerMap", {
configurable: true,
enumerable: false,
get: () => {
return item;
return this.routerMap;
},
});
})
.add(async (ctx) => {
if (!ctx.actionMetadata) {
return BlankMiddleware;
} else {
return await ctx.actionMetadata.getAction();
}
});
});
}

function readMap(): RouterDistOptions | undefined {
Expand Down
1 change: 1 addition & 0 deletions packages/router/test/modules/def/error.get.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
throw new Error();
1 change: 1 addition & 0 deletions packages/testing/src/startup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ const ctxMap = new WeakMap<Startup, Context | Request>();
Startup.prototype.test = async function (): Promise<Response> {
process.env.NODE_ENV = "test";

await this["initialize"]();
const res = await this["invoke"](ctxMap.get(this) ?? new Context());

const err = getError(res.ctx);
Expand Down

0 comments on commit 93528a0

Please sign in to comment.