Skip to content

Commit 92b6d73

Browse files
authored
feat: improved types for actions (#733)
* feat: improved types for actions * fix: revert back-compatible issues * chore: remove unused code
1 parent 8d44282 commit 92b6d73

8 files changed

Lines changed: 70 additions & 40 deletions

File tree

packages/plugin-router-hapi/src/attach.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@ export default function attachRouter(service: Microfleet, config: RouterHapiPlug
3939
name: 'microfleetRouter',
4040
version: '1.0.0',
4141
async register(server: Server) {
42-
for (const [actionName, handler] of service.router.routes.get(ActionTransport.http).entries()) {
42+
const routes = service.router.routes.get<{ TransportOptions: { hapi: ServerRoute } }>(ActionTransport.http)
43+
for (const [actionName, handler] of routes.entries()) {
4344
const path = fromNameToPath(actionName, config.prefix)
4445
const serverRoute: ServerRoute = {
4546
path,

packages/plugin-router/__tests__/artifacts/utils.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ const reqPromise = async (reqUrl: URL, requestOptions: any) => {
5959
return res
6060
}
6161

62-
export function getHTTPRequest<T = any>(_options: RequestInit & {url: string }): (action: string, params?: any, opts?: any) => Bluebird<T> {
62+
export function getHTTPRequest<T = any>(_options: RequestInit & { url: string }): (action: string, params?: any, opts?: any) => Bluebird<T> {
6363
return (action: string, params?: any, opts: any = {}): Bluebird<T> => {
6464
const { url, ...options } = _options
6565
const requestOptions = {
@@ -70,6 +70,10 @@ export function getHTTPRequest<T = any>(_options: RequestInit & {url: string }):
7070
...options,
7171
}
7272

73+
if (opts.method) {
74+
requestOptions.method = opts.method
75+
}
76+
7377
const reqUrl = new URL(`${url}${action}`)
7478

7579
requestOptions.body = (params || opts.json) ? JSON.stringify(opts.json || params) : null

packages/plugin-router/__tests__/suites/01.router.spec.ts

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -249,15 +249,13 @@ describe('@microfleet/plugin-router', async () => {
249249
}
250250

251251
await service.connect()
252-
await Promise.all([
253-
rget({ sample: 1, bool: true }),
254-
rget({ sample: 'crap', bool: true }, false),
255-
rget({ sample: 13, bool: 'invalid' }, false),
256-
rget({ sample: 13, bool: '0' }),
257-
rget({ sample: 13, bool: '0', oops: 'q' }, false),
258-
rget({ sample: 13.4, bool: '0' }, false),
259-
rget(null, false, { json: { sample: 13.4, bool: '0' }, method: 'post' }),
260-
])
252+
await rget({ sample: 1, bool: true })
253+
await rget({ sample: 'crap', bool: true }, false)
254+
await rget({ sample: 13, bool: 'invalid' }, false)
255+
await rget({ sample: 13, bool: '0' })
256+
await rget({ sample: 13, bool: '0', oops: 'q' }, false)
257+
await rget({ sample: 13.4, bool: '0' }, false)
258+
await rget(null, false, { json: { sample: 13.4, bool: '0' }, method: 'post' })
261259
})
262260

263261
it('should be able to set schema and responseSchema from action name', async () => {

packages/plugin-router/src/extensions/audit/log.ts

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { Microfleet } from '@microfleet/core-types'
2-
import type { ServiceRequest } from '../../types/router'
2+
import type { ReplyGenericInterface, RequestGenericInterface, ServiceRequest } from '../../types/router'
33
import { Lifecycle, LifecycleExtensions } from '../../lifecycle/index'
44
import { initTimingExtension } from './timing'
55

@@ -13,15 +13,18 @@ export type AuditLogExtensionParams = {
1313
getErrorLevel?: (this: Microfleet, error: any) => ErrorLevel | undefined
1414
}
1515

16-
export type MetaLog = {
17-
headers: Record<string, unknown>
16+
export type MetaLog<
17+
DefaultRequest extends RequestGenericInterface = RequestGenericInterface,
18+
DefaultReply extends ReplyGenericInterface = ReplyGenericInterface
19+
> = {
20+
headers: DefaultRequest["Headers"]
1821
latency: number | null
1922
method: string
20-
params: any
21-
query: any
23+
params: DefaultRequest["Params"]
24+
query: DefaultRequest["Querystring"]
2225
route: string
2326
transport: string
24-
response?: any
27+
response?: DefaultReply["Reply"]
2528
err?: Error
2629
}
2730

packages/plugin-router/src/extensions/validate/query-string-parser.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
import { parse } from 'qs'
1+
import { parse, type ParsedQs } from 'qs'
22
import { Lifecycle } from '../../lifecycle/index'
33
import { ServiceRequest } from '../../types/router'
44

55
type QSParserAugmentedAction = ServiceRequest & {
66
action: ServiceRequest['action'] & {
7-
transformQuery?: (...args: any[]) => any;
8-
transformOpts?: any;
7+
transformQuery?: (input: Record<string, any>) => ParsedQs;
8+
transformOpts?: Parameters<typeof parse>[1];
99
};
1010
}
1111

@@ -19,7 +19,8 @@ async function preValidate(request: QSParserAugmentedAction): Promise<any> {
1919
const { action } = request
2020
const { transformQuery = identity, transformOpts } = action
2121

22-
request.query = transformQuery(parse(query, {
22+
// module actually handles all variations of input
23+
request.query = transformQuery(parse(query as any, {
2324
depth: 1,
2425
parameterLimit: 10,
2526
parseArrays: false,

packages/plugin-router/src/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ export type {
1818
ServiceMiddleware,
1919
ServiceActionHandler,
2020
ServiceActionAuthGetName,
21-
TransportOptions,
21+
RequestGenericInterface,
22+
ReplyGenericInterface
2223
} from './types/router'
2324

2425
export type { AuthInfo } from './lifecycle/handlers/auth'

packages/plugin-router/src/routes.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,21 @@
1-
import { ServiceAction } from './types/router'
1+
import type { ReplyGenericInterface, RequestGenericInterface, ServiceAction } from './types/router'
22

33
export type RouteName = string
44
export type TransportName = string
5-
export type RoutesCollection = Map<RouteName, ServiceAction>
5+
export type RoutesCollection<
6+
DefaultRequest extends RequestGenericInterface = RequestGenericInterface,
7+
DefaultResponse extends ReplyGenericInterface = ReplyGenericInterface
8+
> = Map<RouteName, ServiceAction<DefaultRequest, DefaultResponse>>
69
export type RoutesGroupedByTransport = Map<TransportName, RoutesCollection>
710
export default class Routes {
811
protected groupedByTransport: RoutesGroupedByTransport = new Map()
912

10-
get(transport: TransportName): RoutesCollection {
13+
get<
14+
DefaultRequest extends RequestGenericInterface = RequestGenericInterface,
15+
DefaultResponse extends ReplyGenericInterface = ReplyGenericInterface
16+
>(transport: TransportName): RoutesCollection<DefaultRequest, DefaultResponse> {
1117
const { groupedByTransport } = this
12-
const routes: RoutesCollection = groupedByTransport.get(transport) || new Map()
18+
const routes: RoutesCollection<DefaultRequest, DefaultResponse> = groupedByTransport.get(transport) || new Map()
1319

1420
groupedByTransport.set(transport, routes)
1521

packages/plugin-router/src/types/router.ts

Lines changed: 30 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,34 +7,50 @@ export type ServiceMiddleware = (this: Microfleet, request: ServiceRequest) => P
77
export type ServiceActionAuthGetName = (request: ServiceRequest) => string
88
export type ServiceActionHandler = ServiceAction['handler']
99

10-
export interface ServiceAction<R = unknown> {
11-
handler(this: Microfleet, request: ServiceRequest, ...params: any[]): Promise<R>
10+
11+
export interface RequestGenericInterface {
12+
Params?: unknown;
13+
Headers?: unknown;
14+
Querystring?: unknown;
15+
Locals?: unknown;
16+
TransportOptions?: unknown;
17+
}
18+
19+
export interface ReplyGenericInterface {
20+
Reply?: unknown;
21+
}
22+
export interface ServiceAction<
23+
DefaultRequest extends RequestGenericInterface = RequestGenericInterface,
24+
DefaultReply extends ReplyGenericInterface = ReplyGenericInterface,
25+
> {
26+
handler(this: Microfleet, request: ServiceRequest, ...params: any[]): Promise<DefaultReply["Reply"]>
1227
actionName: string
1328
transports: ServiceRequest['transport'][]
14-
transportOptions?: TransportOptions
29+
transportOptions?: DefaultRequest["TransportOptions"]
1530
validateResponse: boolean
1631
schema?: string | null | boolean
1732
responseSchema?: string;
1833
readonly?: boolean
1934
}
2035

21-
// eslint-disable-next-line @typescript-eslint/no-empty-interface
22-
export interface TransportOptions {}
23-
24-
export interface ServiceRequest<R = unknown> {
36+
export interface ServiceRequest<
37+
DefaultRequest extends RequestGenericInterface = RequestGenericInterface,
38+
DefaultReply extends ReplyGenericInterface = ReplyGenericInterface,
39+
ErrorArg extends Error & { name: string, code?: string } = any
40+
> {
2541
route: string
26-
action: ServiceAction<R>
27-
params: any
28-
headers: any
29-
query: any
42+
action: ServiceAction<DefaultRequest, DefaultReply>
43+
params: DefaultRequest["Params"]
44+
headers: DefaultRequest["Headers"]
45+
query: DefaultRequest["Querystring"]
3046
method: keyof typeof RequestDataKey
3147
transport: typeof ActionTransport[keyof typeof ActionTransport]
3248
transportRequest: any | ClientRequest
33-
locals: any
49+
locals: DefaultRequest["Locals"]
3450
parentSpan: null
3551
span: null
3652
log: Logger
37-
response?: unknown
38-
error?: any
53+
response?: DefaultReply["Reply"]
54+
error?: ErrorArg
3955
reformatError: boolean
4056
}

0 commit comments

Comments
 (0)