geniebox-shared-lib
v2.6.2
Published
Shared NestJS library with gRPC clients
Readme
GenieBox Shared Library
A comprehensive shared NestJS library providing gRPC clients, interfaces, and utilities for the GenieBox microservices ecosystem. This library serves as the central communication layer between all GenieBox services.
Features
- gRPC Clients: Pre-configured clients for all GenieBox services
- TypeScript Interfaces: Fully typed interfaces for all service communications
- Protocol Buffers: Auto-generated from proto files with type safety
- NestJS Integration: Seamless integration with NestJS microservices
- Service Discovery: Centralized service client management
- Error Handling: Consistent error handling across all services
- Observable Support: RxJS observables for reactive programming
Architecture
Core Components
- gRPC Clients: Service-specific clients for communication
- Interfaces: TypeScript interfaces for all service methods
- Shared Module: NestJS module for easy integration
- Protocol Buffers: Auto-generated from proto definitions
- Type Definitions: Complete TypeScript type definitions
Supported Services
- User Service: User management and authentication
- Auth Service: Authentication and authorization
- AI Service: AI processing and machine learning
- OpenAI Service: OpenAI API integration
- Storage Service: File storage and management
- Event Service: Real-time event streaming
- Key Service: API key management
Installation
# Install from npm registry
npm install geniebox-shared-lib
# Or install from local development
npm install file:../libs/geniebox-sharedQuick Start
Basic Usage
import {
SharedModule,
UsersClient,
AuthClient,
AIClient
} from 'geniebox-shared-lib';
// Import in your NestJS module
@Module({
imports: [SharedModule],
// ... other module configuration
})
export class YourModule {}Using gRPC Clients
import { Injectable } from '@nestjs/common';
import { UsersClient, CreateUserRequest } from 'geniebox-shared-lib';
@Injectable()
export class YourService {
constructor(private readonly usersClient: UsersClient) {}
async createUser(userData: CreateUserRequest) {
return await this.usersClient.createUser(userData);
}
}Service-Specific Usage
User Service
import {
UsersClient,
CreateUserRequest,
UserResponse
} from 'geniebox-shared-lib';
// Create user
const createUserRequest: CreateUserRequest = {
email: '[email protected]',
password: 'securePassword',
firstName: 'John',
lastName: 'Doe'
};
const user: UserResponse = await usersClient.createUser(createUserRequest);Auth Service
import {
AuthClient,
LoginCredentials,
AuthResponse
} from 'geniebox-shared-lib';
// Login user
const credentials: LoginCredentials = {
email: '[email protected]',
password: 'securePassword',
rememberMe: true
};
const authResponse: AuthResponse = await authClient.login(credentials);AI Service
import {
AIClient,
AICallRequest,
AICallResponse
} from 'geniebox-shared-lib';
// Make AI request
const aiRequest: AICallRequest = {
endpoint: '/ai/chat',
payload: { message: 'Hello, AI!' },
priority: 'normal'
};
const aiResponse: AICallResponse = await aiClient.call(aiRequest);Storage Service
import {
StorageClient,
UploadRequest,
UploadResponse
} from 'geniebox-shared-lib';
// Upload file
const uploadRequest: UploadRequest = {
filename: 'document.pdf',
content: fileBuffer,
contentType: 'application/pdf'
};
const uploadResponse: UploadResponse = await storageClient.upload(uploadRequest);Event Service
import {
EventClient,
SubscribeRequest,
EventMessage
} from 'geniebox-shared-lib';
// Subscribe to events
const subscribeRequest: SubscribeRequest = {
eventType: 'user.created',
userId: 'user-123'
};
const eventStream = eventClient.subscribe(subscribeRequest);
eventStream.subscribe((event: EventMessage) => {
console.log('Received event:', event);
});Key Service
import {
KeyClient,
CreateKeyRequest,
KeyResponse
} from 'geniebox-shared-lib';
// Create API key
const createKeyRequest: CreateKeyRequest = {
name: 'My API Key',
permissions: ['read', 'write'],
expiresAt: new Date(Date.now() + 30 * 24 * 60 * 60 * 1000) // 30 days
};
const key: KeyResponse = await keyClient.createKey(createKeyRequest);Configuration
Environment Variables
The shared library uses environment variables for service configuration:
# User Service
USER_SERVICE_URL=grpc://user-service:50051
# Auth Service
AUTH_SERVICE_URL=grpc://auth-service:50052
# AI Service
AI_SERVICE_URL=grpc://ai-service:50053
# OpenAI Service
OPENAI_SERVICE_URL=grpc://openai-service:50054
# Storage Service
STORAGE_SERVICE_URL=grpc://storage-service:50055
# Event Service
EVENT_SERVICE_URL=grpc://event-service:50056
# Key Service
KEY_SERVICE_URL=grpc://key-service:50057Service Configuration
import { Module } from '@nestjs/common';
import { SharedModule } from 'geniebox-shared-lib';
@Module({
imports: [
SharedModule.forRoot({
userService: {
url: process.env.USER_SERVICE_URL || 'grpc://localhost:50051',
options: {
keepalive: true,
keepaliveTimeMs: 30000,
keepaliveTimeoutMs: 5000,
}
},
authService: {
url: process.env.AUTH_SERVICE_URL || 'grpc://localhost:50052',
options: {
keepalive: true,
keepaliveTimeMs: 30000,
keepaliveTimeoutMs: 5000,
}
},
// ... other services
})
],
})
export class AppModule {}Development
Prerequisites
- Node.js 18.x or higher
- npm 9.x or higher
- Protocol Buffers compiler (protoc)
- TypeScript 5.x
Setup
# Install dependencies
npm install
# Generate protobuf files
npm run proto:gen
# Build the library
npm run build
# Generate and build
npm run generateScripts
| Script | Description |
|--------|-------------|
| npm run build | Build TypeScript to JavaScript |
| npm run proto:gen | Generate TypeScript from proto files |
| npm run generate | Generate proto files and build |
| npm run prepublishOnly | Build before publishing |
Proto File Generation
The library automatically generates TypeScript interfaces and clients from Protocol Buffer definitions:
# Generate from proto files
npm run proto:gen
# This command:
# 1. Reads proto files from ../../protos/
# 2. Generates TypeScript interfaces in src/
# 3. Creates gRPC clients for each serviceAPI Reference
SharedModule
The main NestJS module that provides all gRPC clients.
@Module({
imports: [SharedModule],
providers: [YourService],
})
export class YourModule {}Service Clients
UsersClient
class UsersClient {
createUser(request: CreateUserRequest): Promise<UserResponse>
getUserById(request: GetByIdRequest): Promise<UserResponse>
updateUser(request: UpdateUserRequest): Promise<UserResponse>
deleteUser(request: GetByIdRequest): Promise<void>
findUserByEmail(request: FindByEmailRequest): Promise<UserResponse>
findUserByPhone(request: FindByPhoneRequest): Promise<UserResponse>
updateUserPersonal(request: UpdateUserPersonal): Promise<UserResponse>
updatePassword(request: UpdatePasswordRequest): Promise<void>
updateEmailVerification(request: UpdateEmailVerificationRequest): Promise<void>
getEmailVerificationStatus(request: GetEmailVerificationStatusRequest): Promise<EmailVerificationStatusResponse>
}AuthClient
class AuthClient {
login(request: LoginCredentials): Promise<AuthResponse>
register(request: RegisterCredentials): Promise<AuthResponse>
logout(request: LogoutRequest): Promise<void>
refresh(request: RefreshRequest): Promise<RefreshTokenResponse>
recover(request: RecoverRequest): Promise<void>
resetPassword(request: ResetPasswordRequest): Promise<void>
confirmEmail(request: ConfirmEmailRequest): Promise<ConfirmEmailResponse>
confirmEmailByCode(request: ConfirmEmailByCodeRequest): Promise<AuthResponse>
checkEmailVerified(request: CheckEmailVerifiedRequest): Promise<CheckEmailVerifiedResponse>
resendConfirmationCode(request: ResendConfirmationCodeRequest): Promise<void>
}AIClient
class AIClient {
call(request: AICallRequest): Promise<AICallResponse>
status(request: AIStatusRequest): Promise<AIStatusResponse>
result(request: AIResultRequest): Promise<AIResultResponse>
cancel(request: AICancelRequest): Promise<AICancelResponse>
stream(request: AIStreamRequest): Observable<AIStreamResponse>
}StorageClient
class StorageClient {
upload(request: UploadRequest): Promise<UploadResponse>
download(request: DownloadRequest): Promise<DownloadResponse>
delete(request: DeleteRequest): Promise<DeleteResponse>
}EventClient
class EventClient {
subscribe(request: SubscribeRequest): Observable<EventMessage>
publish(event: EventMessage): Promise<void>
}KeyClient
class KeyClient {
createKey(request: CreateKeyRequest): Promise<KeyResponse>
getKeyById(request: GetKeyByIdRequest): Promise<KeyResponse>
updateKey(request: UpdateKeyRequest): Promise<KeyResponse>
removeKey(request: RemoveKeyRequest): Promise<void>
getKeysByUser(request: GetKeysByUserRequest): Promise<KeysResponse>
}Error Handling
The library provides consistent error handling across all services:
import { RpcException } from '@nestjs/microservices';
try {
const user = await usersClient.createUser(request);
} catch (error) {
if (error instanceof RpcException) {
// Handle gRPC errors
console.error('gRPC Error:', error.message);
} else {
// Handle other errors
console.error('Unexpected error:', error);
}
}Type Safety
All interfaces are fully typed with TypeScript:
// Fully typed request/response objects
interface CreateUserRequest {
email: string;
password: string;
firstName: string;
lastName: string;
phone?: string;
dateOfBirth?: Date;
}
interface UserResponse {
id: string;
email: string;
firstName: string;
lastName: string;
phone?: string;
dateOfBirth?: Date;
createdAt: Date;
updatedAt: Date;
}Performance
Connection Pooling
The library uses gRPC connection pooling for optimal performance:
// Configure connection options
const clientOptions = {
keepalive: true,
keepaliveTimeMs: 30000,
keepaliveTimeoutMs: 5000,
keepalivePermitWithoutCalls: true,
maxReceiveMessageLength: 4 * 1024 * 1024, // 4MB
maxSendMessageLength: 4 * 1024 * 1024, // 4MB
};Caching
Service clients can be configured with caching:
// Enable client-side caching
const usersClient = new UsersClient(serviceUrl, {
...clientOptions,
cache: {
enabled: true,
ttl: 300000, // 5 minutes
}
});Testing
Unit Testing
import { Test, TestingModule } from '@nestjs/testing';
import { SharedModule, UsersClient } from 'geniebox-shared-lib';
describe('YourService', () => {
let service: YourService;
let usersClient: UsersClient;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
imports: [SharedModule],
providers: [YourService],
}).compile();
service = module.get<YourService>(YourService);
usersClient = module.get<UsersClient>(UsersClient);
});
it('should create user', async () => {
const mockUser = { id: '1', email: '[email protected]' };
jest.spyOn(usersClient, 'createUser').mockResolvedValue(mockUser);
const result = await service.createUser({ email: '[email protected]' });
expect(result).toEqual(mockUser);
});
});Integration Testing
import { Test, TestingModule } from '@nestjs/testing';
import { SharedModule } from 'geniebox-shared-lib';
describe('Integration Tests', () => {
let app: INestApplication;
beforeAll(async () => {
const moduleFixture: TestingModule = await Test.createTestingModule({
imports: [SharedModule],
}).compile();
app = moduleFixture.createNestApplication();
await app.init();
});
afterAll(async () => {
await app.close();
});
it('should connect to services', async () => {
// Test actual service connections
});
});Troubleshooting
Common Issues
Connection Errors
# Check service URLs
echo $USER_SERVICE_URL
echo $AUTH_SERVICE_URL
# Test gRPC connectivity
grpcurl -plaintext localhost:50051 listType Errors
# Regenerate types from proto files
npm run proto:gen
# Rebuild the library
npm run buildImport Errors
// Ensure correct imports
import { UsersClient, CreateUserRequest } from 'geniebox-shared-lib';
// Not from individual files
// import { UsersClient } from 'geniebox-shared-lib/src/user.client';Debug Mode
// Enable gRPC debug logging
process.env.GRPC_VERBOSITY = 'DEBUG';
process.env.GRPC_TRACE = 'all';
// Enable client debug mode
const client = new UsersClient(serviceUrl, {
...options,
debug: true,
});Contributing
Development Setup
- Fork the repository
- Create a feature branch
- Install dependencies:
npm install - Make your changes
- Run tests:
npm test - Submit a pull request
Code Standards
- TypeScript: Strict type checking enabled
- ESLint: Code linting with TypeScript rules
- Prettier: Code formatting
- Testing: All new code must include tests
- Documentation: JSDoc comments for public APIs
Adding New Services
- Add proto file to
../../protos/ - Run
npm run proto:gento generate interfaces - Create client class in
src/ - Export from
src/index.ts - Update
SharedModuleto include new client - Add tests for new client
License
This project is licensed under the ISC License - see the package.json file for details.
Support
For support and questions:
- Issues: Create a GitHub issue
- Documentation: Check this README and inline JSDoc
- Logs: Review gRPC connection logs
- Debug: Enable debug mode for detailed logging
Version: 2.0.0
Last Updated: January 2024
Maintainer: GenieBox Team
