From ac608ded46705bb40478ac96af11f1b23131e3b7 Mon Sep 17 00:00:00 2001 From: Marco Beretta <81851188+berry-13@users.noreply.github.com> Date: Sat, 23 Aug 2025 06:18:31 +0200 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20feat:=20Add=20cursor=20pagination?= =?UTF-8?q?=20utilities=20and=20refine=20user/group/role=20types=20in=20`@?= =?UTF-8?q?librechat/data-schemas`=20(#9218)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: Add pagination interfaces and update user and group types for better data handling * fix: Update data-schemas version to 0.0.19 --- package-lock.json | 2 +- packages/data-schemas/package.json | 2 +- packages/data-schemas/src/common/index.ts | 1 + .../data-schemas/src/common/pagination.ts | 17 +++++++++ packages/data-schemas/src/methods/user.ts | 6 +-- packages/data-schemas/src/schema/group.ts | 1 + packages/data-schemas/src/types/group.ts | 36 ++++++++++++++---- packages/data-schemas/src/types/role.ts | 25 +++++++++++- packages/data-schemas/src/types/user.ts | 38 +++++++++++++++---- 9 files changed, 108 insertions(+), 20 deletions(-) create mode 100644 packages/data-schemas/src/common/pagination.ts diff --git a/package-lock.json b/package-lock.json index 502151b27..8fbb81d95 100644 --- a/package-lock.json +++ b/package-lock.json @@ -51876,7 +51876,7 @@ }, "packages/data-schemas": { "name": "@librechat/data-schemas", - "version": "0.0.18", + "version": "0.0.19", "license": "MIT", "devDependencies": { "@rollup/plugin-alias": "^5.1.0", diff --git a/packages/data-schemas/package.json b/packages/data-schemas/package.json index 93bb9fd0c..0001b60a4 100644 --- a/packages/data-schemas/package.json +++ b/packages/data-schemas/package.json @@ -1,6 +1,6 @@ { "name": "@librechat/data-schemas", - "version": "0.0.18", + "version": "0.0.19", "description": "Mongoose schemas and models for LibreChat", "type": "module", "main": "dist/index.cjs", diff --git a/packages/data-schemas/src/common/index.ts b/packages/data-schemas/src/common/index.ts index bdd505d9c..e990985eb 100644 --- a/packages/data-schemas/src/common/index.ts +++ b/packages/data-schemas/src/common/index.ts @@ -1 +1,2 @@ export * from './enum'; +export * from './pagination'; diff --git a/packages/data-schemas/src/common/pagination.ts b/packages/data-schemas/src/common/pagination.ts new file mode 100644 index 000000000..711e78a68 --- /dev/null +++ b/packages/data-schemas/src/common/pagination.ts @@ -0,0 +1,17 @@ +export interface CursorPaginationParams { + limit?: number; + cursor?: string; + sortBy?: string; + sortOrder?: 'asc' | 'desc'; +} + +export interface CursorPaginationResponse { + data: T[]; + pagination: { + hasNextPage: boolean; + hasPreviousPage: boolean; + nextCursor?: string; + previousCursor?: string; + totalCount?: number; + }; +} diff --git a/packages/data-schemas/src/methods/user.ts b/packages/data-schemas/src/methods/user.ts index b1f4c82ce..83a433da7 100644 --- a/packages/data-schemas/src/methods/user.ts +++ b/packages/data-schemas/src/methods/user.ts @@ -1,5 +1,5 @@ import mongoose, { FilterQuery } from 'mongoose'; -import type { IUser, BalanceConfig, UserCreateData, UserUpdateResult } from '~/types'; +import type { IUser, BalanceConfig, CreateUserRequest, UserDeleteResult } from '~/types'; import { signPayload } from '~/crypto'; /** Factory function that takes mongoose instance and returns the methods */ @@ -31,7 +31,7 @@ export function createUserMethods(mongoose: typeof import('mongoose')) { * Creates a new user, optionally with a TTL of 1 week. */ async function createUser( - data: UserCreateData, + data: CreateUserRequest, balanceConfig?: BalanceConfig, disableTTL: boolean = true, returnUser: boolean = false, @@ -123,7 +123,7 @@ export function createUserMethods(mongoose: typeof import('mongoose')) { /** * Delete a user by their unique ID. */ - async function deleteUserById(userId: string): Promise { + async function deleteUserById(userId: string): Promise { try { const User = mongoose.models.User; const result = await User.deleteOne({ _id: userId }); diff --git a/packages/data-schemas/src/schema/group.ts b/packages/data-schemas/src/schema/group.ts index 7de514b77..55cb54e8b 100644 --- a/packages/data-schemas/src/schema/group.ts +++ b/packages/data-schemas/src/schema/group.ts @@ -24,6 +24,7 @@ const groupSchema = new Schema( memberIds: [ { type: String, + required: false, }, ], source: { diff --git a/packages/data-schemas/src/types/group.ts b/packages/data-schemas/src/types/group.ts index 30c067664..e0e622aca 100644 --- a/packages/data-schemas/src/types/group.ts +++ b/packages/data-schemas/src/types/group.ts @@ -1,22 +1,44 @@ import type { Document, Types } from 'mongoose'; +import { CursorPaginationParams } from '~/common'; export interface IGroup extends Document { _id: Types.ObjectId; - /** The name of the group */ name: string; - /** Optional description of the group */ description?: string; - /** Optional email address for the group */ email?: string; - /** Optional avatar URL for the group */ avatar?: string; /** Array of member IDs (stores idOnTheSource values, not ObjectIds) */ - memberIds: string[]; - /** The source of the group ('local' or 'entra') */ + memberIds?: string[]; source: 'local' | 'entra'; /** External ID (e.g., Entra ID) - required for non-local sources */ idOnTheSource?: string; - /** Timestamps */ createdAt?: Date; updatedAt?: Date; } + +export interface CreateGroupRequest { + name: string; + description?: string; + email?: string; + avatar?: string; + memberIds?: string[]; + source: 'local' | 'entra'; + idOnTheSource?: string; +} + +export interface UpdateGroupRequest { + name?: string; + description?: string; + email?: string; + avatar?: string; + memberIds?: string[]; + source?: 'local' | 'entra' | 'ldap'; + idOnTheSource?: string; +} + +export interface GroupFilterOptions extends CursorPaginationParams { + // Includes email, name and description + search?: string; + source?: 'local' | 'entra' | 'ldap'; + hasMember?: string; +} diff --git a/packages/data-schemas/src/types/role.ts b/packages/data-schemas/src/types/role.ts index 281b8b423..5441847b9 100644 --- a/packages/data-schemas/src/types/role.ts +++ b/packages/data-schemas/src/types/role.ts @@ -1,5 +1,6 @@ -import { Document } from 'mongoose'; import { PermissionTypes, Permissions } from 'librechat-data-provider'; +import type { Document } from 'mongoose'; +import { CursorPaginationParams } from '~/common'; export interface IRole extends Document { name: string; @@ -48,3 +49,25 @@ export interface IRole extends Document { }; }; } + +export type RolePermissions = IRole['permissions']; +type DeepPartial = { + [K in keyof T]?: T[K] extends object ? DeepPartial : T[K]; +}; +export type RolePermissionsInput = DeepPartial; + +export interface CreateRoleRequest { + name: string; + permissions: RolePermissionsInput; +} + +export interface UpdateRoleRequest { + name?: string; + permissions?: RolePermissionsInput; +} + +export interface RoleFilterOptions extends CursorPaginationParams { + // Includes role name + search?: string; + hasPermission?: string; +} diff --git a/packages/data-schemas/src/types/user.ts b/packages/data-schemas/src/types/user.ts index 6d2742229..ad86172d8 100644 --- a/packages/data-schemas/src/types/user.ts +++ b/packages/data-schemas/src/types/user.ts @@ -1,4 +1,5 @@ -import { Document, Types } from 'mongoose'; +import type { Document, Types } from 'mongoose'; +import { CursorPaginationParams } from '~/common'; export interface IUser extends Document { name?: string; @@ -48,18 +49,39 @@ export interface BalanceConfig { refillAmount?: number; } -export interface UserCreateData extends Partial { +export interface CreateUserRequest extends Partial { email: string; } -export interface UserUpdateResult { +export interface UpdateUserRequest { + name?: string; + username?: string; + email?: string; + role?: string; + emailVerified?: boolean; + avatar?: string; + plugins?: string[]; + twoFactorEnabled?: boolean; + termsAccepted?: boolean; + personalization?: { + memories?: boolean; + }; +} + +export interface UserDeleteResult { deletedCount: number; message: string; } -export interface UserSearchCriteria { - email?: string; - username?: string; +export interface UserFilterOptions extends CursorPaginationParams { + _id?: Types.ObjectId | string; + // Includes email, username and name + search?: string; + role?: string; + emailVerified?: boolean; + provider?: string; + twoFactorEnabled?: boolean; + // External IDs googleId?: string; facebookId?: string; openidId?: string; @@ -68,7 +90,9 @@ export interface UserSearchCriteria { githubId?: string; discordId?: string; appleId?: string; - _id?: Types.ObjectId | string; + // Date filters + createdAfter?: string; + createdBefore?: string; } export interface UserQueryOptions {