Compare commits

13 Commits

Author SHA1 Message Date
97cb5078e2 Try fix error with time zone 2025-11-19 12:09:00 -05:00
f2e56c99aa Cleared console.log in jsonrpc.ts file 2025-11-12 15:22:47 -05:00
9741568f12 Cleared console.logs used in different files 2025-11-12 15:16:27 -05:00
fa04b7e9da added feature that allows client to work directly with ip and ports 2025-11-04 14:53:44 -05:00
470f510701 fix: use valid RPC method for session validation 2025-10-15 15:46:42 -05:00
da83e18aa2 fix: use valid RPC method for session validation 2025-10-15 15:45:30 -05:00
09d26efa0d debug: add detailed logs for session restoration 2025-10-15 15:43:21 -05:00
c2f3454a38 fix: update transport session when restoring session 2025-10-15 15:39:08 -05:00
ed9002f436 feat: make password optional for session restoration 2025-10-15 15:34:16 -05:00
7d8a85f01e feat: add setupConnection and setSession methods for session restoration 2025-10-15 15:19:34 -05:00
31d7cab487 chore: update @types/node to specific version 2025-10-15 15:14:52 -05:00
b691020074 Merge branch 'typescript-transition' 2025-10-15 15:00:27 -05:00
b8a11e779c Merge pull request 'typescript-transition' (#1) from typescript-transition into main
Reviewed-on: #1
2025-10-11 17:38:37 -05:00
6 changed files with 97 additions and 31 deletions

12
package-lock.json generated
View File

@@ -1,15 +1,15 @@
{
"name": "tryton-rpc-client",
"name": "tryton-rpc-client-js",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "tryton-rpc-client",
"name": "tryton-rpc-client-js",
"version": "1.0.0",
"license": "MIT",
"devDependencies": {
"@types/node": "^20.0.0",
"@types/node": "^20.19.21",
"rimraf": "^5.0.0",
"typescript": "^5.0.0"
},
@@ -47,9 +47,9 @@
}
},
"node_modules/@types/node": {
"version": "20.19.20",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.20.tgz",
"integrity": "sha512-2Q7WS25j4pS1cS8yw3d6buNCVJukOTeQ39bAnwR6sOJbaxvyCGebzTMypDFN82CxBLnl+lSWVdCCWbRY6y9yZQ==",
"version": "20.19.21",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.21.tgz",
"integrity": "sha512-CsGG2P3I5y48RPMfprQGfy4JPRZ6csfC3ltBZSRItG3ngggmNY/qs2uZKp4p9VbrpqNNSMzUZNFZKzgOGnd/VA==",
"dev": true,
"license": "MIT",
"dependencies": {

View File

@@ -34,11 +34,10 @@
"engines": {
"node": ">=14.0.0"
},
"dependencies": {},
"devDependencies": {
"@types/node": "^20.0.0",
"typescript": "^5.0.0",
"rimraf": "^5.0.0"
"@types/node": "^20.19.21",
"rimraf": "^5.0.0",
"typescript": "^5.0.0"
},
"files": [
"dist",

View File

@@ -181,7 +181,6 @@ export class TrytonCache {
throw new Error("Key expired");
}
console.log(`(cached) ${prefix} ${key}`);
return this._deepCopy(entry.value);
}

View File

@@ -45,6 +45,9 @@ export class TrytonClient {
/**
* Create a new Tryton client
* @param config Configuration object
* @param config.hostname - Hostname or IP address. Can include port (e.g., "46.62.242.210:8090")
* @param config.port - Port number (ignored if hostname includes port)
*/
constructor(config: TrytonClientConfig) {
const {
@@ -69,10 +72,20 @@ export class TrytonClient {
this.useHttps = port === 443 || port === 8443;
}
// Handle IP:Port format (e.g., "46.62.242.210:8090")
if (this.hostname.includes(":") && !this.hostname.startsWith("http")) {
const [ip, hostPort] = this.hostname.split(":");
this.hostname = ip;
this.port = parseInt(hostPort, 10);
// Determine https based on extracted port
this.useHttps = this.port === 443 || this.port === 8443;
} else {
this.port = port;
}
this.database = database;
this.username = username;
this.password = password;
this.port = port;
this.password = password || ""; // Empty string if not provided
this.language = language;
this.options = options;
this.connection = null;
@@ -81,6 +94,7 @@ export class TrytonClient {
/**
* Alternative constructor for backward compatibility
* Note: If hostname includes port (IP:Port), the port parameter will be ignored
*/
static create(
hostname: string,
@@ -158,6 +172,28 @@ export class TrytonClient {
}
}
/**
* Setup connection pool without authentication
* Used when restoring an existing session
* @returns {Promise<void>}
*/
async setupConnection(): Promise<void> {
this.connection = new ServerPool(
this.hostname,
this.port,
this.database,
{
session: undefined, // Session will be set by restoreSession()
cache: this.options.cache !== false ? [] : null,
verbose: this.options.verbose || false,
connectTimeout: this.options.connectTimeout || CONNECT_TIMEOUT,
timeout: this.options.timeout || DEFAULT_TIMEOUT,
keepMax: this.options.keepMax || 4,
useHttps: this.useHttps,
}
);
}
/**
* Call RPC method on server
* @param {string} methodName - RPC method name (e.g., 'model.party.party.read')
@@ -521,21 +557,30 @@ export class TrytonClient {
// Establecer la sesión sin hacer login
this.session = sessionToken;
// Verificar que la sesión sigue siendo válida
const proxy = this.connection?.getConnection();
if (!proxy) {
throw new Error("No connection available");
// Actualizar la sesión en el connection pool ANTES de obtener proxy
if (this.connection) {
this.connection.setSession(sessionToken);
} else {
throw new Error("No connection pool available");
}
// Obtener proxy (ahora con la sesión ya actualizada)
const proxy = this.connection.getConnection();
// Test de validación de sesión
try {
await proxy.request("common.version", []);
console.log("✅ Sesión restaurada exitosamente");
// Usar un método que requiere autenticación para validar la sesión
await proxy.request("model.res.user.get_preferences", [
true,
{},
]);
this.connection.putConnection(proxy); // Devolver conexión al pool
return true;
} catch (error) {
// Sesión inválida o expirada
console.error("❌ Error en validación:", error);
this.session = null;
console.log("❌ Sesión inválida o expirada");
this.connection.putConnection(proxy); // Devolver conexión al pool
return false;
}
} catch (error) {

View File

@@ -169,13 +169,15 @@ export class TrytonJSONEncoder {
case "datetime": {
const dt = specialValue as TrytonDateTime;
return new Date(
dt.year,
dt.month - 1,
dt.day,
dt.hour || 0,
dt.minute || 0,
dt.second || 0,
Math.floor((dt.microsecond || 0) / 1000)
Date.UTC(
dt.year,
dt.month - 1,
dt.day,
dt.hour || 0,
dt.minute || 0,
dt.second || 0,
Math.floor((dt.microsecond || 0) / 1000)
)
);
}
@@ -378,9 +380,9 @@ export class Transport {
responseText = data.toString("utf-8");
}
if (verbose) {
console.log("Response:", responseText);
}
// if (verbose) {
// console.log("Response:", responseText);
// }
const response = TrytonJSONEncoder.deserialize(
responseText
@@ -646,6 +648,27 @@ export class ServerPool {
}
}
/**
* Update session for all connections
* @param {string} session - New session string
*/
setSession(session: string): void {
this.session = session;
this.options.session = session;
// Update session for all existing connections and their transports
for (const conn of this.pool) {
if ((conn as any).transport) {
(conn as any).transport.session = session;
}
}
for (const conn of this.used) {
if ((conn as any).transport) {
(conn as any).transport.session = session;
}
}
}
/**
* Get connection from pool or create new one
* @returns {ServerProxy} - Server proxy instance

View File

@@ -16,7 +16,7 @@ export interface TrytonClientConfig {
hostname: string;
database: string;
username: string;
password: string;
password?: string; // Optional - no necesario para restaurar sesión
port?: number;
language?: string;
options?: TrytonClientOptions;