@gpe-sistemas/tripero-node 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +674 -0
  3. package/dist/client/TriperoClient.d.ts +137 -0
  4. package/dist/client/TriperoClient.d.ts.map +1 -0
  5. package/dist/client/TriperoClient.js +386 -0
  6. package/dist/client/TriperoClient.js.map +1 -0
  7. package/dist/client/TriperoHttpClient.d.ts +161 -0
  8. package/dist/client/TriperoHttpClient.d.ts.map +1 -0
  9. package/dist/client/TriperoHttpClient.js +121 -0
  10. package/dist/client/TriperoHttpClient.js.map +1 -0
  11. package/dist/client/constants.d.ts +51 -0
  12. package/dist/client/constants.d.ts.map +1 -0
  13. package/dist/client/constants.js +53 -0
  14. package/dist/client/constants.js.map +1 -0
  15. package/dist/client/index.d.ts +5 -0
  16. package/dist/client/index.d.ts.map +1 -0
  17. package/dist/client/index.js +15 -0
  18. package/dist/client/index.js.map +1 -0
  19. package/dist/client/logger.d.ts +17 -0
  20. package/dist/client/logger.d.ts.map +1 -0
  21. package/dist/client/logger.js +51 -0
  22. package/dist/client/logger.js.map +1 -0
  23. package/dist/index.d.ts +12 -0
  24. package/dist/index.d.ts.map +1 -0
  25. package/dist/index.js +23 -0
  26. package/dist/index.js.map +1 -0
  27. package/dist/interfaces/config.interface.d.ts +120 -0
  28. package/dist/interfaces/config.interface.d.ts.map +1 -0
  29. package/dist/interfaces/config.interface.js +3 -0
  30. package/dist/interfaces/config.interface.js.map +1 -0
  31. package/dist/interfaces/events.interface.d.ts +199 -0
  32. package/dist/interfaces/events.interface.d.ts.map +1 -0
  33. package/dist/interfaces/events.interface.js +7 -0
  34. package/dist/interfaces/events.interface.js.map +1 -0
  35. package/dist/interfaces/index.d.ts +3 -0
  36. package/dist/interfaces/index.d.ts.map +1 -0
  37. package/dist/interfaces/index.js +19 -0
  38. package/dist/interfaces/index.js.map +1 -0
  39. package/dist/nestjs/decorators.d.ts +53 -0
  40. package/dist/nestjs/decorators.d.ts.map +1 -0
  41. package/dist/nestjs/decorators.js +90 -0
  42. package/dist/nestjs/decorators.js.map +1 -0
  43. package/dist/nestjs/index.d.ts +3 -0
  44. package/dist/nestjs/index.d.ts.map +1 -0
  45. package/dist/nestjs/index.js +19 -0
  46. package/dist/nestjs/index.js.map +1 -0
  47. package/dist/nestjs/tripero.module.d.ts +84 -0
  48. package/dist/nestjs/tripero.module.d.ts.map +1 -0
  49. package/dist/nestjs/tripero.module.js +146 -0
  50. package/dist/nestjs/tripero.module.js.map +1 -0
  51. package/package.json +92 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 GPE Sistemas
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,674 @@
1
+ <p align="center">
2
+ <img src="https://raw.githubusercontent.com/GPE-Sistemas/tripero-node/main/docs/logo.png" width="200" alt="Tripero Node Logo" />
3
+ </p>
4
+
5
+ <h1 align="center">tripero-node</h1>
6
+
7
+ <p align="center">
8
+ <strong>Node.js/TypeScript SDK for Tripero GPS Trip Detection Service</strong>
9
+ </p>
10
+
11
+ <p align="center">
12
+ <a href="https://www.npmjs.com/package/@gpe-sistemas/tripero-node"><img src="https://img.shields.io/npm/v/@gpe-sistemas/tripero-node.svg" alt="npm version"></a>
13
+ <a href="https://www.npmjs.com/package/@gpe-sistemas/tripero-node"><img src="https://img.shields.io/npm/dm/@gpe-sistemas/tripero-node.svg" alt="npm downloads"></a>
14
+ <a href="https://github.com/GPE-Sistemas/tripero-node/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="License"></a>
15
+ <a href="https://www.typescriptlang.org/"><img src="https://img.shields.io/badge/TypeScript-5.0-blue.svg" alt="TypeScript"></a>
16
+ <a href="https://nodejs.org/"><img src="https://img.shields.io/badge/node-%3E%3D18.0.0-brightgreen.svg" alt="Node.js"></a>
17
+ </p>
18
+
19
+ <p align="center">
20
+ <a href="#-features">Features</a> •
21
+ <a href="#-installation">Installation</a> •
22
+ <a href="#-quick-start">Quick Start</a> •
23
+ <a href="#-api-reference">API</a> •
24
+ <a href="#-nestjs-integration">NestJS</a> •
25
+ <a href="#-events">Events</a> •
26
+ <a href="#-contributing">Contributing</a>
27
+ </p>
28
+
29
+ ---
30
+
31
+ ## 📋 Overview
32
+
33
+ **tripero-node** is the official Node.js/TypeScript SDK for [Tripero](https://github.com/GPE-Sistemas/tripero), an intelligent GPS trip detection and stop analysis microservice. This SDK simplifies integration with Tripero by providing:
34
+
35
+ - **Type-safe API** - Full TypeScript support with complete type definitions
36
+ - **Redis PubSub abstraction** - Simple methods for publishing positions and subscribing to events
37
+ - **HTTP client** - Access Tripero's REST API for queries and configuration
38
+ - **NestJS integration** - Dedicated module with dependency injection support
39
+ - **Fire-and-forget** - Non-blocking async operations by default
40
+
41
+ ## ✨ Features
42
+
43
+ | Feature | Description |
44
+ |---------|-------------|
45
+ | 🔌 **Easy Integration** | Simple API to publish GPS positions and receive trip events |
46
+ | 📡 **Real-time Events** | Subscribe to trip starts, completions, stops, and state changes |
47
+ | 🔒 **Type Safety** | Full TypeScript definitions for all events and configurations |
48
+ | ⚡ **High Performance** | Fire-and-forget publishing with Redis pipelines for batch operations |
49
+ | 🏗️ **NestJS Ready** | First-class NestJS support with module, service, and decorators |
50
+ | 🔧 **Configurable** | Flexible configuration with sensible defaults |
51
+ | 📊 **HTTP API Access** | Query tracker status, trips, stops, and configure odometers |
52
+ | 🏷️ **Metadata Support** | Multi-tenancy support with custom metadata propagation |
53
+
54
+ ## 📦 Installation
55
+
56
+ ```bash
57
+ # npm
58
+ npm install @gpe-sistemas/tripero-node
59
+
60
+ # yarn
61
+ yarn add @gpe-sistemas/tripero-node
62
+
63
+ # pnpm
64
+ pnpm add @gpe-sistemas/tripero-node
65
+ ```
66
+
67
+ ### Peer Dependencies
68
+
69
+ For NestJS integration (optional):
70
+ ```bash
71
+ npm install @nestjs/common @nestjs/core
72
+ ```
73
+
74
+ ## 🚀 Quick Start
75
+
76
+ ### Basic Usage (Node.js)
77
+
78
+ ```typescript
79
+ import { TriperoClient } from '@gpe-sistemas/tripero-node';
80
+
81
+ // Create client
82
+ const tripero = new TriperoClient({
83
+ redis: {
84
+ host: 'localhost',
85
+ port: 6379,
86
+ },
87
+ });
88
+
89
+ // Connect to Redis
90
+ await tripero.connect();
91
+
92
+ // Publish a GPS position
93
+ await tripero.publishPosition({
94
+ deviceId: 'VEHICLE-001',
95
+ timestamp: Date.now(),
96
+ latitude: -34.6037,
97
+ longitude: -58.3816,
98
+ speed: 45,
99
+ ignition: true,
100
+ });
101
+
102
+ // Subscribe to trip events
103
+ tripero.on('trip:started', (event) => {
104
+ console.log(`🚗 Trip started: ${event.tripId}`);
105
+ });
106
+
107
+ tripero.on('trip:completed', (event) => {
108
+ console.log(`🏁 Trip completed: ${event.tripId}`);
109
+ console.log(` Distance: ${event.distance}m`);
110
+ console.log(` Duration: ${event.duration}s`);
111
+ });
112
+
113
+ await tripero.subscribe();
114
+
115
+ // Cleanup on shutdown
116
+ process.on('SIGINT', async () => {
117
+ await tripero.disconnect();
118
+ process.exit(0);
119
+ });
120
+ ```
121
+
122
+ ### With HTTP API
123
+
124
+ ```typescript
125
+ const tripero = new TriperoClient({
126
+ redis: {
127
+ host: 'redis-tripero-service',
128
+ port: 6379,
129
+ },
130
+ http: {
131
+ baseUrl: 'http://tripero-service:3001',
132
+ },
133
+ });
134
+
135
+ await tripero.connect();
136
+
137
+ // Get tracker status
138
+ const status = await tripero.getTrackerStatus('VEHICLE-001');
139
+ console.log(`State: ${status.data.currentState.state}`);
140
+ console.log(`Odometer: ${status.data.odometer.totalKm} km`);
141
+
142
+ // Get trip history
143
+ const trips = await tripero.getTrips({
144
+ deviceId: 'VEHICLE-001',
145
+ from: new Date('2024-01-01'),
146
+ to: new Date(),
147
+ });
148
+
149
+ // Set odometer (sync with vehicle's real odometer)
150
+ await tripero.setOdometer('VEHICLE-001', 125000000, 'vehicle_sync');
151
+ ```
152
+
153
+ ## 📚 API Reference
154
+
155
+ ### TriperoClient
156
+
157
+ The main class for interacting with Tripero.
158
+
159
+ #### Constructor
160
+
161
+ ```typescript
162
+ new TriperoClient(options: TriperoClientOptions)
163
+ ```
164
+
165
+ #### Configuration Options
166
+
167
+ ```typescript
168
+ interface TriperoClientOptions {
169
+ redis: {
170
+ host?: string; // Default: 'localhost'
171
+ port?: number; // Default: 6379
172
+ db?: number; // Default: 0
173
+ password?: string; // Optional
174
+ username?: string; // Optional (Redis 6+ ACL)
175
+ keyPrefix?: string; // Default: 'tripero:'
176
+ };
177
+ http?: {
178
+ baseUrl: string; // Tripero HTTP API URL
179
+ timeout?: number; // Default: 10000ms
180
+ headers?: Record<string, string>;
181
+ };
182
+ options?: {
183
+ enableRetry?: boolean; // Default: false
184
+ enableOfflineQueue?: boolean; // Default: false
185
+ throwOnError?: boolean; // Default: false
186
+ logLevel?: 'debug' | 'info' | 'warn' | 'error' | 'silent';
187
+ };
188
+ }
189
+ ```
190
+
191
+ ### Connection Methods
192
+
193
+ | Method | Description |
194
+ |--------|-------------|
195
+ | `connect()` | Connect to Redis server |
196
+ | `disconnect()` | Disconnect from Redis server |
197
+ | `health()` | Check Redis connection health |
198
+ | `healthHttp()` | Check Tripero HTTP API health (requires `http` config) |
199
+
200
+ ### Publishing Methods
201
+
202
+ #### `publishPosition(position: PositionEvent): Promise<void>`
203
+
204
+ Publish a GPS position to Tripero.
205
+
206
+ ```typescript
207
+ await tripero.publishPosition({
208
+ deviceId: 'VEHICLE-001', // Required: unique device identifier
209
+ timestamp: Date.now(), // Required: Unix timestamp in ms
210
+ latitude: -34.6037, // Required: -90 to 90
211
+ longitude: -58.3816, // Required: -180 to 180
212
+ speed: 45, // Required: km/h
213
+ ignition: true, // Optional: engine state
214
+ heading: 180, // Optional: degrees 0-360
215
+ altitude: 25, // Optional: meters
216
+ accuracy: 5, // Optional: GPS accuracy in meters
217
+ satellites: 12, // Optional: number of satellites
218
+ metadata: { // Optional: custom data
219
+ tenant_id: 'acme-corp',
220
+ fleet_id: 'delivery',
221
+ driver_id: 'driver-123',
222
+ },
223
+ });
224
+ ```
225
+
226
+ #### `publishPositions(positions: PositionEvent[]): Promise<void>`
227
+
228
+ Publish multiple positions in a single batch (uses Redis pipeline for performance).
229
+
230
+ ```typescript
231
+ await tripero.publishPositions([
232
+ { deviceId: 'V-001', timestamp: Date.now(), latitude: -34.60, longitude: -58.38, speed: 45 },
233
+ { deviceId: 'V-002', timestamp: Date.now(), latitude: -34.61, longitude: -58.39, speed: 30 },
234
+ { deviceId: 'V-003', timestamp: Date.now(), latitude: -34.62, longitude: -58.40, speed: 55 },
235
+ ]);
236
+ ```
237
+
238
+ #### `publishIgnitionEvent(event: IgnitionEvent): Promise<void>`
239
+
240
+ Publish an ignition state change.
241
+
242
+ ```typescript
243
+ await tripero.publishIgnitionEvent({
244
+ deviceId: 'VEHICLE-001',
245
+ timestamp: Date.now(),
246
+ ignition: true, // true = ON, false = OFF
247
+ latitude: -34.6037,
248
+ longitude: -58.3816,
249
+ });
250
+ ```
251
+
252
+ ### Subscription Methods
253
+
254
+ #### `on(eventType, handler): void`
255
+
256
+ Register an event handler.
257
+
258
+ ```typescript
259
+ tripero.on('trip:started', (event: TripStartedEvent) => {
260
+ console.log(`Trip ${event.tripId} started at ${event.startTime}`);
261
+ });
262
+
263
+ tripero.on('trip:completed', (event: TripCompletedEvent) => {
264
+ console.log(`Trip ${event.tripId}: ${event.distance}m in ${event.duration}s`);
265
+ });
266
+
267
+ tripero.on('stop:started', (event: StopStartedEvent) => {
268
+ console.log(`Stop detected: ${event.reason}`);
269
+ });
270
+
271
+ tripero.on('tracker:state:changed', (event: TrackerStateChangedEvent) => {
272
+ console.log(`${event.previousState} → ${event.currentState}`);
273
+ });
274
+ ```
275
+
276
+ #### `off(eventType, handler): void`
277
+
278
+ Remove an event handler.
279
+
280
+ #### `subscribe(): Promise<void>`
281
+
282
+ Start listening to all registered events.
283
+
284
+ #### `unsubscribe(): Promise<void>`
285
+
286
+ Stop listening to events.
287
+
288
+ ### HTTP API Methods
289
+
290
+ > **Note:** These methods require the `http` configuration option.
291
+
292
+ #### `getTrackerStatus(trackerId: string): Promise<TrackerStatusResponse>`
293
+
294
+ Get real-time status of a tracker including state, odometer, position, and statistics.
295
+
296
+ #### `setOdometer(trackerId: string, meters: number, reason?: string): Promise<OdometerSetResponse>`
297
+
298
+ Set the odometer offset to sync with the vehicle's real odometer.
299
+
300
+ #### `getTrips(options: ReportQueryOptions): Promise<TripReport[]>`
301
+
302
+ Query historical trips.
303
+
304
+ ```typescript
305
+ const trips = await tripero.getTrips({
306
+ deviceId: 'VEHICLE-001', // or ['V-001', 'V-002'] or 'all'
307
+ from: new Date('2024-01-01'),
308
+ to: new Date(),
309
+ tenantId: 'acme-corp', // Optional: filter by tenant
310
+ fleetId: 'delivery', // Optional: filter by fleet
311
+ });
312
+ ```
313
+
314
+ #### `getStops(options: ReportQueryOptions): Promise<StopReport[]>`
315
+
316
+ Query historical stops with the same options as `getTrips()`.
317
+
318
+ ## 🏗️ NestJS Integration
319
+
320
+ ### Module Setup
321
+
322
+ ```typescript
323
+ // app.module.ts
324
+ import { Module } from '@nestjs/common';
325
+ import { TriperoModule } from '@gpe-sistemas/tripero-node/nestjs';
326
+
327
+ @Module({
328
+ imports: [
329
+ // Static configuration
330
+ TriperoModule.forRoot({
331
+ redis: {
332
+ host: 'redis-tripero-service',
333
+ port: 6379,
334
+ },
335
+ http: {
336
+ baseUrl: 'http://tripero-service:3001',
337
+ },
338
+ }),
339
+ ],
340
+ })
341
+ export class AppModule {}
342
+ ```
343
+
344
+ ### Async Configuration
345
+
346
+ ```typescript
347
+ // app.module.ts
348
+ import { Module } from '@nestjs/common';
349
+ import { ConfigModule, ConfigService } from '@nestjs/config';
350
+ import { TriperoModule } from '@gpe-sistemas/tripero-node/nestjs';
351
+
352
+ @Module({
353
+ imports: [
354
+ ConfigModule.forRoot(),
355
+ TriperoModule.forRootAsync({
356
+ imports: [ConfigModule],
357
+ inject: [ConfigService],
358
+ useFactory: (config: ConfigService) => ({
359
+ redis: {
360
+ host: config.get('TRIPERO_REDIS_HOST', 'localhost'),
361
+ port: config.get('TRIPERO_REDIS_PORT', 6379),
362
+ keyPrefix: config.get('TRIPERO_KEY_PREFIX', 'tripero:'),
363
+ },
364
+ http: {
365
+ baseUrl: config.get('TRIPERO_HTTP_URL'),
366
+ },
367
+ }),
368
+ }),
369
+ ],
370
+ })
371
+ export class AppModule {}
372
+ ```
373
+
374
+ ### Using the Service
375
+
376
+ ```typescript
377
+ // position.service.ts
378
+ import { Injectable } from '@nestjs/common';
379
+ import { TriperoService } from '@gpe-sistemas/tripero-node/nestjs';
380
+
381
+ @Injectable()
382
+ export class PositionService {
383
+ constructor(private readonly tripero: TriperoService) {}
384
+
385
+ async handleGpsData(data: GpsData) {
386
+ await this.tripero.publishPosition({
387
+ deviceId: data.imei,
388
+ timestamp: Date.now(),
389
+ latitude: data.lat,
390
+ longitude: data.lon,
391
+ speed: data.speed,
392
+ ignition: data.acc,
393
+ metadata: {
394
+ tenant_id: data.tenantId,
395
+ },
396
+ });
397
+ }
398
+
399
+ async getVehicleStatus(deviceId: string) {
400
+ return this.tripero.getTrackerStatus(deviceId);
401
+ }
402
+ }
403
+ ```
404
+
405
+ ### Event Decorators
406
+
407
+ ```typescript
408
+ // trip-listener.service.ts
409
+ import { Injectable, OnModuleInit } from '@nestjs/common';
410
+ import { TriperoService } from '@gpe-sistemas/tripero-node/nestjs';
411
+ import type { TripStartedEvent, TripCompletedEvent } from '@gpe-sistemas/tripero-node';
412
+
413
+ @Injectable()
414
+ export class TripListenerService implements OnModuleInit {
415
+ constructor(private readonly tripero: TriperoService) {}
416
+
417
+ async onModuleInit() {
418
+ // Register event handlers
419
+ this.tripero.on('trip:started', this.handleTripStarted.bind(this));
420
+ this.tripero.on('trip:completed', this.handleTripCompleted.bind(this));
421
+
422
+ // Start listening
423
+ await this.tripero.subscribe();
424
+ }
425
+
426
+ private handleTripStarted(event: TripStartedEvent) {
427
+ console.log(`🚗 Trip started: ${event.tripId}`);
428
+ // Send notification, update dashboard, etc.
429
+ }
430
+
431
+ private handleTripCompleted(event: TripCompletedEvent) {
432
+ console.log(`🏁 Trip completed: ${event.tripId}`);
433
+ console.log(` Distance: ${event.distance}m`);
434
+ console.log(` Duration: ${event.duration}s`);
435
+ // Generate report, calculate fuel, etc.
436
+ }
437
+ }
438
+ ```
439
+
440
+ ## 📡 Events
441
+
442
+ ### Input Events (publish to Tripero)
443
+
444
+ | Channel | Method | Description |
445
+ |---------|--------|-------------|
446
+ | `position:new` | `publishPosition()` | GPS position data |
447
+ | `ignition:changed` | `publishIgnitionEvent()` | Ignition state changes |
448
+
449
+ ### Output Events (receive from Tripero)
450
+
451
+ | Event | Description | Key Fields |
452
+ |-------|-------------|------------|
453
+ | `tracker:state:changed` | Tracker state transition | `previousState`, `currentState`, `odometer` |
454
+ | `trip:started` | Trip has started | `tripId`, `deviceId`, `startTime`, `startLocation` |
455
+ | `trip:completed` | Trip has ended | `tripId`, `distance`, `duration`, `avgSpeed`, `maxSpeed` |
456
+ | `stop:started` | Stop detected during trip | `stopId`, `tripId`, `location`, `reason` |
457
+ | `stop:completed` | Stop has ended | `stopId`, `duration` |
458
+ | `position:rejected` | Position failed validation | `deviceId`, `reason` |
459
+
460
+ ### Tracker States
461
+
462
+ ```
463
+ STOPPED ←→ IDLE ←→ MOVING
464
+ ```
465
+
466
+ | State | Description |
467
+ |-------|-------------|
468
+ | `STOPPED` | Vehicle completely stopped (ignition OFF) |
469
+ | `IDLE` | Engine running but not moving (ignition ON, speed ≈ 0) |
470
+ | `MOVING` | Vehicle in motion (ignition ON, speed > threshold) |
471
+
472
+ ## 🏷️ Metadata Support
473
+
474
+ Tripero supports custom metadata that propagates automatically from positions to trips and stops:
475
+
476
+ ```typescript
477
+ await tripero.publishPosition({
478
+ deviceId: 'VEHICLE-001',
479
+ timestamp: Date.now(),
480
+ latitude: -34.6037,
481
+ longitude: -58.3816,
482
+ speed: 45,
483
+ metadata: {
484
+ // Optimized fields (B-tree index, ~1-2ms queries)
485
+ tenant_id: 'acme-corp',
486
+ client_id: 'client-123',
487
+ fleet_id: 'delivery-trucks',
488
+
489
+ // Custom fields (GIN index, ~5-10ms queries)
490
+ driver_id: 'driver-456',
491
+ route_number: 'R42',
492
+ delivery_id: 'DEL-789',
493
+ },
494
+ });
495
+ ```
496
+
497
+ Query trips/stops by metadata:
498
+
499
+ ```typescript
500
+ const trips = await tripero.getTrips({
501
+ deviceId: 'all',
502
+ from: new Date('2024-01-01'),
503
+ to: new Date(),
504
+ tenantId: 'acme-corp', // Fast query (~1-2ms)
505
+ fleetId: 'delivery-trucks', // Fast query (~1-2ms)
506
+ });
507
+ ```
508
+
509
+ ## ⚙️ Configuration
510
+
511
+ ### Environment Variables
512
+
513
+ When using with NestJS ConfigService:
514
+
515
+ | Variable | Description | Default |
516
+ |----------|-------------|---------|
517
+ | `TRIPERO_REDIS_HOST` | Redis server host | `localhost` |
518
+ | `TRIPERO_REDIS_PORT` | Redis server port | `6379` |
519
+ | `TRIPERO_REDIS_DB` | Redis database number | `0` |
520
+ | `TRIPERO_REDIS_PASSWORD` | Redis password | - |
521
+ | `TRIPERO_KEY_PREFIX` | Redis key/channel prefix | `tripero:` |
522
+ | `TRIPERO_HTTP_URL` | Tripero HTTP API URL | - |
523
+ | `TRIPERO_LOG_LEVEL` | Log level | `info` |
524
+
525
+ ### Redis Key Prefix
526
+
527
+ The SDK uses `tripero:` as the default key prefix to match Tripero server defaults. This allows sharing a Redis instance with other applications:
528
+
529
+ ```typescript
530
+ const tripero = new TriperoClient({
531
+ redis: {
532
+ host: 'shared-redis',
533
+ keyPrefix: 'myapp:tripero:', // Custom prefix
534
+ },
535
+ });
536
+ ```
537
+
538
+ > **Important:** The `keyPrefix` must match the `REDIS_KEY_PREFIX` configured in Tripero server.
539
+
540
+ ## 🔧 Advanced Usage
541
+
542
+ ### Custom Logger
543
+
544
+ ```typescript
545
+ import { TriperoClient, TriperoLogger } from '@gpe-sistemas/tripero-node';
546
+
547
+ const customLogger: TriperoLogger = {
548
+ debug: (msg, ...args) => myLogger.debug(msg, ...args),
549
+ info: (msg, ...args) => myLogger.info(msg, ...args),
550
+ warn: (msg, ...args) => myLogger.warn(msg, ...args),
551
+ error: (msg, ...args) => myLogger.error(msg, ...args),
552
+ };
553
+
554
+ const tripero = new TriperoClient({
555
+ redis: { host: 'localhost' },
556
+ options: {
557
+ logger: customLogger,
558
+ },
559
+ });
560
+ ```
561
+
562
+ ### Error Handling
563
+
564
+ By default, the SDK logs errors but doesn't throw (fire-and-forget). To enable exceptions:
565
+
566
+ ```typescript
567
+ const tripero = new TriperoClient({
568
+ redis: { host: 'localhost' },
569
+ options: {
570
+ throwOnError: true,
571
+ },
572
+ });
573
+
574
+ try {
575
+ await tripero.publishPosition(position);
576
+ } catch (error) {
577
+ console.error('Failed to publish:', error);
578
+ }
579
+ ```
580
+
581
+ ### Connection Retry
582
+
583
+ ```typescript
584
+ const tripero = new TriperoClient({
585
+ redis: {
586
+ host: 'localhost',
587
+ redisOptions: {
588
+ retryStrategy: (times) => Math.min(times * 1000, 30000),
589
+ maxRetriesPerRequest: 3,
590
+ },
591
+ },
592
+ options: {
593
+ enableRetry: true,
594
+ enableOfflineQueue: true,
595
+ },
596
+ });
597
+ ```
598
+
599
+ ## 🤝 Contributing
600
+
601
+ Contributions are welcome! Here's how you can help:
602
+
603
+ 1. **Fork** the repository
604
+ 2. **Create** a feature branch (`git checkout -b feature/amazing-feature`)
605
+ 3. **Commit** your changes (`git commit -m 'Add amazing feature'`)
606
+ 4. **Push** to the branch (`git push origin feature/amazing-feature`)
607
+ 5. **Open** a Pull Request
608
+
609
+ ### Development Setup
610
+
611
+ ```bash
612
+ # Clone the repository
613
+ git clone https://github.com/GPE-Sistemas/tripero-node.git
614
+ cd tripero-node
615
+
616
+ # Install dependencies
617
+ npm install
618
+
619
+ # Build
620
+ npm run build
621
+
622
+ # Run tests
623
+ npm test
624
+
625
+ # Lint
626
+ npm run lint
627
+ ```
628
+
629
+ ### Code Style
630
+
631
+ - Follow TypeScript best practices
632
+ - Use meaningful variable and function names
633
+ - Add JSDoc comments for public APIs
634
+ - Write tests for new features
635
+
636
+ ## 📄 License
637
+
638
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
639
+
640
+ ```
641
+ MIT License
642
+
643
+ Copyright (c) 2024 GPE Sistemas
644
+
645
+ Permission is hereby granted, free of charge, to any person obtaining a copy
646
+ of this software and associated documentation files (the "Software"), to deal
647
+ in the Software without restriction, including without limitation the rights
648
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
649
+ copies of the Software, and to permit persons to whom the Software is
650
+ furnished to do so, subject to the following conditions:
651
+
652
+ The above copyright notice and this permission notice shall be included in all
653
+ copies or substantial portions of the Software.
654
+ ```
655
+
656
+ ## 🔗 Related Projects
657
+
658
+ - **[Tripero](https://github.com/GPE-Sistemas/tripero)** - GPS trip detection microservice
659
+ - **[IRIX](https://github.com/GPE-Sistemas)** - Fleet management platform
660
+
661
+ ## 📞 Support
662
+
663
+ - **Issues**: [GitHub Issues](https://github.com/GPE-Sistemas/tripero-node/issues)
664
+ - **Discussions**: [GitHub Discussions](https://github.com/GPE-Sistemas/tripero-node/discussions)
665
+
666
+ ---
667
+
668
+ <p align="center">
669
+ Made with ❤️ by <a href="https://gpesistemas.com">GPE Sistemas</a>
670
+ </p>
671
+
672
+ <p align="center">
673
+ <sub>If you find this project useful, please consider giving it a ⭐</sub>
674
+ </p>