From 6543e8052539bc7ac3092216c66e5613a62b44ca Mon Sep 17 00:00:00 2001 From: Juan Diego Moreno Upegui Date: Fri, 26 Sep 2025 14:02:30 -0500 Subject: [PATCH] first commit --- README.md | 299 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 299 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..7ebd759 --- /dev/null +++ b/README.md @@ -0,0 +1,299 @@ +# Tryton RPC Client for JavaScript + +JavaScript implementation of a Tryton ERP RPC client, based on the Python `sabatron-tryton-rpc-client` package. This client allows you to connect to Tryton servers via JSON-RPC and perform operations programmatically. + +## Features + +- ✅ **Full RPC Support** - Complete implementation of Tryton's JSON-RPC protocol +- ✅ **Connection Pooling** - Efficient connection reuse with configurable pool size +- ✅ **Smart Caching** - LRU cache with expiration support for improved performance +- ✅ **Session Management** - Automatic session handling and authentication +- ✅ **Type Safety** - Proper serialization/deserialization of Tryton data types +- ✅ **Error Handling** - Comprehensive error handling with retry logic +- ✅ **SSL/TLS Support** - Secure connections with certificate validation +- ✅ **Helper Methods** - Convenient methods for common operations (CRUD) + +## Installation + +```bash +npm install tryton-rpc-client-js +``` + +## Quick Start + +```javascript +const { TrytonClient } = require("tryton-rpc-client-js"); + +async function main() { + // Create client instance + const client = new TrytonClient({ + hostname: "localhost", + database: "tryton", + username: "admin", + password: "admin", + port: 8000, + language: "en", + }); + + try { + // Connect to server + await client.connect(); + console.log("Connected successfully!"); + + // Read a party record + const parties = await client.read( + "party.party", + [1], + ["id", "name", "code"] + ); + console.log("Party:", parties[0]); + + // Create a new party + const newParties = await client.create("party.party", [ + { name: "From JavaScript" }, + ]); + console.log("Created party ID:", newParties[0]); + } catch (error) { + console.error("Error:", error.message); + } finally { + client.close(); + } +} + +main(); +``` + +## API Reference + +### Constructor + +```javascript +const client = new TrytonClient({ + hostname: "localhost", // Server hostname + database: "tryton", // Database name + username: "admin", // Username + password: "admin", // Password + port: 8000, // Server port (default: 8000) + language: "en", // Language code (default: 'en') + options: { + // Additional options + verbose: false, // Enable verbose logging + cache: true, // Enable caching (default: true) + keepMax: 4, // Max pooled connections (default: 4) + connectTimeout: 5000, // Connection timeout in ms + timeout: 30000, // Request timeout in ms + }, +}); +``` + +### Methods + +#### Connection Management + +```javascript +// Connect to server +await client.connect(); + +// Check connection status +console.log(client.isConnected); // true/false + +// Get connection info +console.log(client.getConfig()); + +// Close connection +client.close(); +``` + +#### RPC Calls + +```javascript +// Generic RPC call +const result = await client.call("method.name", [arg1, arg2, arg3]); + +// Multiple calls in sequence +const results = await client.callMultiple([ + { method: "model.party.party.read", args: [[1], ["name"]] }, + { method: "model.company.company.read", args: [[1], ["name"]] }, +]); + +// Multiple calls in parallel +const results = await client.callParallel([ + { method: "model.party.party.read", args: [[1], ["name"]] }, + { method: "model.company.company.read", args: [[1], ["name"]] }, +]); +``` + +#### CRUD Operations + +```javascript +// Create records +const ids = await client.create("party.party", [ + { name: "John Doe", code: "JOHN001" }, + { name: "Jane Smith", code: "JANE001" }, +]); + +// Read records +const records = await client.read( + "party.party", + [1, 2], + ["id", "name", "code"] +); + +// Update records +await client.write("party.party", [1], { name: "Updated Name" }); + +// Delete records +await client.delete("party.party", [1]); +``` + +#### Search Operations + +```javascript +// Search for record IDs +const ids = await client.search("party.party", [["name", "like", "John%"]]); + +// Search and read in one call +const records = await client.searchRead( + "party.party", + [["active", "=", true]], + ["id", "name", "code"], + 0, // offset + 10, // limit + ["name"] // order +); + +// Count records +const count = await client.searchCount("party.party", [["active", "=", true]]); +``` + +#### Server Information + +```javascript +// Get server version +const version = await client.getVersion(); + +// List databases +const databases = await client.listDatabases(); + +// Get database info +const dbInfo = await client.getDatabaseInfo(); +``` + +#### Cache Management + +```javascript +// Clear all cache +client.clearCache(); + +// Clear cache for specific prefix +client.clearCache("model.party.party"); +``` + +## Advanced Usage + +### Custom Options + +```javascript +const client = new TrytonClient({ + hostname: "localhost", + database: "tryton", + username: "admin", + password: "admin", + options: { + verbose: true, // Enable request/response logging + cache: true, // Enable response caching + keepMax: 8, // Keep up to 8 pooled connections + connectTimeout: 10000, // 10 second connection timeout + timeout: 60000, // 60 second request timeout + }, +}); +``` + +### Error Handling + +```javascript +const { TrytonClient, Fault, ProtocolError } = require("tryton-rpc-client-js"); + +try { + await client.call("invalid.method", []); +} catch (error) { + if (error instanceof Fault) { + console.log("RPC Fault:", error.faultCode, error.faultString); + } else if (error instanceof ProtocolError) { + console.log("Protocol Error:", error.errcode, error.errmsg); + } else { + console.log("Other Error:", error.message); + } +} +``` + +### Connection Cloning + +```javascript +// Clone client with same configuration +const client2 = client.clone(); +await client2.connect(); + +// Both clients can work independently +const result1 = await client.read("party.party", [1], ["name"]); +const result2 = await client2.read("company.company", [1], ["name"]); +``` + +## Data Types + +The client automatically handles Tryton's special data types: + +- **Date/DateTime** - JavaScript `Date` objects +- **Decimal** - JavaScript `number` (with precision handling) +- **Bytes** - Node.js `Buffer` objects +- **TimeDelta** - Number of seconds + +## Error Types + +- **`Fault`** - RPC errors from server +- **`ProtocolError`** - HTTP/connection errors +- **`ResponseError`** - Invalid response format + +## Requirements + +- Node.js >= 12.0.0 +- No external dependencies (uses only Node.js built-in modules) + +## Compatibility + +This client is compatible with: + +- Tryton 6.x +- Tryton 7.x +- Any Tryton server supporting JSON-RPC + +## License + +GNU General Public License v3.0 (GPL-3.0) + +## Contributing + +1. Fork the repository +2. Create a feature branch +3. Make your changes +4. Add tests if applicable +5. Submit a pull request + +## Support + +For issues and questions: + +- Open an issue on GitHub +- Check the Tryton documentation +- Review the examples in the `examples/` directory + +## Changelog + +### v1.0.0 + +- Initial release +- Full RPC implementation +- Connection pooling +- Smart caching +- Helper methods for CRUD operations +- Comprehensive error handling