Skip to content
Open
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 0 additions & 5 deletions app/definitions/rest/helpers/PaginatedRequest.ts

This file was deleted.

5 changes: 0 additions & 5 deletions app/definitions/rest/helpers/PaginatedResult.ts

This file was deleted.

127 changes: 107 additions & 20 deletions app/definitions/rest/helpers/index.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
import { type Endpoints } from '../v1';
// POC: This file implements rest-typings patterns adapted to work with our current Endpoints structure.
// Once all endpoint definitions are migrated to use @rocket.chat/rest-typings Endpoints
// (which uses /v1/ prefix paths), we can replace this with direct imports from the package.
import type { KeyOfEach } from '@rocket.chat/core-typings';
import type { ReplacePlaceholders } from '@rocket.chat/rest-typings';

type ReplacePlaceholders<TPath extends string> = string extends TPath
? TPath
: TPath extends `${infer Start}:${infer _Param}/${infer Rest}`
? `${Start}${string}/${ReplacePlaceholders<Rest>}`
: TPath extends `${infer Start}:${infer _Param}`
? `${Start}${string}`
: TPath;
import { type Endpoints } from '../v1';

type KeyOfEach<T> = T extends any ? keyof T : never;
// Re-export utility types from rest-typings that we can use directly
export type { ReplacePlaceholders } from '@rocket.chat/rest-typings';

// GetParams and GetResult - matching rest-typings implementation
type GetParams<TOperation> = TOperation extends (...args: any) => any
? Parameters<TOperation>[0] extends void
? void
Expand All @@ -26,7 +26,7 @@ type OperationsByPathPatternAndMethod<
? {
pathPattern: TPathPattern;
method: TMethod;
path: ReplacePlaceholders<TPathPattern>;
path: ReplacePlaceholders<TPathPattern & string>;
params: GetParams<Endpoints[TPathPattern][TMethod]>;
result: GetResult<Endpoints[TPathPattern][TMethod]>;
}
Expand All @@ -38,11 +38,10 @@ type OperationsByPathPattern<TPathPattern extends keyof Endpoints> = TPathPatter

type Operations = OperationsByPathPattern<keyof Endpoints>;

type Method = Operations['method'];

// Core types matching rest-typings structure
export type Method = Operations['method'];
export type PathPattern = Operations['pathPattern'];

type Path = Operations['path'];
export type Path = Operations['path'];

//

Expand All @@ -56,22 +55,108 @@ export type Serialized<T> = T extends Date
}
: null;

// MatchPathPattern - matching rest-typings implementation
export type MatchPathPattern<TPath extends Path> = TPath extends any
? Extract<Operations, { path: TPath }>['pathPattern']
: never;

export type OperationResult<
TMethod extends Method,
TPathPattern extends PathPattern
> = TMethod extends keyof Endpoints[TPathPattern] ? GetResult<Endpoints[TPathPattern][TMethod]> : never;
// JoinPathPattern - utility from rest-typings for combining path patterns
export type JoinPathPattern<
TBasePath extends string,
TSubPathPattern extends string
> = Extract<
PathPattern,
`${TBasePath}${TSubPathPattern extends '' ? TSubPathPattern : `/${TSubPathPattern}`}` | TSubPathPattern
>;

// UrlParams - extracts URL parameters from path patterns (from rest-typings)
export type UrlParams<T extends string> = string extends T
? Record<string, string>
: T extends `${string}:${infer Param}/${infer Rest}`
? {
[k in Param | keyof UrlParams<Rest>]: string;
}
: T extends `${string}:${infer Param}`
? {
[k in Param]: string;
}
: undefined | Record<string, never>;

// MethodOf - gets methods available for a path pattern (from rest-typings)
export type MethodOf<TPathPattern extends PathPattern> = TPathPattern extends any
? keyof Endpoints[TPathPattern]
: never;

// PathFor - matching rest-typings implementation pattern
type MethodToPathMap = {
[TOperation in Operations as TOperation['method']]: TOperation['path'];
};

export type PathFor<TMethod extends Method> = TMethod extends any ? Extract<Operations, { method: TMethod }>['path'] : never;
export type PathFor<TMethod extends Method> = MethodToPathMap[TMethod];

// PathWithParamsFor and PathWithoutParamsFor - additional utilities from rest-typings
// These check if the operation function has parameters (matching rest-typings pattern)
type MethodToPathWithParamsMap = {
[TOperation in Operations as TOperation['params'] extends void
? never
: TOperation['method']]: TOperation['path'];
};

type MethodToPathWithoutParamsMap = {
[TOperation in Operations as TOperation['params'] extends void
? TOperation['method']
: undefined extends TOperation['params']
? TOperation['method']
: never]: TOperation['path'];
};

export type PathWithParamsFor<TMethod extends Method> = MethodToPathWithParamsMap[TMethod extends keyof MethodToPathWithParamsMap
? TMethod
: never];

export type PathWithoutParamsFor<TMethod extends Method> = MethodToPathWithoutParamsMap[TMethod extends keyof MethodToPathWithoutParamsMap
? TMethod
: never];

// OperationParams and OperationResult - matching rest-typings implementation
export type OperationParams<
TMethod extends Method,
TPathPattern extends PathPattern
> = TMethod extends keyof Endpoints[TPathPattern] ? GetParams<Endpoints[TPathPattern][TMethod]> : never;

export type OperationResult<
TMethod extends Method,
TPathPattern extends PathPattern
> = TMethod extends keyof Endpoints[TPathPattern] ? GetResult<Endpoints[TPathPattern][TMethod]> : never;

