Skip to content

Commit

Permalink
feat: integrate utils for customizing api route. (#61)
Browse files Browse the repository at this point in the history
  • Loading branch information
richardo2016 authored Nov 9, 2023
1 parent 40e6cfa commit 03bd5ed
Show file tree
Hide file tree
Showing 7 changed files with 183 additions and 6 deletions.
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "fib-app",
"version": "1.16.10",
"version": "1.16.11-alpha.1",
"description": "",
"main": "lib",
"types": "typings/index.d.ts",
Expand Down
77 changes: 77 additions & 0 deletions src/http/customize.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import { FibApp } from '../Typo/app';

type ApiRouteContext = Parameters<FibApp.FibAppOpts['customizeApiRoute']>[0];

type GetHandlerType<T, K extends ApiRouteContext['routeType']> = T extends {
routeType: K
handler: infer H;
} ? { [P in K]: H }[K] : never

type FibAppApiHandlers = {
[K in ApiRouteContext['routeType']]: GetHandlerType<ApiRouteContext, K>
}

type BaseFilter = {
basecls: string,
extend?: string,
id?: string,
rid?: string,
};

type PostFuncFilter = { func: string | string[] };

function onApiRoute<T extends ApiRouteContext['routeType']>(
ctx: ApiRouteContext,
routeType: T,
_filters: T extends 'http-postfunc' ? (BaseFilter & PostFuncFilter) : (string | BaseFilter),
userDefineHandler: FibAppApiHandlers[T]
) {
if (routeType !== ctx.routeType) return null;

const filters: BaseFilter & Partial<PostFuncFilter> = typeof _filters === 'string' ? { basecls: _filters } : _filters;

const funcs = (Array.isArray(filters.func) ? filters.func : [filters.func]).filter(Boolean);

if (routeType === 'http-postfunc' && !funcs.length) {
throw new Error(`[onApiRoute] func name is required for route with type 'http-postfunc'`);
}

return (...args: Parameters<typeof userDefineHandler>) => {
const [, _maybeBase, _idOrFunc, _maybeExtend, _eid] = args;
if (_maybeBase !== filters.basecls) return ;

if (filters.extend) {
if (_maybeExtend !== filters.extend) return ;
if (filters.rid && _eid !== filters.rid) return ;
}

if (routeType === 'http-postfunc' && !funcs.includes(_idOrFunc as string)) {
return ;
}

return userDefineHandler.apply(null, args);
};
}

export function makeCustomizeApiRoute(
maker: (ctx: {
onApiRoute: typeof onApiRoute
}) => FibApp.FibAppOpts['customizeApiRoute'],
options?: {
allowCustomizePostApiRoute?: FibApp.FibAppOpts['customizeApiRoute']['allowCustomizePostApiRoute']
}
) {
const customize = maker({
onApiRoute,
});

if (options?.allowCustomizePostApiRoute) {
Object.defineProperty(customize, 'allowCustomizePostApiRoute', {
value: true,
writable: false,
configurable: false,
});
}

return customize;
}
4 changes: 3 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,6 @@ export { FibApp };

export function defineAppModel<T = any>(definition: FibApp.FibAppOrmDefineFn<T>) {
return definition;
};
};

export { makeCustomizeApiRoute } from './http/customize';
35 changes: 33 additions & 2 deletions type-test/project/src/app.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,41 @@
import { expectType } from 'ts-expect';

import App, { FibApp } from '@src';
import App, { FibApp, makeCustomizeApiRoute } from '@src';

import { UserDef } from './defs';

const app = new App('sqlite://:memory:', {});
declare function isNotAuthorized(req: FibApp.FibAppHttpRequest): boolean;
declare function isAuthorized(req: FibApp.FibAppHttpRequest): boolean;

const customizeApiRoute = makeCustomizeApiRoute(({ onApiRoute }) => {
return (ctx) => {
return [
onApiRoute(ctx, 'http-rest-find', 'users', (req) => {
expectType<FibApp.FibAppHttpRequest>(req);

if (isNotAuthorized(req)) {
return req.end();
}

// deal with your request
expectType<FibApp.FibAppClass>(ctx.app);

// then ...
req.end();
}),
// original fib-app handler, we must make sure it in the array,
// by default, it should be at the last position, if you want to
// put it in the middle, enable `allowCustomizePostApiRoute` option
ctx.handler,
]
}
}, {
allowCustomizePostApiRoute: false,
})

const app = new App('sqlite://:memory:', {
customizeApiRoute,
}, {});

