@@ -3,7 +3,9 @@ import { Logger } from '@rocket.chat/logger';
33import { Users } from '@rocket.chat/models' ;
44import { Random } from '@rocket.chat/random' ;
55import type { JoinPathPattern , Method } from '@rocket.chat/rest-typings' ;
6+ import { ajv } from '@rocket.chat/rest-typings/src/v1/Ajv' ;
67import { wrapExceptions } from '@rocket.chat/tools' ;
8+ import type { ValidateFunction } from 'ajv' ;
79import express from 'express' ;
810import type { Request , Response } from 'express' ;
911import { Accounts } from 'meteor/accounts-base' ;
@@ -29,6 +31,8 @@ import type {
2931 PartialThis ,
3032 SuccessResult ,
3133 TypedThis ,
34+ TypedAction ,
35+ TypedOptions ,
3236 UnauthorizedResult ,
3337} from './definition' ;
3438import { getUserInfo } from './helpers/getUserInfo' ;
@@ -141,7 +145,14 @@ const generateConnection = (
141145 clientAddress : ipAddress ,
142146} ) ;
143147
144- export class APIClass < TBasePath extends string = '' > {
148+ export class APIClass <
149+ TBasePath extends string = '' ,
150+ TOperations extends {
151+ [ x : string ] : unknown ;
152+ } = { } ,
153+ > {
154+ public typedRoutes : Record < string , Record < string , unknown > > = { } ;
155+
145156 protected apiPath ?: string ;
146157
147158 readonly version ?: string ;
@@ -496,6 +507,182 @@ export class APIClass<TBasePath extends string = ''> {
496507 return routeActions . map ( ( action ) => this . getFullRouteName ( route , action ) ) ;
497508 }
498509
510+ private registerTypedRoutesLegacy < TSubPathPattern extends string , TOptions extends Options > (
511+ method : Method ,
512+ subpath : TSubPathPattern ,
513+ options : TOptions ,
514+ ) : void {
515+ const { authRequired, validateParams } = options ;
516+
517+ const opt = {
518+ authRequired,
519+ ...( validateParams &&
520+ method . toLowerCase ( ) === 'get' &&
521+ ( 'GET' in validateParams
522+ ? { query : validateParams . GET }
523+ : {
524+ query : validateParams as ValidateFunction < any > ,
525+ } ) ) ,
526+
527+ ...( validateParams &&
528+ method . toLowerCase ( ) === 'post' &&
529+ ( 'POST' in validateParams ? { query : validateParams . POST } : { body : validateParams as ValidateFunction < any > } ) ) ,
530+
531+ ...( validateParams &&
532+ method . toLowerCase ( ) === 'put' &&
533+ ( 'PUT' in validateParams ? { query : validateParams . PUT } : { body : validateParams as ValidateFunction < any > } ) ) ,
534+ ...( validateParams &&
535+ method . toLowerCase ( ) === 'delete' &&
536+ ( 'DELETE' in validateParams ? { query : validateParams . DELETE } : { body : validateParams as ValidateFunction < any > } ) ) ,
537+
538+ tags : [ 'Missing Documentation' ] ,
539+ response : {
540+ 200 : ajv . compile ( {
541+ type : 'object' ,
542+ properties : {
543+ success : { type : 'boolean' } ,
544+ error : { type : 'string' } ,
545+ } ,
546+ required : [ 'success' ] ,
547+ } ) ,
548+ } ,
549+ } ;
550+
551+ this . registerTypedRoutes ( method , subpath , opt ) ;
552+ }
553+
554+ private registerTypedRoutes <
555+ TSubPathPattern extends string ,
556+ TOptions extends TypedOptions ,
557+ TPathPattern extends `${TBasePath } /${TSubPathPattern } `,
558+ > ( method : Method , subpath : TSubPathPattern , options : TOptions ) : void {
559+ const path = `/${ this . _config . apiPath } /${ subpath } ` . replaceAll ( '//' , '/' ) as TPathPattern ;
560+ this . typedRoutes = this . typedRoutes || { } ;
561+ this . typedRoutes [ path ] = this . typedRoutes [ subpath ] || { } ;
562+ const { query, authRequired, response, body, tags, ...rest } = options ;
563+ this . typedRoutes [ path ] [ method . toLowerCase ( ) ] = {
564+ ...( response && {
565+ responses : Object . fromEntries (
566+ Object . entries ( response ) . map ( ( [ status , schema ] ) => [
567+ status ,
568+ {
569+ description : '' ,
570+ content : {
571+ 'application/json' : 'schema' in schema ? { schema : schema . schema } : schema ,
572+ } ,
573+ } ,
574+ ] ) ,
575+ ) ,
576+ } ) ,
577+ ...( query && {
578+ parameters : [
579+ {
580+ schema : query . schema ,
581+ in : 'query' ,
582+ name : 'query' ,
583+ required : true ,
584+ } ,
585+ ] ,
586+ } ) ,
587+ ...( body && {
588+ requestBody : {
589+ required : true ,
590+ content : {
591+ 'application/json' : { schema : body . schema } ,
592+ } ,
593+ } ,
594+ } ) ,
595+ ...( authRequired && {
596+ ...rest ,
597+ security : [
598+ {
599+ userId : [ ] ,
600+ authToken : [ ] ,
601+ } ,
602+ ] ,
603+ } ) ,
604+ tags,
605+ } ;
606+ }
607+
608+ private method < TSubPathPattern extends string , TOptions extends TypedOptions , TPathPattern extends `${TBasePath } /${TSubPathPattern } `> (
609+ method : Method ,
610+ subpath : TSubPathPattern ,
611+ options : TOptions ,
612+ action : TypedAction < TOptions > ,
613+ ) : APIClass <
614+ TBasePath ,
615+ | TOperations
616+ | ( {
617+ method : Method ;
618+ path : TPathPattern ;
619+ } & Omit < TOptions , 'response' > )
620+ > {
621+ this . addRoute ( [ subpath ] , { ...options } , { [ method . toLowerCase ( ) ] : { action } } as any ) ;
622+ this . registerTypedRoutes ( method , subpath , options ) ;
623+ return this ;
624+ }
625+
626+ get < TSubPathPattern extends string , TOptions extends TypedOptions , TPathPattern extends `${TBasePath } /${TSubPathPattern } `> (
627+ subpath : TSubPathPattern ,
628+ options : TOptions ,
629+ action : TypedAction < TOptions > ,
630+ ) : APIClass <
631+ TBasePath ,
632+ | TOperations
633+ | ( {
634+ method : 'GET' ;
635+ path : TPathPattern ;
636+ } & Omit < TOptions , 'response' > )
637+ > {
638+ return this . method ( 'GET' , subpath , options , action ) ;
639+ }
640+
641+ post < TSubPathPattern extends string , TOptions extends TypedOptions , TPathPattern extends `${TBasePath } /${TSubPathPattern } `> (
642+ subpath : TSubPathPattern ,
643+ options : TOptions ,
644+ action : TypedAction < TOptions > ,
645+ ) : APIClass <
646+ TBasePath ,
647+ | TOperations
648+ | ( {
649+ method : 'POST' ;
650+ path : TPathPattern ;
651+ } & Omit < TOptions , 'response' > )
652+ > {
653+ return this . method ( 'POST' , subpath , options , action ) ;
654+ }
655+
656+ put < TSubPathPattern extends string , TOptions extends TypedOptions , TPathPattern extends `${TBasePath } /${TSubPathPattern } `> (
657+ subpath : TSubPathPattern ,
658+ options : TOptions ,
659+ action : TypedAction < TOptions > ,
660+ ) : APIClass <
661+ TBasePath ,
662+ | TOperations
663+ | ( {
664+ method : 'PUT' ;
665+ path : TPathPattern ;
666+ } & Omit < TOptions , 'response' > )
667+ > {
668+ return this . method ( 'PUT' , subpath , options , action ) ;
669+ }
670+
671+ delete < TSubPathPattern extends string , TOptions extends TypedOptions , TPathPattern extends `${TBasePath } /${TSubPathPattern } `> (
672+ subpath : TSubPathPattern ,
673+ options : TOptions ,
674+ action : TypedAction < TOptions > ,
675+ ) : APIClass <
676+ TBasePath ,
677+ | TOperations
678+ | ( {
679+ method : 'DELETE' ;
680+ path : TPathPattern ;
681+ } & Omit < TOptions , 'response' > )
682+ > {
683+ return this . method ( 'DELETE' , subpath , options , action ) ;
684+ }
685+
499686 addRoute < TSubPathPattern extends string > (
500687 subpath : TSubPathPattern ,
501688 operations : Operations < JoinPathPattern < TBasePath , TSubPathPattern > > ,
@@ -707,6 +894,11 @@ export class APIClass<TBasePath extends string = ''> {
707894 options : _options ,
708895 endpoints : operations [ method as keyof Operations < TPathPattern , TOptions > ] as unknown as Record < string , string > ,
709896 } ) ;
897+
898+ this . registerTypedRoutesLegacy ( method as Method , route , {
899+ ...options ,
900+ ...operations [ method as keyof Operations < TPathPattern , TOptions > ] ,
901+ } ) ;
710902 } ) ;
711903 } ) ;
712904 }
@@ -938,17 +1130,14 @@ export class APIClass<TBasePath extends string = ''> {
9381130 }
9391131}
9401132
941- const createApi = function _createApi ( options : { version ?: string ; apiPath ?: string } = { } ) : APIClass {
942- return new APIClass (
943- Object . assign (
944- {
945- apiPath : 'api/' ,
946- useDefaultAuth : true ,
947- prettyJson : process . env . NODE_ENV === 'development' ,
948- } ,
949- options ,
950- ) as IAPIProperties ,
951- ) ;
1133+ const createApi = function _createApi ( options : { version ?: string ; useDefaultAuth ?: true } = { } ) : APIClass {
1134+ return new APIClass ( {
1135+ apiPath : 'api/' ,
1136+ useDefaultAuth : false ,
1137+ prettyJson : process . env . NODE_ENV === 'development' ,
1138+ auth : getUserAuth ( ) ,
1139+ ...options ,
1140+ } ) ;
9521141} ;
9531142
9541143export const API : {
@@ -982,12 +1171,10 @@ export const API: {
9821171 ApiClass : APIClass ,
9831172 api : new Router ( '/api' ) ,
9841173 v1 : createApi ( {
985- apiPath : '' ,
9861174 version : 'v1' ,
1175+ useDefaultAuth : true ,
9871176 } ) ,
988- default : createApi ( {
989- apiPath : '' ,
990- } ) ,
1177+ default : createApi ( { } ) ,
9911178} ;
9921179
9931180settings . watch < string > ( 'Accounts_CustomFields' , ( value ) => {
0 commit comments