@@ -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 { tracerSpan } from '@rocket.chat/tracing' ;
8+ import type { ValidateFunction } from 'ajv' ;
79import { Accounts } from 'meteor/accounts-base' ;
810import { DDP } from 'meteor/ddp' ;
911import { DDPCommon } from 'meteor/ddp-common' ;
@@ -26,6 +28,8 @@ import type {
2628 Options ,
2729 PartialThis ,
2830 SuccessResult ,
31+ TypedAction ,
32+ TypedOptions ,
2933 UnauthorizedResult ,
3034} from './definition' ;
3135import { getUserInfo } from './helpers/getUserInfo' ;
@@ -137,7 +141,14 @@ const generateConnection = (
137141
138142let prometheusAPIUserAgent = false ;
139143
140- export class APIClass < TBasePath extends string = '' > extends Restivus {
144+ export class APIClass <
145+ TBasePath extends string = '' ,
146+ TOperations extends {
147+ [ x : string ] : unknown ;
148+ } = { } ,
149+ > extends Restivus {
150+ public typedRoutes : Record < string , Record < string , unknown > > = { } ;
151+
141152 protected apiPath ?: string ;
142153
143154 public authMethods : ( ( ...args : any [ ] ) => any ) [ ] ;
@@ -484,6 +495,182 @@ export class APIClass<TBasePath extends string = ''> extends Restivus {
484495 return routeActions . map ( ( action ) => this . getFullRouteName ( route , action , apiVersion ) ) ;
485496 }
486497
498+ private registerTypedRoutesLegacy < TSubPathPattern extends string , TOptions extends Options > (
499+ method : Method ,
500+ subpath : TSubPathPattern ,
501+ options : TOptions ,
502+ ) : void {
503+ const { authRequired, validateParams } = options ;
504+
505+ const opt = {
506+ authRequired,
507+ ...( validateParams &&
508+ method . toLowerCase ( ) === 'get' &&
509+ ( 'GET' in validateParams
510+ ? { query : validateParams . GET }
511+ : {
512+ query : validateParams as ValidateFunction < any > ,
513+ } ) ) ,
514+
515+ ...( validateParams &&
516+ method . toLowerCase ( ) === 'post' &&
517+ ( 'POST' in validateParams ? { query : validateParams . POST } : { body : validateParams as ValidateFunction < any > } ) ) ,
518+
519+ ...( validateParams &&
520+ method . toLowerCase ( ) === 'put' &&
521+ ( 'PUT' in validateParams ? { query : validateParams . PUT } : { body : validateParams as ValidateFunction < any > } ) ) ,
522+ ...( validateParams &&
523+ method . toLowerCase ( ) === 'delete' &&
524+ ( 'DELETE' in validateParams ? { query : validateParams . DELETE } : { body : validateParams as ValidateFunction < any > } ) ) ,
525+
526+ tags : [ 'Missing Documentation' ] ,
527+ response : {
528+ 200 : ajv . compile ( {
529+ type : 'object' ,
530+ properties : {
531+ success : { type : 'boolean' } ,
532+ error : { type : 'string' } ,
533+ } ,
534+ required : [ 'success' ] ,
535+ } ) ,
536+ } ,
537+ } ;
538+
539+ this . registerTypedRoutes ( method , subpath , opt ) ;
540+ }
541+
542+ private registerTypedRoutes <
543+ TSubPathPattern extends string ,
544+ TOptions extends TypedOptions ,
545+ TPathPattern extends `${TBasePath } /${TSubPathPattern } `,
546+ > ( method : Method , subpath : TSubPathPattern , options : TOptions ) : void {
547+ const path = `/${ this . _config . apiPath } /${ subpath } ` . replaceAll ( '//' , '/' ) as TPathPattern ;
548+ this . typedRoutes = this . typedRoutes || { } ;
549+ this . typedRoutes [ path ] = this . typedRoutes [ subpath ] || { } ;
550+ const { query, authRequired, response, body, tags, ...rest } = options ;
551+ this . typedRoutes [ path ] [ method . toLowerCase ( ) ] = {
552+ ...( response && {
553+ responses : Object . fromEntries (
554+ Object . entries ( response ) . map ( ( [ status , schema ] ) => [
555+ status ,
556+ {
557+ description : '' ,
558+ content : {
559+ 'application/json' : 'schema' in schema ? { schema : schema . schema } : schema ,
560+ } ,
561+ } ,
562+ ] ) ,
563+ ) ,
564+ } ) ,
565+ ...( query && {
566+ parameters : [
567+ {
568+ schema : query . schema ,
569+ in : 'query' ,
570+ name : 'query' ,
571+ required : true ,
572+ } ,
573+ ] ,
574+ } ) ,
575+ ...( body && {
576+ requestBody : {
577+ required : true ,
578+ content : {
579+ 'application/json' : { schema : body . schema } ,
580+ } ,
581+ } ,
582+ } ) ,
583+ ...( authRequired && {
584+ ...rest ,
585+ security : [
586+ {
587+ userId : [ ] ,
588+ authToken : [ ] ,
589+ } ,
590+ ] ,
591+ } ) ,
592+ tags,
593+ } ;
594+ }
595+
596+ private method < TSubPathPattern extends string , TOptions extends TypedOptions , TPathPattern extends `${TBasePath } /${TSubPathPattern } `> (
597+ method : Method ,
598+ subpath : TSubPathPattern ,
599+ options : TOptions ,
600+ action : TypedAction < TOptions > ,
601+ ) : APIClass <
602+ TBasePath ,
603+ | TOperations
604+ | ( {
605+ method : Method ;
606+ path : TPathPattern ;
607+ } & Omit < TOptions , 'response' > )
608+ > {
609+ this . addRoute ( [ subpath ] , { ...options } , { [ method . toLowerCase ( ) ] : { action } } as any ) ;
610+ this . registerTypedRoutes ( method , subpath , options ) ;
611+ return this ;
612+ }
613+
614+ get < TSubPathPattern extends string , TOptions extends TypedOptions , TPathPattern extends `${TBasePath } /${TSubPathPattern } `> (
615+ subpath : TSubPathPattern ,
616+ options : TOptions ,
617+ action : TypedAction < TOptions > ,
618+ ) : APIClass <
619+ TBasePath ,
620+ | TOperations
621+ | ( {
622+ method : 'GET' ;
623+ path : TPathPattern ;
624+ } & Omit < TOptions , 'response' > )
625+ > {
626+ return this . method ( 'GET' , subpath , options , action ) ;
627+ }
628+
629+ post < TSubPathPattern extends string , TOptions extends TypedOptions , TPathPattern extends `${TBasePath } /${TSubPathPattern } `> (
630+ subpath : TSubPathPattern ,
631+ options : TOptions ,
632+ action : TypedAction < TOptions > ,
633+ ) : APIClass <
634+ TBasePath ,
635+ | TOperations
636+ | ( {
637+ method : 'POST' ;
638+ path : TPathPattern ;
639+ } & Omit < TOptions , 'response' > )
640+ > {
641+ return this . method ( 'POST' , subpath , options , action ) ;
642+ }
643+
644+ put < TSubPathPattern extends string , TOptions extends TypedOptions , TPathPattern extends `${TBasePath } /${TSubPathPattern } `> (
645+ subpath : TSubPathPattern ,
646+ options : TOptions ,
647+ action : TypedAction < TOptions > ,
648+ ) : APIClass <
649+ TBasePath ,
650+ | TOperations
651+ | ( {
652+ method : 'PUT' ;
653+ path : TPathPattern ;
654+ } & Omit < TOptions , 'response' > )
655+ > {
656+ return this . method ( 'PUT' , subpath , options , action ) ;
657+ }
658+
659+ delete < TSubPathPattern extends string , TOptions extends TypedOptions , TPathPattern extends `${TBasePath } /${TSubPathPattern } `> (
660+ subpath : TSubPathPattern ,
661+ options : TOptions ,
662+ action : TypedAction < TOptions > ,
663+ ) : APIClass <
664+ TBasePath ,
665+ | TOperations
666+ | ( {
667+ method : 'DELETE' ;
668+ path : TPathPattern ;
669+ } & Omit < TOptions , 'response' > )
670+ > {
671+ return this . method ( 'DELETE' , subpath , options , action ) ;
672+ }
673+
487674 addRoute < TSubPathPattern extends string > (
488675 subpath : TSubPathPattern ,
489676 operations : Operations < JoinPathPattern < TBasePath , TSubPathPattern > > ,
@@ -752,8 +939,12 @@ export class APIClass<TBasePath extends string = ''> extends Restivus {
752939
753940 // Allow the endpoints to make usage of the logger which respects the user's settings
754941 ( operations [ method as keyof Operations < TPathPattern , TOptions > ] as Record < string , any > ) . logger = logger ;
755- } ) ;
756942
943+ this . registerTypedRoutesLegacy ( method as Method , route , {
944+ ...options ,
945+ ...operations [ method as keyof Operations < TPathPattern , TOptions > ] ,
946+ } ) ;
947+ } ) ;
757948 super . addRoute ( route , options , operations ) ;
758949 } ) ;
759950 }
@@ -1058,19 +1249,15 @@ const defaultOptionsEndpoint = async function _defaultOptionsEndpoint(this: Rest
10581249 this . done ( ) ;
10591250} ;
10601251
1061- const createApi = function _createApi ( options : { version ?: string } = { } ) : APIClass {
1062- return new APIClass (
1063- Object . assign (
1064- {
1065- apiPath : 'api/' ,
1066- useDefaultAuth : true ,
1067- prettyJson : process . env . NODE_ENV === 'development' ,
1068- defaultOptionsEndpoint,
1069- auth : getUserAuth ( ) ,
1070- } ,
1071- options ,
1072- ) as IAPIProperties ,
1073- ) ;
1252+ const createApi = function _createApi ( options : { version ?: string ; useDefaultAuth ?: true } = { } ) : APIClass {
1253+ return new APIClass ( {
1254+ apiPath : 'api/' ,
1255+ useDefaultAuth : false ,
1256+ prettyJson : process . env . NODE_ENV === 'development' ,
1257+ defaultOptionsEndpoint,
1258+ auth : getUserAuth ( ) ,
1259+ ...options ,
1260+ } ) ;
10741261} ;
10751262
10761263export const API : {
@@ -1105,6 +1292,7 @@ export const API: {
11051292 ApiClass : APIClass ,
11061293 v1 : createApi ( {
11071294 version : 'v1' ,
1295+ useDefaultAuth : true ,
11081296 } ) ,
11091297 default : createApi ( ) ,
11101298} ;
0 commit comments