// ParamsFor and ResultFor - using MethodToPathPatternToParamsMap pattern from rest-typings
type MethodToPathPatternToParamsMap = {
[TMethod in Method]: {
[TPathPattern in keyof Endpoints]: TMethod extends keyof Endpoints[TPathPattern]
? Endpoints[TPathPattern][TMethod] extends infer TOperation
? TOperation extends (...args: any) => any
? Parameters<TOperation>[0]
: never
: never
: never;
};
};

type MethodToPathPatternToResultMap = {
[TMethod in Method]: {
[TPathPattern in keyof Endpoints]: TMethod extends keyof Endpoints[TPathPattern]
? Endpoints[TPathPattern][TMethod] extends infer TOperation
? TOperation extends (...args: any) => any
? ReturnType<TOperation>
: never
: never
: never;
};
};

export type ParamsFor<TMethod extends Method, TPathPattern extends PathPattern> =
MethodToPathPatternToParamsMap[TMethod][TPathPattern];

type SuccessResult<T> = T & { success: true };

type FailureResult<T, TStack = undefined, TErrorType = undefined, TErrorDetails = undefined> = {
Expand All @@ -87,8 +172,10 @@ type UnauthorizedResult<T> = {
error: T | 'unauthorized';
};

// ResultFor wraps the base result with success/error handling (SDK-specific)
// Uses MethodToPathPatternToResultMap pattern from rest-typings
export type ResultFor<TMethod extends Method, TPathPattern extends PathPattern> =
| SuccessResult<OperationResult<TMethod, TPathPattern>>
| SuccessResult<MethodToPathPatternToResultMap[TMethod][TPathPattern]>
| FailureResult<unknown, unknown, unknown, unknown>
| UnauthorizedResult<unknown>;

Expand Down
124 changes: 7 additions & 117 deletions app/definitions/rest/v1/channels.ts
Original file line number Diff line number Diff line change
@@ -1,119 +1,9 @@
import { type ITeam } from '../../ITeam';
import type { IMessageFromServer } from '../../IMessage';
import type { IServerRoom } from '../../IRoom';
import type { IUser } from '../../IUser';
import { type IGetRoomRoles } from '../../IRole';
import { type IServerAttachment } from '../../IAttachment';
import { type PaginatedRequest } from '../helpers/PaginatedRequest';
import type { ChannelsEndpoints as RestTypingsChannelsEndpoints } from '@rocket.chat/rest-typings';

export type ChannelsEndpoints = {
'channels.files': {
GET: (params: { roomId: IServerRoom['_id']; offset: number; sort: string | { uploadedAt: number } }) => {
files: IServerAttachment[];
count: number;
offset: number;
total: number;
};
};
'channels.members': {
GET: (params: {
roomId: IServerRoom['_id'];
offset?: number;
count?: number;
filter?: boolean;
status?: string[];
}) => PaginatedRequest<{
members: IUser[];
}>;
};
'channels.history': {
GET: (params: { roomId: string; count: number; latest?: string }) => {
messages: IMessageFromServer[];
};
};
'channels.archive': {
POST: (params: { roomId: string }) => void;
};
'channels.unarchive': {
POST: (params: { roomId: string }) => void;
};
'channels.create': {
POST: (params: {
name: string;
members: string[];
readOnly: boolean;
extraData: {
broadcast: boolean;
encrypted: boolean;
teamId?: string;
};
}) => {
group: Partial<IServerRoom>;
};
};
'channels.convertToTeam': {
POST: (params: { channelId: string } | { channelName: string } | { channelId: string; channelName: string }) => {
team: ITeam;
};
};
'channels.info': {
GET: (params: { roomId: string }) => { channel: IServerRoom };
};
'channels.counters': {
GET: (params: { roomId: string }) => {
joined: boolean;
members: number;
unreads: number;
unreadsFrom: Date;
msgs: number;
latest: Date;
userMentions: number;
};
};
'channels.join': {
POST: (params: { roomId: string; joinCode: string | null }) => { channel: IServerRoom };
};
'channels.close': {
POST: (params: { roomId: string }) => {};
};
'channels.kick': {
POST: (params: { roomId: string; userId: string }) => {};
};
'channels.delete': {
POST: (params: { roomId: string }) => {};
};
'channels.leave': {
POST: (params: { roomId: string }) => {};
};
'channels.addModerator': {
POST: (params: { roomId: string; userId: string }) => {};
};
'channels.removeModerator': {
POST: (params: { roomId: string; userId: string }) => {};
};
'channels.addOwner': {
POST: (params: { roomId: string; userId: string }) => {};
};
'channels.removeOwner': {
POST: (params: { roomId: string; userId: string }) => {};
};
'channels.addLeader': {
POST: (params: { roomId: string; userId: string }) => {};
};
'channels.removeLeader': {
POST: (params: { roomId: string; userId: string }) => {};
};
'channels.roles': {
GET: (params: { roomId: string }) => { roles: IGetRoomRoles[] };
};
'channels.messages': {
GET: (params: {
roomId: IServerRoom['_id'];
query: { 'mentions._id': { $in: string[] } } | { 'starred._id': { $in: string[] } } | { pinned: boolean };
offset: number;
sort: { ts: number };
}) => {
messages: IMessageFromServer[];
};
};
type RemoveV1Prefix<T> = T extends `/v1/${infer Rest}` ? Rest : T;

type AdaptChannelsEndpoints<T> = {
[K in keyof T as RemoveV1Prefix<K & string>]: T[K];
};

export type ChannelsEndpoints = AdaptChannelsEndpoints<RestTypingsChannelsEndpoints>;
Loading