UNPKG

@gp_jcisneros/aws-utils

Version:

AWS SDK utilities for GreenPay microservices

595 lines (430 loc) 17.5 kB
# @gp_jcisneros/aws-utils 🚀 **AWS SDK utilities for GreenPay microservices** with standardized error handling and modern AWS SDK v3 support. This NPM package provides easy-to-use utilities for common AWS operations including **Lambda**, **S3**, **SQS**, **DynamoDB**, and **Cognito** with **standardized error handling** using `@gp_jcisneros/errors`. ## ✨ Features - 🔧 **AWS SDK v3 Support** - Built with the latest AWS SDK - 🛡️ **Standardized Error Handling** - Consistent error format across all utilities - 📦 **Modular Design** - Import only what you need - 🧪 **Comprehensive Testing** - Full test coverage - 📚 **TypeScript Ready** - Full JSDoc documentation - ⚡ **Performance Optimized** - Efficient AWS operations ## 📦 Installation ```bash npm install @gp_jcisneros/aws-utils ``` ## 🚀 Quick Start ```javascript const { DynamoUtils, S3Utils, LambdaUtils, SQSUtils, CognitoUtils } = require('@gp_jcisneros/aws-utils'); // DynamoDB - Get an item const user = await DynamoUtils.getItem('users', { id: '123' }); // S3 - Upload a file await S3Utils.uploadFile('my-bucket', 'data.json', Buffer.from('{"key": "value"}')); // Lambda - Invoke a function const result = await LambdaUtils.invokeLambda('my-function', { data: 'test' }); // SQS - Send a message await SQSUtils.sendMessage('https://sqs.region.amazonaws.com/queue', 'Hello World!'); // Cognito - User login const authResult = await CognitoUtils.login('username', 'password', poolData); ``` ## 📖 Usage Examples ### 🔧 Lambda Operations ```javascript const { LambdaUtils, invokeLambda } = require('@gp_jcisneros/aws-utils'); // Synchronous invocation const result = await LambdaUtils.invokeLambda('my-function', { data: 'test' }); // Asynchronous invocation await LambdaUtils.invokeLambdaAsync('my-function', { data: 'test' }); // Get function configuration const config = await LambdaUtils.getFunctionConfiguration('my-function'); // Using convenience function const result = await invokeLambda('my-function', { data: 'test' }); ``` ### ☁️ S3 Operations ```javascript const { S3Utils, uploadToS3 } = require('@gp_jcisneros/aws-utils'); // Upload a file const result = await S3Utils.uploadFile('my-bucket', 'path/to/file.json', fileData); // Upload JSON data const result = await S3Utils.uploadJson('my-bucket', 'data.json', { key: 'value' }); // Download a file const file = await S3Utils.downloadFile('my-bucket', 'path/to/file.json'); // Download and parse JSON const data = await S3Utils.downloadJson('my-bucket', 'data.json'); // Delete a file await S3Utils.deleteFile('my-bucket', 'path/to/file.json'); // Using convenience function await uploadToS3('my-bucket', 'data.json', { key: 'value' }); ``` ### 📨 SQS Operations ```javascript const { SQSUtils, sendToSQS } = require('@gp_jcisneros/aws-utils'); // Send a message const result = await SQSUtils.sendMessage('https://sqs.region.amazonaws.com/queue-url', { data: 'test' }); // Send JSON message const result = await SQSUtils.sendJsonMessage('queue-url', { key: 'value' }); // Receive messages const messages = await SQSUtils.receiveMessages('queue-url'); // Process messages with handler const results = await SQSUtils.processMessages('queue-url', async (message) => { console.log('Processing:', message.Body); return { processed: true }; }); // Delete a message await SQSUtils.deleteMessage('queue-url', message.ReceiptHandle); // Using convenience function await sendToSQS('queue-url', { key: 'value' }); ``` ### 🗄️ DynamoDB Operations ```javascript const { DynamoUtils, getFromDynamo } = require('@gp_jcisneros/aws-utils'); // Get an item const item = await DynamoUtils.getItem('my-table', { id: '123' }); // Put an item const result = await DynamoUtils.putItem('my-table', { id: '123', data: 'value' }); // Update an item const result = await DynamoUtils.updateItem( 'my-table', { id: '123' }, 'SET #data = :data', { ':data': 'new-value' }, { '#data': 'data' } ); // Delete an item await DynamoUtils.deleteItem('my-table', { id: '123' }); // Query items const items = await DynamoUtils.queryItems( 'my-table', 'id = :id', { ':id': '123' } ); // Scan items const items = await DynamoUtils.scanItems('my-table'); // Batch get items const items = await DynamoUtils.batchGetItems('my-table', [ { id: '123' }, { id: '456' } ]); // Using convenience function const item = await getFromDynamo('my-table', { id: '123' }); ``` ### 🔐 Cognito Operations ```javascript const { CognitoUtils, login } = require('@gp_jcisneros/aws-utils'); // Pool data configuration const poolData = { ClientId: 'your-client-id', UserPoolId: 'your-user-pool-id', SecretHash: 'your-secret-hash' }; // User authentication const loginResult = await CognitoUtils.login('username', 'password', poolData); // User registration const signUpResult = await CognitoUtils.signUp('username', 'password', poolData, [ { Name: 'email', Value: 'user@example.com' }, { Name: 'given_name', Value: 'John' } ]); // Verify user with confirmation code await CognitoUtils.verify('username', '123456', poolData); // Forgot password flow await CognitoUtils.forgotPassword('username', poolData); // Confirm new password await CognitoUtils.confirmPassword('username', '123456', 'newPassword', poolData); // Refresh tokens const refreshResult = await CognitoUtils.refreshToken('username', 'refreshToken', poolData); // Revoke tokens await CognitoUtils.revokeToken('accessToken', poolData); // Change password (requires access token) await CognitoUtils.changePassword('accessToken', 'oldPassword', 'newPassword'); // Admin operations - Add user to group await CognitoUtils.adminAddUserToGroup('username', 'admin', poolData); // Admin operations - Remove user from group await CognitoUtils.adminRemoveUserFromGroup('username', 'admin', poolData); // Group management - Create group await CognitoUtils.addGroupPool('admin', 'Administrator group', poolData); // Group management - Delete group await CognitoUtils.deleteGroupPool('admin', poolData); // User management - Delete user await CognitoUtils.deleteUserPool('username', poolData); // Using convenience functions const result = await login('username', 'password', poolData); ``` ## 🛡️ Error Handling All utilities use **standardized error handling** with `@gp_jcisneros/errors`. Each error includes: - **`errorCode`**: Specific error code for the operation - **`description`**: Detailed error description - **`integration`**: Service name (aws-utils) - **`statusCode`**: Appropriate HTTP status code - **`timestamp`**: Error timestamp - **`type`**: Error type for categorization ### 🚨 Error Types ```javascript const { AWSError, DatabaseError, IntegrationError } = require('@gp_jcisneros/errors'); // AWS Errors (statusCode: 500) const awsError = new AWSError('AWS service error', 'S3', 'UPLOAD_ERROR'); // { // errorCode: 'AWS_S3', // description: 'AWS service error', // integration: 'aws-service', // statusCode: 500, // service: 'S3', // awsErrorCode: 'UPLOAD_ERROR' // } // Database Errors (statusCode: 500) const dbError = new DatabaseError('Database operation failed', 'GET', 'users'); // { // errorCode: 'DB_GET', // description: 'Database operation failed', // integration: 'database-service', // statusCode: 500, // operation: 'GET', // table: 'users' // } // Integration Errors (statusCode: 502) const integrationError = new IntegrationError('External service error', 'SERVICE_ERROR', 'external-service', { context: 'data' }); // { // errorCode: 'SERVICE_ERROR', // description: 'External service error', // integration: 'external-service', // statusCode: 502, // integrationCode: 'SERVICE_ERROR', // integrationName: 'external-service', // context: { context: 'data' } // } ``` ### 🔍 Error Handling Example ```javascript const { DynamoUtils } = require('@gp_jcisneros/aws-utils'); const { DatabaseError, AWSError } = require('@gp_jcisneros/errors'); try { const item = await DynamoUtils.getItem('users', { id: '123' }); return item; } catch (error) { if (error instanceof DatabaseError) { console.log('Database error:', { errorCode: error.errorCode, // 'DB_GET' description: error.description, // 'DynamoDB get failed for users: ...' integration: error.integration, // 'database-service' operation: error.operation, // 'GET' table: error.table, // 'users' statusCode: error.statusCode // 500 }); } else if (error instanceof AWSError) { console.log('AWS error:', { service: error.service, // 'DYNAMODB' awsErrorCode: error.awsErrorCode, // 'ERROR_CODE' statusCode: error.statusCode // 500 }); } throw error; } ``` ## 📚 API Reference ### LambdaUtils #### `invokeLambda(functionName, payload, invocationType)` Invokes a Lambda function synchronously or asynchronously. **Parameters:** - `functionName` (string): Name of the Lambda function - `payload` (object): Data to send to the function - `invocationType` (string): 'RequestResponse' or 'Event' (default: 'RequestResponse') **Returns:** Promise with Lambda response #### `invokeLambdaAsync(functionName, payload)` Invokes a Lambda function asynchronously. #### `getFunctionConfiguration(functionName)` Gets the configuration of a Lambda function. ### S3Utils #### `uploadFile(bucketName, key, data, contentType)` Uploads a file to S3. **Parameters:** - `bucketName` (string): Name of the S3 bucket - `key` (string): Object key (file path) - `data` (Buffer|string): File data - `contentType` (string): Content type (default: 'application/json') **Returns:** Promise with upload result #### `downloadFile(bucketName, key)` Downloads a file from S3. #### `deleteFile(bucketName, key)` Deletes a file from S3. #### `uploadJson(bucketName, key, jsonData)` Uploads JSON data to S3. #### `downloadJson(bucketName, key)` Downloads and parses JSON from S3. ### SQSUtils #### `sendMessage(queueUrl, messageBody, options)` Sends a message to an SQS queue. **Parameters:** - `queueUrl` (string): URL of the SQS queue - `messageBody` (object|string): Message to send - `options` (object): Additional options (delaySeconds, messageAttributes, etc.) **Returns:** Promise with send result #### `receiveMessages(queueUrl, options)` Receives messages from an SQS queue. #### `deleteMessage(queueUrl, receiptHandle)` Deletes a message from an SQS queue. #### `sendJsonMessage(queueUrl, jsonData, options)` Sends JSON data to an SQS queue. #### `processMessages(queueUrl, messageHandler, options)` Processes messages from an SQS queue with a handler function. ### DynamoUtils #### `getItem(tableName, key)` Gets an item from DynamoDB. **Parameters:** - `tableName` (string): Name of the DynamoDB table - `key` (object): Primary key of the item **Returns:** Promise with item or null #### `putItem(tableName, item)` Puts an item in DynamoDB. #### `updateItem(tableName, key, updateExpression, expressionAttributeValues, expressionAttributeNames)` Updates an item in DynamoDB. #### `deleteItem(tableName, key)` Deletes an item from DynamoDB. #### `queryItems(tableName, keyConditionExpression, expressionAttributeValues, expressionAttributeNames, indexName)` Queries items from DynamoDB. #### `scanItems(tableName, filterExpression, expressionAttributeValues, expressionAttributeNames)` Scans items from DynamoDB. #### `batchGetItems(tableName, keys)` Batch gets items from DynamoDB. ### CognitoUtils #### `login(username, password, poolData)` Authenticates a user with username and password. **Parameters:** - `username` (string): User's username or email - `password` (string): User's password - `poolData` (object): Cognito pool configuration with ClientId, UserPoolId, and SecretHash **Returns:** Promise with authentication result including tokens #### `signUp(username, password, poolData, userAttributes)` Registers a new user in Cognito. **Parameters:** - `username` (string): Desired username - `password` (string): User's password - `poolData` (object): Cognito pool configuration - `userAttributes` (array): User attributes (email, given_name, etc.) **Returns:** Promise with registration result #### `verify(username, code, poolData)` Verifies a user's email/phone with confirmation code. #### `forgotPassword(username, poolData)` Initiates forgot password flow. #### `confirmPassword(username, code, newPassword, poolData)` Confirms new password with verification code. #### `refreshToken(username, refreshToken, poolData)` Refreshes access tokens using refresh token. #### `revokeToken(token, poolData)` Revokes access or refresh tokens. #### `changePassword(accessToken, oldPassword, newPassword)` Changes user password (requires valid access token). #### `adminAddUserToGroup(username, groupName, poolData)` Adds user to a Cognito group (admin operation). #### `adminRemoveUserFromGroup(username, groupName, poolData)` Removes user from a Cognito group (admin operation). #### `addGroupPool(groupName, description, poolData)` Creates a new group in the user pool. #### `deleteGroupPool(groupName, poolData)` Deletes a group from the user pool. #### `deleteUserPool(username, poolData)` Deletes a user from the user pool (admin operation). ## 🧪 Testing ```bash # Run all tests npm test # Run tests with coverage npm run test:coverage # Run tests in watch mode npm run test:watch # Run specific test file npm test -- tests/DynamoUtils.test.js ``` ## 🛠️ Development ```bash # Install dependencies npm install # Run linting npm run lint # Fix linting issues npm run lint:fix # Format code npm run format # Run tests before commit npm run pre-commit ``` ## 🚀 Despliegue Local ### Configuración del Token NPM Para publicar el paquete localmente, primero configura tu token de npm: ```bash # Configurar token de npm (reemplaza TU_TOKEN_AQUI con tu token real) npm config set //registry.npmjs.org/:_authToken=TU_TOKEN_AQUI # Verificar que estás autenticado npm whoami ``` ### Pasos para Publicar ```bash # 1. Instalar dependencias npm install # 2. Ejecutar tests npm test # 3. Ejecutar linting npm run lint # 4. Verificar qué se va a publicar npm pack # 5. Publicar el paquete npm publish --access public ``` ### Verificar la Publicación ```bash # Verificar que el paquete se publicó correctamente npm info @gp_jcisneros/aws-utils # Instalar el paquete para probar npm install @gp_jcisneros/aws-utils ``` ### Actualizar Versión ```bash # Incrementar versión patch (1.0.0 -> 1.0.1) npm version patch # Incrementar versión minor (1.0.0 -> 1.1.0) npm version minor # Incrementar versión major (1.0.0 -> 2.0.0) npm version major # Publicar nueva versión npm publish ``` ## 📦 Dependencies - **@aws-sdk/client-lambda**: ^3.500.0 - **@aws-sdk/client-s3**: ^3.500.0 - **@aws-sdk/client-sqs**: ^3.500.0 - **@aws-sdk/lib-dynamodb**: ^3.500.0 - **@aws-sdk/client-cognito-identity-provider**: ^3.856.0 - **@gp_jcisneros/errors**: ^1.0.1-dev ## 🤝 Contributing 1. Fork the repository 2. Create a feature branch (`git checkout -b feature/amazing-feature`) 3. Commit your changes (`git commit -m 'Add some amazing feature'`) 4. Push to the branch (`git push origin feature/amazing-feature`) 5. Open a Pull Request ## 📄 License This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details. ## 📋 Changelog ### v1.0.13-dev - ✅ **Added CognitoUtils** - Complete AWS Cognito integration - ✅ **User authentication** - Login, signup, verification flows - ✅ **Password management** - Forgot password, change password, confirm password - ✅ **Token management** - Refresh tokens, revoke tokens - ✅ **Admin operations** - User group management, user deletion - ✅ **Group management** - Create and delete user pool groups - ✅ **Comprehensive error handling** for all Cognito operations - ✅ **Static methods** for convenient usage - ✅ **Full test coverage** for CognitoUtils - ✅ **Updated documentation** with Cognito examples and API reference ### v1.0.1-dev - ✅ **Updated error handling** to use new `@gp_jcisneros/errors` constructor - ✅ **Improved error messages** with better context and details - ✅ **Enhanced integration errors** with service-specific information - ✅ **Updated all utilities** to use standardized error handling - ✅ **Better error codes** for different AWS operations - ✅ **Consistent error format** across all utilities - ✅ **Removed singleton pattern** for better flexibility - ✅ **Enhanced test coverage** with comprehensive error testing - ✅ **Updated documentation** with new error handling examples ### v1.0.0 - 🎉 Initial release - ✨ AWS SDK v3 support - 🛡️ Standardized error handling - 📦 Modular utility classes - 🧪 Comprehensive test suite