From 626965cdd6c055a6105917e9275981586f44a757 Mon Sep 17 00:00:00 2001 From: richardo2016 Date: Sat, 27 Apr 2019 16:49:05 +0800 Subject: [PATCH] support Hooks --- @types/app.d.ts | 6 +++ demo/test/index.js | 1 + demo/test/integration/hooks.js | 94 ++++++++++++++++++++++++++++++++++ lib.ts | 2 +- src/app.ts | 9 +++- src/http/hook.ts | 3 ++ src/http/index.ts | 74 ++++++++++++++------------ 7 files changed, 152 insertions(+), 37 deletions(-) create mode 100644 demo/test/integration/hooks.js create mode 100644 src/http/hook.ts diff --git a/@types/app.d.ts b/@types/app.d.ts index 1ef2b6c..1fafad5 100644 --- a/@types/app.d.ts +++ b/@types/app.d.ts @@ -289,6 +289,12 @@ declare namespace FibApp { viewPathPrefix?: string graphQLPathPrefix?: string batchPathPrefix?: string + + hooks?: Hooks + } + + interface Hooks { + beforeSetupRoute?: FxOrmHook.HookActionCallback } interface GetTestRoutingOptions { diff --git a/demo/test/index.js b/demo/test/index.js index 48a97a6..725caca 100644 --- a/demo/test/index.js +++ b/demo/test/index.js @@ -38,6 +38,7 @@ describe('fib-app', function () { require('../defs/hooks/spec') require('./integration/orm-pool-reload') + require('./integration/hooks') } if (!process.env.FIBAPP_NO_MODEL_SPEC) { diff --git a/demo/test/integration/hooks.js b/demo/test/integration/hooks.js new file mode 100644 index 0000000..992df2e --- /dev/null +++ b/demo/test/integration/hooks.js @@ -0,0 +1,94 @@ +const test = require('test'); +test.setup(); + +describe('Hooks', () => { + var tappInfo + function setup(opts) { + tappInfo = require('../support/spec_helper').getRandomSqliteBasedApp({ + hooks: opts.hooks + }, {}); + } + + var triggered = { + beforeSetupRoute: false + }; + + afterEach(() => { + Object.keys(triggered).forEach(k => triggered[k] = false) + }) + + const apis = [ + 'get', + 'post', + 'put', + 'del', + 'eget', + 'epost', + 'eput', + 'edel', + 'functionHandler' + ] + + function assert_apis_not_exist(app) { + apis.forEach(k => { + assert.notExist(app.api[k]) + }) + } + + function assert_apis_exist(app) { + apis.forEach(k => { + assert.isFunction(app.api[k]) + }) + + assert.isFunction(app.filterRequest) + } + + it('[beforeSetupRoute] triggered after app instanced', () => { + setup({ + hooks: { + beforeSetupRoute () { + assert.isFalse(triggered.beforeSetupRoute) + triggered.beforeSetupRoute = true; + + assert.exist(this) + assert.isObject(this) + + assert.isObject(this.api) + assert_apis_exist(this) + } + } + }) + + assert.isTrue(triggered.beforeSetupRoute); + assert_apis_exist(tappInfo.app); + }); + + it('[beforeSetupRoute] triggered after app instanced - next', () => { + setup({ + hooks: { + beforeSetupRoute (next) { + setTimeout(() => { + assert.isFalse(triggered.beforeSetupRoute) + triggered.beforeSetupRoute = true; + + assert.exist(this) + assert.isObject(this) + + assert.isObject(this.api) + assert_apis_exist(this) + + next() + }, 100) + } + } + }) + + assert.isTrue(triggered.beforeSetupRoute); + assert_apis_exist(tappInfo.app); + }); +}) + +if (require.main === module) { + test.run(console.DEBUG); + process.exit(); +} diff --git a/lib.ts b/lib.ts index 504acc3..194c0de 100644 --- a/lib.ts +++ b/lib.ts @@ -1,6 +1,6 @@ import util = require('util') -if ((util.buildInfo() as any).fibjs !== '0.25.0') { +if ((util.buildInfo()).fibjs !== '0.25.0') { module.exports = require('./src') } else { module.exports = require('./lib/index.js') diff --git a/src/app.ts b/src/app.ts index f8d0e92..9a90422 100644 --- a/src/app.ts +++ b/src/app.ts @@ -1,4 +1,6 @@ import * as mq from 'mq'; +import * as util from 'util'; + import setupApis = require('./http'); import setupTest = require('./testkits') @@ -31,8 +33,9 @@ class App extends mq.Routing implements FibApp.FibAppClass { constructor(connStr: string) { super(); - const dbSetupOpts: FibApp.FibAppDbSetupOpts = arguments[arguments.length - 1] - const appOpts: FibApp.FibAppOpts = (arguments[1] === dbSetupOpts ? null : arguments[1]) || {} + const args = Array.prototype.slice.apply(arguments); + const dbSetupOpts: FibApp.FibAppDbSetupOpts = util.last(args) + const appOpts: FibApp.FibAppOpts = (args[1] === dbSetupOpts ? null : args[1]) || {} Object.defineProperty(this, '__opts', { value: filterFibAppOptions(appOpts), @@ -43,6 +46,8 @@ class App extends mq.Routing implements FibApp.FibAppClass { this.__opts.graphqlTypeMap = this.__opts.graphqlTypeMap || (dbSetupOpts as any).graphqlTypeMap || {} this.ormPool = setupDb(this, connStr, dbSetupOpts); + appOpts.hooks = appOpts.hooks || {}; + setupApis.bind(this); setupTest.bind(this); diff --git a/src/http/hook.ts b/src/http/hook.ts new file mode 100644 index 0000000..d7f853c --- /dev/null +++ b/src/http/hook.ts @@ -0,0 +1,3 @@ +const { trigger, wait } = require('@fxjs/orm/lib/orm/entry/Hook.js') + +export { trigger, wait } \ No newline at end of file diff --git a/src/http/index.ts b/src/http/index.ts index cfe1d16..62d17eb 100644 --- a/src/http/index.ts +++ b/src/http/index.ts @@ -8,7 +8,7 @@ import _view = require('./view'); import { parse_req_resource_and_hdlr_type, filterRequest } from '../utils/filter_request' import { run_graphql, is_graphql_request } from '../utils/graphql'; import { run_batch } from '../utils/batch-request'; - +import * as Hook from './hook'; export function bind (app: FibApp.FibAppClass) { // bind it firstly @@ -16,6 +16,7 @@ export function bind (app: FibApp.FibAppClass) { const api = app.api = {} as FibApp.FibAppInternalApis; const viewApi = app.viewApi = {} as FibApp.FibAppInternalViewApis; + _base.setup(app); _extend.setup(app); _function.setup(app); @@ -40,11 +41,11 @@ export function bind (app: FibApp.FibAppClass) { /* api extend :start */ app.put(`${apiPathPrefix}/:classname/:id/:extend`, (req: FibApp.FibAppHttpRequest, classname: string, id: FibApp.AppIdType, extend: FibAppACL.ACLExtendModelNameType) => app.filterRequest(req, classname, id, extend, api.elink)); - app.put(`${apiPathPrefix}/:classname/:id/:extend/:rid`, (req: FibApp.FibAppHttpRequest, classname: string, id: FibApp.AppIdType, extend: FibAppACL.ACLExtendModelNameType, rid) => app.filterRequest(req, classname, id, extend, rid, api.eput)); + app.put(`${apiPathPrefix}/:classname/:id/:extend/:rid`, (req: FibApp.FibAppHttpRequest, classname: string, id: FibApp.AppIdType, extend: FibAppACL.ACLExtendModelNameType, rid: FibApp.AppIdType) => app.filterRequest(req, classname, id, extend, rid, api.eput)); app.post(`${apiPathPrefix}/:classname/:id/:extend`, (req: FibApp.FibAppHttpRequest, classname: string, id: FibApp.AppIdType, extend: FibAppACL.ACLExtendModelNameType) => app.filterRequest(req, classname, id, extend, api.epost)); app.get(`${apiPathPrefix}/:classname/:id/:extend`, (req: FibApp.FibAppHttpRequest, classname: string, id: FibApp.AppIdType, extend: FibAppACL.ACLExtendModelNameType) => app.filterRequest(req, classname, id, extend, filterApiCollection(req, app).efind)); - app.get(`${apiPathPrefix}/:classname/:id/:extend/:rid`, (req: FibApp.FibAppHttpRequest, classname: string, id: FibApp.AppIdType, extend: FibAppACL.ACLExtendModelNameType, rid) => app.filterRequest(req, classname, id, extend, rid, filterApiCollection(req, app).eget)); - app.del(`${apiPathPrefix}/:classname/:id/:extend/:rid`, (req: FibApp.FibAppHttpRequest, classname: string, id: FibApp.AppIdType, extend: FibAppACL.ACLExtendModelNameType, rid) => app.filterRequest(req, classname, id, extend, rid, api.edel)); + app.get(`${apiPathPrefix}/:classname/:id/:extend/:rid`, (req: FibApp.FibAppHttpRequest, classname: string, id: FibApp.AppIdType, extend: FibAppACL.ACLExtendModelNameType, rid: FibApp.AppIdType) => app.filterRequest(req, classname, id, extend, rid, filterApiCollection(req, app).eget)); + app.del(`${apiPathPrefix}/:classname/:id/:extend/:rid`, (req: FibApp.FibAppHttpRequest, classname: string, id: FibApp.AppIdType, extend: FibAppACL.ACLExtendModelNameType, rid: FibApp.AppIdType) => app.filterRequest(req, classname, id, extend, rid, api.edel)); /* api extend :end */ app.post(`${apiPathPrefix}/:classname/:func`, (req: FibApp.FibAppHttpRequest, classname: string, func: string) => { @@ -61,43 +62,48 @@ export function bind (app: FibApp.FibAppClass) { /* view base :end */ /* view extend :start */ app.get(`${viewPathPrefix}/:classname/:id/:extend`, (req: FibApp.FibAppHttpRequest, classname: string, id: FibApp.AppIdType, extend: FibAppACL.ACLExtendModelNameType) => app.filterRequest(req, classname, id, extend, viewApi.efind)); - app.get(`${viewPathPrefix}/:classname/:id/:extend/:rid`, (req: FibApp.FibAppHttpRequest, classname: string, id: FibApp.AppIdType, extend: FibAppACL.ACLExtendModelNameType, rid) => app.filterRequest(req, classname, id, extend, rid, viewApi.eget)); + app.get(`${viewPathPrefix}/:classname/:id/:extend/:rid`, (req: FibApp.FibAppHttpRequest, classname: string, id: FibApp.AppIdType, extend: FibAppACL.ACLExtendModelNameType, rid: FibApp.AppIdType) => app.filterRequest(req, classname, id, extend, rid, viewApi.eget)); /* view extend :end */ } } - if (!apiPathPrefix && viewPathPrefix) { - setupViewRoute() - setupApiRoute() - } else { - setupApiRoute() - setupViewRoute() - } + Hook.wait(app, app.__opts.hooks.beforeSetupRoute, function (err: FxOrmError.ExtendedError) { + if (err) + throw err; - /* setup graphql :start */ - const mergeRootAndGraphqlRoot = !graphQLPathPrefix || graphQLPathPrefix === '/' - if (!mergeRootAndGraphqlRoot) - app.post(graphQLPathPrefix, (req: FibApp.FibAppHttpRequest) => { - if (!is_graphql_request(req)) - return fill_error(req, err_info(4000005)) - - run_graphql(app, req) - }) - /* setup graphql :end */ + if (!apiPathPrefix && viewPathPrefix) { + setupViewRoute() + setupApiRoute() + } else { + setupApiRoute() + setupViewRoute() + } - /* setup batch task :end */ - const mergeRootAndBatchRoot = !batchPathPrefix || batchPathPrefix === '/' - if (!mergeRootAndBatchRoot) - app.post(batchPathPrefix, (req: FibApp.FibAppHttpRequest) => run_batch(app, req)) - /* setup batch task :end */ + /* setup graphql :start */ + const mergeRootAndGraphqlRoot = !graphQLPathPrefix || graphQLPathPrefix === '/' + if (!mergeRootAndGraphqlRoot) + app.post(graphQLPathPrefix, (req: FibApp.FibAppHttpRequest) => { + if (!is_graphql_request(req)) + return fill_error(req, err_info(4000005)) + + run_graphql(app, req) + }) + /* setup graphql :end */ - - /* finally, root setup */ - app.post('/', (req: FibApp.FibAppHttpRequest) => { - if (is_graphql_request(req)) - return mergeRootAndGraphqlRoot && run_graphql(app, req); - - mergeRootAndBatchRoot && run_batch(app, req) + /* setup batch task :end */ + const mergeRootAndBatchRoot = !batchPathPrefix || batchPathPrefix === '/' + if (!mergeRootAndBatchRoot) + app.post(batchPathPrefix, (req: FibApp.FibAppHttpRequest) => run_batch(app, req)) + /* setup batch task :end */ + + + /* finally, root setup */ + app.post('/', (req: FibApp.FibAppHttpRequest) => { + if (is_graphql_request(req)) + return mergeRootAndGraphqlRoot && run_graphql(app, req); + + mergeRootAndBatchRoot && run_batch(app, req) + }); }); };