app.db(orm => {
UserDef(orm);
Expand Down
66 changes: 66 additions & 0 deletions typings/http/customize.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { FibApp } from '../Typo/app';
declare type ApiRouteContext = Parameters<FibApp.FibAppOpts['customizeApiRoute']>[0];
declare type GetHandlerType<T, K extends ApiRouteContext['routeType']> = T extends {
routeType: K;
handler: infer H;
} ? {
[P in K]: H;
}[K] : never;
declare type FibAppApiHandlers = {
[K in ApiRouteContext['routeType']]: GetHandlerType<ApiRouteContext, K>;
};
declare type BaseFilter = {
basecls: string;
extend?: string;
id?: string;
rid?: string;
};
declare type PostFuncFilter = {
func: string | string[];
};
declare function onApiRoute<T extends ApiRouteContext['routeType']>(ctx: ApiRouteContext, routeType: T, _filters: T extends 'http-postfunc' ? (BaseFilter & PostFuncFilter) : (string | BaseFilter), userDefineHandler: FibAppApiHandlers[T]): (...args: Parameters<typeof userDefineHandler>) => any;
export declare function makeCustomizeApiRoute(maker: (ctx: {
onApiRoute: typeof onApiRoute;
}) => FibApp.FibAppOpts['customizeApiRoute'], options?: {
allowCustomizePostApiRoute?: FibApp.FibAppOpts['customizeApiRoute']['allowCustomizePostApiRoute'];
}): ((context: {
app: FibApp.FibAppClass;
} & ({
routeType: "http-rest-post";
handler: (origReq: FibApp.FibAppHttpRequest, classname: string) => void;
} | {
routeType: "http-rest-get";
handler: (origReq: FibApp.FibAppHttpRequest, classname: string, id: FibApp.AppIdType) => void;
} | {
routeType: "http-rest-put";
handler: (origReq: FibApp.FibAppHttpRequest, classname: string, id: FibApp.AppIdType) => void;
} | {
routeType: "http-rest-delete";
handler: (origReq: FibApp.FibAppHttpRequest, classname: string, id: FibApp.AppIdType, extend: string) => void;
} | {
routeType: "http-rest-find";
handler: (origReq: FibApp.FibAppHttpRequest, classname: string) => void;
} | {
routeType: "http-rest-epost";
handler: (req: FibApp.FibAppHttpRequest, classname: string, id: FibApp.AppIdType, extend: string) => void;
} | {
routeType: "http-rest-eput";
withExtendId?: boolean;
handler: (req: FibApp.FibAppHttpRequest, classname: string, id: FibApp.AppIdType, extend: string, rid?: FibApp.AppIdType) => void;
} | {
routeType: "http-rest-efind";
handler: (req: FibApp.FibAppHttpRequest, classname: string, id: FibApp.AppIdType, extend: string) => void;
} | {
routeType: "http-rest-eget";
withExtendId?: boolean;
handler: (req: FibApp.FibAppHttpRequest, classname: string, id: FibApp.AppIdType, extend: string, rid?: FibApp.AppIdType) => void;
} | {
routeType: "http-rest-edel";
handler: (req: FibApp.FibAppHttpRequest, classname: string, id: FibApp.AppIdType, extend: string, rid: FibApp.AppIdType) => void;
} | {
routeType: "http-postfunc";
handler: (origReq: FibApp.FibAppHttpRequest, classname: string, func_name: string) => void;
})) => ((origReq: FibApp.FibAppHttpRequest, classname: string) => void) | ((origReq: FibApp.FibAppHttpRequest, classname: string, id: FibApp.AppIdType) => void) | ((origReq: FibApp.FibAppHttpRequest, classname: string, id: FibApp.AppIdType) => void) | ((origReq: FibApp.FibAppHttpRequest, classname: string, id: FibApp.AppIdType, extend: string) => void) | ((origReq: FibApp.FibAppHttpRequest, classname: string) => void) | ((req: FibApp.FibAppHttpRequest, classname: string, id: FibApp.AppIdType, extend: string) => void) | ((req: FibApp.FibAppHttpRequest, classname: string, id: FibApp.AppIdType, extend: string, rid?: FibApp.AppIdType) => void) | ((req: FibApp.FibAppHttpRequest, classname: string, id: FibApp.AppIdType, extend: string) => void) | ((req: FibApp.FibAppHttpRequest, classname: string, id: FibApp.AppIdType, extend: string, rid?: FibApp.AppIdType) => void) | ((req: FibApp.FibAppHttpRequest, classname: string, id: FibApp.AppIdType, extend: string, rid: FibApp.AppIdType) => void) | ((origReq: FibApp.FibAppHttpRequest, classname: string, func_name: string) => void) | (((origReq: FibApp.FibAppHttpRequest, classname: string) => void) | ((origReq: FibApp.FibAppHttpRequest, classname: string, id: FibApp.AppIdType) => void) | ((origReq: FibApp.FibAppHttpRequest, classname: string, id: FibApp.AppIdType) => void) | ((origReq: FibApp.FibAppHttpRequest, classname: string, id: FibApp.AppIdType, extend: string) => void) | ((origReq: FibApp.FibAppHttpRequest, classname: string) => void) | ((req: FibApp.FibAppHttpRequest, classname: string, id: FibApp.AppIdType, extend: string) => void) | ((req: FibApp.FibAppHttpRequest, classname: string, id: FibApp.AppIdType, extend: string, rid?: FibApp.AppIdType) => void) | ((req: FibApp.FibAppHttpRequest, classname: string, id: FibApp.AppIdType, extend: string) => void) | ((req: FibApp.FibAppHttpRequest, classname: string, id: FibApp.AppIdType, extend: string, rid?: FibApp.AppIdType) => void) | ((req: FibApp.FibAppHttpRequest, classname: string, id: FibApp.AppIdType, extend: string, rid: FibApp.AppIdType) => void) | ((origReq: FibApp.FibAppHttpRequest, classname: string, func_name: string) => void))[]) & {
allowCustomizePostApiRoute?: boolean;
};
export {};
1 change: 1 addition & 0 deletions typings/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ export default App;
import type { FibApp } from './Typo/app';
export { FibApp };
export declare function defineAppModel<T = any>(definition: FibApp.FibAppOrmDefineFn<T>): FibApp.FibAppOrmDefineFn<T>;
export { makeCustomizeApiRoute } from './http/customize';

0 comments on commit 03bd5ed

Please sign in to comment.