Compare commits

...

2 Commits

Author SHA1 Message Date
b4f191de42 fix: basic connection example 2026-04-05 19:57:26 -05:00
9d25b3e6a9 fix: port by default 443 2026-04-03 23:35:10 -05:00
2 changed files with 721 additions and 752 deletions

View File

@@ -18,10 +18,23 @@ import { TrytonClient } from "../src/client";
// ==================================================== // ====================================================
// CONFIGURACIÓN - EDITA ESTOS VALORES CON TUS DATOS // CONFIGURACIÓN - EDITA ESTOS VALORES CON TUS DATOS
// ==================================================== // ====================================================
// const config = {
// hostname: "https://demo7.6.tryton.org", // Servidor demo con HTTPS
// port: 8000, // Puerto del servidor Tryton (generalmente 8000)
// database: "demo7.6", // Base de datos demo
// username: "admin", // Usuario demo
// password: "admin", // Contraseña demo
// language: "es", // Idioma (es, en, etc.)
// options: {
// verbose: true, // Mostrar información detallada de conexión
// timeout: 30000, // Timeout en milisegundos
// },
// };
const config = { const config = {
hostname: "https://demo7.6.tryton.org", // Servidor demo con HTTPS hostname: "demo7.6.tryton.org", // Servidor demo con HTTPS
port: 8000, // Puerto del servidor Tryton (generalmente 8000) port: 443, // Puerto del servidor Tryton (generalmente 8000)
database: "demo7.6", // Base de datos demo database: "tryton", // Base de datos demo
username: "admin", // Usuario demo username: "admin", // Usuario demo
password: "admin", // Contraseña demo password: "admin", // Contraseña demo
language: "es", // Idioma (es, en, etc.) language: "es", // Idioma (es, en, etc.)
@@ -42,12 +55,10 @@ function validateConfig() {
const missingFields = requiredFields.filter((field) => !config[field]); const missingFields = requiredFields.filter((field) => !config[field]);
if (missingFields.length > 0) { if (missingFields.length > 0) {
console.error( console.error("❌ Error: Faltan los siguientes campos de configuración:");
"❌ Error: Faltan los siguientes campos de configuración:"
);
missingFields.forEach((field) => console.error(` - ${field}`)); missingFields.forEach((field) => console.error(` - ${field}`));
console.error( console.error(
"\n💡 Edita este archivo y completa la configuración antes de ejecutar." "\n💡 Edita este archivo y completa la configuración antes de ejecutar.",
); );
process.exit(1); process.exit(1);
} }
@@ -112,7 +123,7 @@ async function main() {
[], // Dominio: todos los terceros (sin filtros) [], // Dominio: todos los terceros (sin filtros)
["id", "name", "code"], // Campos a obtener ["id", "name", "code"], // Campos a obtener
0, // Offset 0, // Offset
20 // Límite de resultados 20, // Límite de resultados
// Sin parámetro order // Sin parámetro order
); );
@@ -125,9 +136,7 @@ async function main() {
partiesData.forEach((party, index) => { partiesData.forEach((party, index) => {
const code = party.code ? ` (${party.code})` : ""; const code = party.code ? ` (${party.code})` : "";
console.log( console.log(
`${(index + 1).toString().padStart(2)}. ${ `${(index + 1).toString().padStart(2)}. ${party.name}${code}`,
party.name
}${code}`
); );
}); });
} }
@@ -135,8 +144,7 @@ async function main() {
console.log("\n🎉 ¡Ejemplo completado exitosamente!"); console.log("\n🎉 ¡Ejemplo completado exitosamente!");
} catch (error) { } catch (error) {
console.error("❌ Error durante la ejecución:"); console.error("❌ Error durante la ejecución:");
const errorMessage = const errorMessage = error instanceof Error ? error.message : String(error);
error instanceof Error ? error.message : String(error);
console.error(errorMessage); console.error(errorMessage);
if (config.options.verbose && error instanceof Error && error.stack) { if (config.options.verbose && error instanceof Error && error.stack) {
@@ -148,9 +156,7 @@ async function main() {
console.error("\n💡 Posibles soluciones:"); console.error("\n💡 Posibles soluciones:");
console.error(" - Verifica que el servidor Tryton esté ejecutándose"); console.error(" - Verifica que el servidor Tryton esté ejecutándose");
console.error(" - Confirma que los datos de conexión sean correctos"); console.error(" - Confirma que los datos de conexión sean correctos");
console.error( console.error(" - Asegúrate de que el usuario tenga permisos adecuados");
" - Asegúrate de que el usuario tenga permisos adecuados"
);
console.error(" - Verifica la conectividad de red al servidor"); console.error(" - Verifica la conectividad de red al servidor");
process.exit(1); process.exit(1);

View File

@@ -55,7 +55,7 @@ export class TrytonClient {
database, database,
username, username,
password, password,
port = 8000, port = 443,
language = "en", language = "en",
options = {}, options = {},
} = config; } = config;
@@ -102,7 +102,7 @@ export class TrytonClient {
username: string, username: string,
password: string, password: string,
port: number = 8000, port: number = 8000,
language: string = "en" language: string = "en",
): TrytonClient { ): TrytonClient {
return new TrytonClient({ return new TrytonClient({
hostname, hostname,
@@ -121,18 +121,12 @@ export class TrytonClient {
*/ */
async connect(): Promise<boolean> { async connect(): Promise<boolean> {
try { try {
const proxy = new ServerProxy( const proxy = new ServerProxy(this.hostname, this.port, this.database, {
this.hostname,
this.port,
this.database,
{
verbose: this.options.verbose || false, verbose: this.options.verbose || false,
connectTimeout: connectTimeout: this.options.connectTimeout || CONNECT_TIMEOUT,
this.options.connectTimeout || CONNECT_TIMEOUT,
timeout: this.options.timeout || DEFAULT_TIMEOUT, timeout: this.options.timeout || DEFAULT_TIMEOUT,
useHttps: this.useHttps, useHttps: this.useHttps,
} });
);
// Perform login // Perform login
const parameters = { const parameters = {
@@ -158,12 +152,11 @@ export class TrytonClient {
session: this.session, session: this.session,
cache: this.options.cache !== false ? [] : null, // Enable cache by default cache: this.options.cache !== false ? [] : null, // Enable cache by default
verbose: this.options.verbose || false, verbose: this.options.verbose || false,
connectTimeout: connectTimeout: this.options.connectTimeout || CONNECT_TIMEOUT,
this.options.connectTimeout || CONNECT_TIMEOUT,
timeout: this.options.timeout || DEFAULT_TIMEOUT, timeout: this.options.timeout || DEFAULT_TIMEOUT,
keepMax: this.options.keepMax || 4, keepMax: this.options.keepMax || 4,
useHttps: this.useHttps, useHttps: this.useHttps,
} },
); );
return true; return true;
@@ -178,11 +171,7 @@ export class TrytonClient {
* @returns {Promise<void>} * @returns {Promise<void>}
*/ */
async setupConnection(): Promise<void> { async setupConnection(): Promise<void> {
this.connection = new ServerPool( this.connection = new ServerPool(this.hostname, this.port, this.database, {
this.hostname,
this.port,
this.database,
{
session: undefined, // Session will be set by restoreSession() session: undefined, // Session will be set by restoreSession()
cache: this.options.cache !== false ? [] : null, cache: this.options.cache !== false ? [] : null,
verbose: this.options.verbose || false, verbose: this.options.verbose || false,
@@ -190,8 +179,7 @@ export class TrytonClient {
timeout: this.options.timeout || DEFAULT_TIMEOUT, timeout: this.options.timeout || DEFAULT_TIMEOUT,
keepMax: this.options.keepMax || 4, keepMax: this.options.keepMax || 4,
useHttps: this.useHttps, useHttps: this.useHttps,
} });
);
} }
/** /**
@@ -247,7 +235,7 @@ export class TrytonClient {
model: ModelName, model: ModelName,
ids: RecordIds, ids: RecordIds,
fields: FieldName[], fields: FieldName[],
context: TrytonContext = {} context: TrytonContext = {},
): Promise<T[]> { ): Promise<T[]> {
return this.call<T[]>(`model.${model}.read`, [ids, fields, context]); return this.call<T[]>(`model.${model}.read`, [ids, fields, context]);
} }
@@ -262,12 +250,9 @@ export class TrytonClient {
async create( async create(
model: ModelName, model: ModelName,
records: Record<string, any>[], records: Record<string, any>[],
context: TrytonContext = {} context: TrytonContext = {},
): Promise<RecordIds> { ): Promise<RecordIds> {
return this.call<RecordIds>(`model.${model}.create`, [ return this.call<RecordIds>(`model.${model}.create`, [records, context]);
records,
context,
]);
} }
/** /**
@@ -282,7 +267,7 @@ export class TrytonClient {
model: ModelName, model: ModelName,
ids: RecordIds, ids: RecordIds,
values: Record<string, any>, values: Record<string, any>,
context: TrytonContext = {} context: TrytonContext = {},
): Promise<void> { ): Promise<void> {
return this.call<void>(`model.${model}.write`, [ids, values, context]); return this.call<void>(`model.${model}.write`, [ids, values, context]);
} }
@@ -297,7 +282,7 @@ export class TrytonClient {
async delete( async delete(
model: ModelName, model: ModelName,
ids: RecordIds, ids: RecordIds,
context: TrytonContext = {} context: TrytonContext = {},
): Promise<void> { ): Promise<void> {
return this.call<void>(`model.${model}.delete`, [ids, context]); return this.call<void>(`model.${model}.delete`, [ids, context]);
} }
@@ -318,7 +303,7 @@ export class TrytonClient {
offset: number = 0, offset: number = 0,
limit: number | null = null, limit: number | null = null,
order: string[] | null = null, order: string[] | null = null,
context: TrytonContext = {} context: TrytonContext = {},
): Promise<RecordIds> { ): Promise<RecordIds> {
return this.call<RecordIds>(`model.${model}.search`, [ return this.call<RecordIds>(`model.${model}.search`, [
domain, domain,
@@ -347,7 +332,7 @@ export class TrytonClient {
offset: number = 0, offset: number = 0,
limit: number | null = null, limit: number | null = null,
order: string[] | null = null, order: string[] | null = null,
context: TrytonContext = {} context: TrytonContext = {},
): Promise<T[]> { ): Promise<T[]> {
return this.call<T[]>(`model.${model}.search_read`, [ return this.call<T[]>(`model.${model}.search_read`, [
domain, domain,
@@ -369,12 +354,9 @@ export class TrytonClient {
async searchCount( async searchCount(
model: ModelName, model: ModelName,
domain: SearchDomain, domain: SearchDomain,
context: TrytonContext = {} context: TrytonContext = {},
): Promise<number> { ): Promise<number> {
return this.call<number>(`model.${model}.search_count`, [ return this.call<number>(`model.${model}.search_count`, [domain, context]);
domain,
context,
]);
} }
/** /**
@@ -419,7 +401,7 @@ export class TrytonClient {
const users = await this.read<TrytonUser>( const users = await this.read<TrytonUser>(
"res.user", "res.user",
[preferences.id], [preferences.id],
["id", "name", "login", "language", "company", "email"] ["id", "name", "login", "language", "company", "email"],
); );
if (!users || users.length === 0) { if (!users || users.length === 0) {
throw new Error("User not found"); throw new Error("User not found");
@@ -570,10 +552,7 @@ export class TrytonClient {
// Test de validación de sesión // Test de validación de sesión
try { try {
// Usar un método que requiere autenticación para validar la sesión // Usar un método que requiere autenticación para validar la sesión
await proxy.request("model.res.user.get_preferences", [ await proxy.request("model.res.user.get_preferences", [true, {}]);
true,
{},
]);
this.connection.putConnection(proxy); // Devolver conexión al pool this.connection.putConnection(proxy); // Devolver conexión al pool
return true; return true;
} catch (error) { } catch (error) {
@@ -595,36 +574,20 @@ export class TrytonClient {
* Creates a typed interface for specific models * Creates a typed interface for specific models
*/ */
model<T extends TrytonRecord = TrytonRecord>( model<T extends TrytonRecord = TrytonRecord>(
modelName: ModelName modelName: ModelName,
): TypedModelOperations<T> { ): TypedModelOperations<T> {
return { return {
read: ( read: (ids: RecordIds, fields: FieldName[], context?: TrytonContext) =>
ids: RecordIds, this.read<T>(modelName, ids, fields, context),
fields: FieldName[],
context?: TrytonContext
) => this.read<T>(modelName, ids, fields, context),
create: ( create: (records: Partial<Omit<T, "id">>[], context?: TrytonContext) =>
records: Partial<Omit<T, "id">>[], this.create(modelName, records as Record<string, any>[], context),
context?: TrytonContext
) =>
this.create(
modelName,
records as Record<string, any>[],
context
),
write: ( write: (
ids: RecordIds, ids: RecordIds,
values: Partial<Omit<T, "id">>, values: Partial<Omit<T, "id">>,
context?: TrytonContext context?: TrytonContext,
) => ) => this.write(modelName, ids, values as Record<string, any>, context),
this.write(
modelName,
ids,
values as Record<string, any>,
context
),
delete: (ids: RecordIds, context?: TrytonContext) => delete: (ids: RecordIds, context?: TrytonContext) =>
this.delete(modelName, ids, context), this.delete(modelName, ids, context),
@@ -634,7 +597,7 @@ export class TrytonClient {
offset?: number, offset?: number,
limit?: number, limit?: number,
order?: string[], order?: string[],
context?: TrytonContext context?: TrytonContext,
) => this.search(modelName, domain, offset, limit, order, context), ) => this.search(modelName, domain, offset, limit, order, context),
searchRead: ( searchRead: (
@@ -643,7 +606,7 @@ export class TrytonClient {
offset?: number, offset?: number,
limit?: number, limit?: number,
order?: string[], order?: string[],
context?: TrytonContext context?: TrytonContext,
) => ) =>
this.searchRead<T>( this.searchRead<T>(
modelName, modelName,
@@ -652,7 +615,7 @@ export class TrytonClient {
offset, offset,
limit, limit,
order, order,
context context,
), ),
searchCount: (domain: SearchDomain, context?: TrytonContext) => searchCount: (domain: SearchDomain, context?: TrytonContext) =>