aves-sdk 1.0.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.
package/README.md ADDED
@@ -0,0 +1,691 @@
1
+ # AVES SDK for NestJS
2
+
3
+ A comprehensive TypeScript SDK for integrating with the AVES XML REST API in NestJS applications. This SDK provides full type safety, validation, error handling, and follows NestJS best practices.
4
+
5
+ ## Features
6
+
7
+ - **Full NestJS Integration** - Native module with `forRoot`/`forRootAsync` support and global availability
8
+ - **Complete Type Safety** - Comprehensive TypeScript interfaces with clean API abstractions
9
+ - **Advanced Validation** - Modern Zod validation with `AvesValidator` class and utility functions
10
+ - **Error Handling** - Structured error handling with AVES-specific error codes
11
+ - **Configuration** - Environment-based configuration with validation
12
+ - **Dependency Injection** - Interface-based DI following NestJS patterns
13
+ - **Clean APIs** - Developer-friendly interfaces abstracting XML complexity
14
+ - **Bidirectional Mappers** - Seamless conversion between clean and XML interfaces
15
+ - **Production Ready** - Built for npm deployment with proper exports
16
+
17
+ ## Installation
18
+
19
+ ```bash
20
+ npm install aves-sdk
21
+ # or
22
+ yarn add aves-sdk
23
+ # or
24
+ pnpm add aves-sdk
25
+ # or
26
+ bun add aves-sdk
27
+ ```
28
+
29
+ ## Quick Start
30
+
31
+ ### 1. Environment Configuration
32
+
33
+ Create a `.env` file:
34
+
35
+ ```env
36
+ AVES_BASE_URL=https://api.aves.example.com
37
+ AVES_HOST_ID=123456
38
+ AVES_XTOKEN=your_xtoken_here
39
+ AVES_LANGUAGE_CODE=01
40
+ AVES_TIMEOUT=30000
41
+ ```
42
+
43
+ ### 2. Module Setup
44
+
45
+ ```typescript
46
+ import { Module } from '@nestjs/common';
47
+ import { ConfigModule } from '@nestjs/config';
48
+ import { AvesModule } from 'aves-sdk';
49
+
50
+ @Module({
51
+ imports: [
52
+ ConfigModule.forRoot({
53
+ isGlobal: true,
54
+ }),
55
+ // Synchronous configuration
56
+ AvesModule.forRoot({
57
+ baseUrl: process.env.AVES_BASE_URL!,
58
+ hostId: process.env.AVES_HOST_ID!,
59
+ xtoken: process.env.AVES_XTOKEN!,
60
+ languageCode: process.env.AVES_LANGUAGE_CODE,
61
+ timeout: parseInt(process.env.AVES_TIMEOUT || '30000'),
62
+ }),
63
+
64
+ // OR Asynchronous configuration
65
+ AvesModule.forRootAsync({
66
+ imports: [ConfigModule],
67
+ useFactory: (configService: ConfigService) => ({
68
+ baseUrl: configService.get('AVES_BASE_URL')!,
69
+ hostId: configService.get('AVES_HOST_ID')!,
70
+ xtoken: configService.get('AVES_XTOKEN')!,
71
+ languageCode: configService.get('AVES_LANGUAGE_CODE'),
72
+ timeout: configService.get('AVES_TIMEOUT'),
73
+ }),
74
+ inject: [ConfigService],
75
+ }),
76
+ ],
77
+ })
78
+ export class AppModule {}
79
+ ```
80
+
81
+ ### 3. Service Usage with Clean APIs
82
+
83
+ ```typescript
84
+ import { Injectable } from '@nestjs/common';
85
+ import {
86
+ AvesService,
87
+ SearchCustomerRequest,
88
+ CreateBookingRequest,
89
+ Customer,
90
+ BookingResponse,
91
+ } from 'aves-sdk';
92
+
93
+ @Injectable()
94
+ export class BookingService {
95
+ constructor(private readonly avesService: AvesService) {}
96
+
97
+ async searchCustomers(searchTerm: string): Promise<Customer[]> {
98
+ const searchRequest: SearchCustomerRequest = {
99
+ type: 'customer',
100
+ fields: [
101
+ {
102
+ name: 'LastName',
103
+ value: searchTerm,
104
+ operator: 'contains',
105
+ },
106
+ ],
107
+ };
108
+
109
+ const response = await this.avesService.searchCustomer(searchRequest);
110
+ return response.results;
111
+ }
112
+
113
+ async createBooking(bookingData: {
114
+ customerId: string;
115
+ passengers: any[];
116
+ services: any[];
117
+ }): Promise<BookingResponse> {
118
+ const bookingRequest: CreateBookingRequest = {
119
+ type: 'individual',
120
+ priority: 'normal',
121
+ customerId: bookingData.customerId,
122
+ passengers: bookingData.passengers,
123
+ services: bookingData.services,
124
+ };
125
+
126
+ return await this.avesService.createBooking(bookingRequest);
127
+ }
128
+ }
129
+ ```
130
+
131
+ ## Clean API Interfaces
132
+
133
+ The SDK provides developer-friendly interfaces that abstract away XML complexity:
134
+
135
+ ### Customer Management
136
+
137
+ ```typescript
138
+ import {
139
+ Customer,
140
+ CustomerAddress,
141
+ CustomerContact,
142
+ AddressType,
143
+ CustomerType,
144
+ } from 'aves-sdk';
145
+
146
+ // Clean, intuitive interfaces
147
+ const customer: Customer = {
148
+ id: '12345',
149
+ type: 'customer',
150
+ status: 'active',
151
+ personalInfo: {
152
+ title: 'mr',
153
+ firstName: 'John',
154
+ lastName: 'Doe',
155
+ dateOfBirth: createDateString('1990-01-01'),
156
+ gender: 'male',
157
+ },
158
+ address: {
159
+ type: 'home',
160
+ street: '123 Main St',
161
+ city: 'New York',
162
+ postalCode: '10001',
163
+ country: 'US',
164
+ },
165
+ contact: {
166
+ phone: {
167
+ type: 'mobile',
168
+ number: '+1234567890',
169
+ },
170
+ email: {
171
+ type: 'work',
172
+ address: 'john.doe@example.com',
173
+ },
174
+ },
175
+ };
176
+ ```
177
+
178
+ ### Booking Management
179
+
180
+ ```typescript
181
+ import {
182
+ CreateBookingRequest,
183
+ BookingPassenger,
184
+ BookingService,
185
+ PassengerType,
186
+ ServiceType,
187
+ } from 'aves-sdk';
188
+
189
+ const booking: CreateBookingRequest = {
190
+ type: 'individual',
191
+ priority: 'normal',
192
+ customerId: '12345',
193
+ passengers: [
194
+ {
195
+ id: 'PAX001',
196
+ type: 'adult',
197
+ title: 'mr',
198
+ firstName: 'John',
199
+ lastName: 'Doe',
200
+ dateOfBirth: createDateString('1990-01-01'),
201
+ gender: 'male',
202
+ },
203
+ ],
204
+ services: [
205
+ {
206
+ id: 'SRV001',
207
+ type: 'flight',
208
+ status: 'confirmed',
209
+ description: 'Flight from NYC to LAX',
210
+ startDate: createDateString('2024-06-01'),
211
+ endDate: createDateString('2024-06-01'),
212
+ },
213
+ ],
214
+ };
215
+ ```
216
+
217
+ ### Complete Type Safety
218
+
219
+ The SDK provides **zero `any` types** and complete type safety throughout:
220
+
221
+ ```typescript
222
+ import {
223
+ CreateBookingRequest,
224
+ Customer,
225
+ CustomerAddress,
226
+ CustomerContact,
227
+ } from 'aves-sdk';
228
+
229
+ // Fully type-safe customer details in booking
230
+ const booking: CreateBookingRequest = {
231
+ type: 'individual',
232
+ priority: 'normal',
233
+ customerId: '12345',
234
+ // customerDetails is now properly typed as Customer interface
235
+ customerDetails: {
236
+ id: 'CUST001',
237
+ type: 'customer',
238
+ status: 'active',
239
+ personalInfo: {
240
+ title: 'mr',
241
+ firstName: 'John',
242
+ lastName: 'Doe',
243
+ dateOfBirth: createDateString('1990-01-01'),
244
+ gender: 'male',
245
+ },
246
+ contact: {
247
+ phone: {
248
+ type: 'mobile',
249
+ number: '+1234567890',
250
+ },
251
+ email: {
252
+ type: 'work',
253
+ address: 'john.doe@example.com',
254
+ },
255
+ },
256
+ address: {
257
+ type: 'home',
258
+ street: '123 Main St',
259
+ city: 'New York',
260
+ postalCode: '10001',
261
+ country: 'US',
262
+ },
263
+ },
264
+ passengers: [...],
265
+ services: [...],
266
+ };
267
+
268
+ // Automatic conversion to XML format with full type safety
269
+ const xmlBooking = mapCreateBookingToXml(booking);
270
+ ```
271
+
272
+ ## API Reference
273
+
274
+ ### Core Services
275
+
276
+ #### AvesService
277
+
278
+ The main service for interacting with the AVES API with clean interfaces.
279
+
280
+ **Customer Management:**
281
+
282
+ - `searchCustomer(request: SearchCustomerRequest)` - Search for customers
283
+ - `createCustomer(customer: Customer)` - Create new customer
284
+ - `updateCustomer(customer: Customer)` - Update existing customer
285
+
286
+ **Booking Management:**
287
+
288
+ - `createBooking(request: CreateBookingRequest)` - Create new booking
289
+ - `updateBooking(bookingId: string, updates: Partial<CreateBookingRequest>)` - Update booking
290
+ - `cancelBooking(request: CancelBookingRequest)` - Cancel booking
291
+ - `getBooking(bookingId: string)` - Get booking details
292
+
293
+ **Payment Management:**
294
+
295
+ - `addPayment(request: AddPaymentRequest)` - Add payment to booking
296
+ - `getPayments(bookingId: string)` - Get payment history
297
+
298
+ **Document Management:**
299
+
300
+ - `printDocument(request: PrintDocumentRequest)` - Generate documents
301
+
302
+ #### AvesValidator
303
+
304
+ Advanced validation class for comprehensive data validation scenarios.
305
+
306
+ **Core Methods:**
307
+
308
+ - `validate(data, schema?)` - Synchronous validation with error throwing
309
+ - `asyncValidate(data, schema?)` - Asynchronous validation with error throwing
310
+ - `safeValidateAndParse(data, schema?)` - Safe validation without throwing errors
311
+ - `safeAsyncValidateAndParse(data, schema?)` - Safe async validation
312
+
313
+ **Utility Methods:**
314
+
315
+ - `getErrorMessage(error, separator?)` - Format ZodError messages
316
+ - `getSchema()` - Get current default schema
317
+
318
+ **Static Methods:**
319
+
320
+ - `AvesValidator.withSchema(schema)` - Create validator with specific schema
321
+
322
+ **Utility Functions:**
323
+
324
+ - `createValidator(schema)` - Create validator instance
325
+ - `quickValidate(data, schema)` - Quick validation with error throwing
326
+ - `quickSafeValidate(data, schema)` - Quick safe validation
327
+
328
+ ### Configuration
329
+
330
+ #### AvesSdkConfig
331
+
332
+ ```typescript
333
+ interface AvesSdkConfig {
334
+ baseUrl: string; // AVES API base URL (validated as URL)
335
+ hostId: string; // 6-digit host ID (validated)
336
+ xtoken: string; // Authentication token (required)
337
+ languageCode?: string; // Language code: '01' (Italian) or '02' (English)
338
+ timeout?: number; // Request timeout in ms (default: 30000)
339
+ }
340
+ ```
341
+
342
+ ### Type Definitions
343
+
344
+ #### Union Types
345
+
346
+ The SDK provides strongly-typed union types for better type safety:
347
+
348
+ ```typescript
349
+ type AddressType = 'home' | 'work' | 'billing' | 'delivery';
350
+ type PassengerType = 'adult' | 'child' | 'infant';
351
+ type ServiceType = 'flight' | 'hotel' | 'transfer' | 'activity';
352
+ type PaymentType = 'cash' | 'credit_card' | 'bank_transfer';
353
+ type CustomerType = 'customer' | 'agent' | 'supplier';
354
+ type BookingType = 'individual' | 'group' | 'corporate';
355
+ ```
356
+
357
+ #### Branded Date Types
358
+
359
+ Type-safe date handling with branded types:
360
+
361
+ ```typescript
362
+ type DateString = string & { readonly __brand: 'DateString' }; // YYYY-MM-DD
363
+ type DateTimeString = string & { readonly __brand: 'DateTimeString' }; // YYYY-MM-DDTHH:mm:ss
364
+ type TimeString = string & { readonly __brand: 'TimeString' }; // HH:mm:ss
365
+
366
+ // Helper functions
367
+ const dateString = createDateString('2024-01-01');
368
+ const dateTimeString = createDateTimeString('2024-01-01T10:30:00');
369
+ const timeString = createTimeString('10:30:00');
370
+ ```
371
+
372
+ ### Validation
373
+
374
+ Built-in Zod validation with descriptive error messages:
375
+
376
+ ```typescript
377
+ import { configValidationSchema } from 'aves-sdk';
378
+
379
+ // Configuration validation
380
+ const result = configValidationSchema.safeParse(config);
381
+ if (!result.success) {
382
+ console.error('Validation errors:', result.error.issues);
383
+ }
384
+
385
+ // Request validation
386
+ import {
387
+ SearchCustomerRequestValidation,
388
+ CreateBookingRequestValidation,
389
+ } from 'aves-sdk';
390
+
391
+ const searchValidation =
392
+ SearchCustomerRequestValidation.safeParse(searchRequest);
393
+ const bookingValidation =
394
+ CreateBookingRequestValidation.safeParse(bookingRequest);
395
+ ```
396
+
397
+ #### AvesValidator Class
398
+
399
+ The SDK provides a comprehensive `AvesValidator` class for advanced validation scenarios:
400
+
401
+ ```typescript
402
+ import {
403
+ AvesValidator,
404
+ configValidationSchema,
405
+ createValidator,
406
+ quickValidate,
407
+ quickSafeValidate,
408
+ } from 'aves-sdk';
409
+
410
+ // Constructor approach - validator with default schema
411
+ const configValidator = new AvesValidator(configValidationSchema);
412
+
413
+ // Synchronous validation with error throwing
414
+ try {
415
+ const validConfig = configValidator.validate(configData);
416
+ console.log('Valid config:', validConfig);
417
+ } catch (error) {
418
+ if (error instanceof ZodError) {
419
+ console.error('Validation errors:', configValidator.getErrorMessage(error));
420
+ }
421
+ }
422
+
423
+ // Safe validation without throwing errors
424
+ const result = configValidator.safeValidateAndParse(configData);
425
+ if (result.success) {
426
+ console.log('Valid config:', result.data);
427
+ } else {
428
+ console.error('Validation errors:', result.error.issues);
429
+ }
430
+
431
+ // Asynchronous validation
432
+ const asyncResult = await configValidator.asyncValidate(configData);
433
+
434
+ // Method approach - validator without default schema
435
+ const validator = new AvesValidator();
436
+
437
+ // Validate with different schemas
438
+ const configResult = validator.validate(configData, configValidationSchema);
439
+ const searchResult = validator.safeValidateAndParse(
440
+ searchData,
441
+ SearchCustomerRequestValidation
442
+ );
443
+
444
+ // Utility functions for quick validation
445
+ const validConfig = quickValidate(configData, configValidationSchema);
446
+ const safeResult = quickSafeValidate(configData, configValidationSchema);
447
+
448
+ // Factory function approach
449
+ const validator = createValidator(configValidationSchema);
450
+ const result = validator.validate(configData);
451
+ ```
452
+
453
+ **AvesValidator Methods:**
454
+
455
+ - `validate(data, schema?)` - Synchronous validation with error throwing
456
+ - `asyncValidate(data, schema?)` - Asynchronous validation with error throwing
457
+ - `safeValidateAndParse(data, schema?)` - Safe validation without throwing errors
458
+ - `safeAsyncValidateAndParse(data, schema?)` - Safe async validation
459
+ - `getErrorMessage(error, separator?)` - Format ZodError messages
460
+ - `getSchema()` - Get current default schema
461
+ - `setSchema(schema)` - Set new default schema
462
+
463
+ ### Error Handling
464
+
465
+ Structured error handling with AVES-specific error codes:
466
+
467
+ ```typescript
468
+ import { AvesErrorHandler, AvesErrorCodes } from 'aves-sdk';
469
+
470
+ @Injectable()
471
+ export class BookingService {
472
+ constructor(
473
+ private readonly avesService: AvesService,
474
+ private readonly errorHandler: AvesErrorHandler
475
+ ) {}
476
+
477
+ async createBooking(data: CreateBookingRequest) {
478
+ try {
479
+ const response = await this.avesService.createBooking(data);
480
+ return response;
481
+ } catch (error) {
482
+ const avesError = this.errorHandler.handleHttpError(error);
483
+
484
+ switch (avesError.code) {
485
+ case AvesErrorCodes.BOOKING_NOT_FOUND:
486
+ throw new NotFoundException('Booking not found');
487
+ case AvesErrorCodes.INVALID_REQUEST_FORMAT:
488
+ throw new BadRequestException('Invalid booking data');
489
+ case AvesErrorCodes.PAYMENT_FAILED:
490
+ throw new PaymentRequiredException('Payment processing failed');
491
+ default:
492
+ throw new InternalServerErrorException(avesError.message);
493
+ }
494
+ }
495
+ }
496
+ }
497
+ ```
498
+
499
+ ## Advanced Usage
500
+
501
+ ### Custom Configuration Factory
502
+
503
+ ```typescript
504
+ @Injectable()
505
+ export class CustomAvesConfigService implements AvesOptionsFactory {
506
+ constructor(private configService: ConfigService) {}
507
+
508
+ async createAvesOptions(): Promise<AvesSdkConfig> {
509
+ // Custom logic to build configuration
510
+ return {
511
+ baseUrl: this.configService.get('AVES_BASE_URL')!,
512
+ hostId: this.configService.get('AVES_HOST_ID')!,
513
+ xtoken: await this.getTokenFromVault(),
514
+ languageCode: '01',
515
+ timeout: 60000,
516
+ };
517
+ }
518
+
519
+ private async getTokenFromVault(): Promise<string> {
520
+ // Custom token retrieval logic
521
+ return 'your-secure-token';
522
+ }
523
+ }
524
+
525
+ // Use in module
526
+ AvesModule.forRootAsync({
527
+ useClass: CustomAvesConfigService,
528
+ });
529
+ ```
530
+
531
+ ### Custom Error Interceptors
532
+
533
+ ```typescript
534
+ @Injectable()
535
+ export class AvesErrorInterceptor implements NestInterceptor {
536
+ constructor(private errorHandler: AvesErrorHandler) {}
537
+
538
+ intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
539
+ return next.handle().pipe(
540
+ catchError((error) => {
541
+ const avesError = this.errorHandler.handleHttpError(error);
542
+
543
+ // Custom error mapping
544
+ const httpStatus = this.mapAvesErrorToHttpStatus(avesError.code);
545
+
546
+ throw new HttpException(
547
+ {
548
+ message: avesError.message,
549
+ code: avesError.code,
550
+ timestamp: avesError.timestamp,
551
+ },
552
+ httpStatus
553
+ );
554
+ })
555
+ );
556
+ }
557
+
558
+ private mapAvesErrorToHttpStatus(code: string): number {
559
+ const statusMap: Record<string, number> = {
560
+ [AvesErrorCodes.BOOKING_NOT_FOUND]: 404,
561
+ [AvesErrorCodes.INVALID_REQUEST_FORMAT]: 400,
562
+ [AvesErrorCodes.PAYMENT_FAILED]: 402,
563
+ };
564
+
565
+ return statusMap[code] || 500;
566
+ }
567
+ }
568
+ ```
569
+
570
+ ### Type-Safe Mappers
571
+
572
+ ```typescript
573
+ import {
574
+ mapCustomerToXml,
575
+ mapCustomerFromXml,
576
+ mapCreateBookingToXml,
577
+ mapBookingFromXml,
578
+ } from 'aves-sdk';
579
+
580
+ // Convert clean API data to XML format
581
+ const xmlCustomer = mapCustomerToXml(cleanCustomer);
582
+ const xmlBooking = mapCreateBookingToXml(cleanBooking);
583
+
584
+ // Convert XML response to clean API format
585
+ const cleanCustomer = mapCustomerFromXml(xmlResponse);
586
+ const cleanBooking = mapBookingFromXml(xmlResponse);
587
+ ```
588
+
589
+ ## Development
590
+
591
+ ### Building
592
+
593
+ ```bash
594
+ yarn build
595
+ ```
596
+
597
+ ### Testing
598
+
599
+ ```bash
600
+ yarn test
601
+ ```
602
+
603
+ ### Linting
604
+
605
+ ```bash
606
+ yarn lint
607
+ ```
608
+
609
+ ## Migration Guide
610
+
611
+ ### From v0.x to v1.x
612
+
613
+ The SDK has been completely rewritten with clean APIs and Zod validation:
614
+
615
+ **Old (v0.x):**
616
+
617
+ ```typescript
618
+ // Complex XML interfaces
619
+ const searchRequest: SearchMasterRecordRQ = {
620
+ SearchCriteria: {
621
+ MasterRecordType: 'CUSTOMER',
622
+ SearchFields: {
623
+ Field: [
624
+ {
625
+ '@Name': 'LastName',
626
+ '@Value': 'Smith',
627
+ '@Operator': 'CONTAINS',
628
+ },
629
+ ],
630
+ },
631
+ },
632
+ };
633
+ ```
634
+
635
+ **New (v1.x):**
636
+
637
+ ```typescript
638
+ // Clean, developer-friendly interfaces
639
+ const searchRequest: SearchCustomerRequest = {
640
+ type: 'customer',
641
+ fields: [
642
+ {
643
+ name: 'LastName',
644
+ value: 'Smith',
645
+ operator: 'contains',
646
+ },
647
+ ],
648
+ };
649
+ ```
650
+
651
+ ## Contributing
652
+
653
+ 1. Fork the repository
654
+ 2. Create a feature branch
655
+ 3. Make your changes
656
+ 4. Add tests
657
+ 5. Submit a pull request
658
+
659
+ ## License
660
+
661
+ MIT License - see LICENSE file for details.
662
+
663
+ ## Support
664
+
665
+ For issues and questions:
666
+
667
+ - Create an issue on GitHub
668
+ - Check the examples in `/examples` directory
669
+ - Review the AVES technical documentation
670
+
671
+ ## Changelog
672
+
673
+ ### v1.0.0
674
+
675
+ - **Clean API Interfaces** - Developer-friendly interfaces abstracting XML complexity
676
+ - **Bidirectional Mappers** - Seamless conversion between clean and XML formats
677
+ - **AvesValidator Class** - Comprehensive validation class with sync/async methods and utility functions
678
+ - **Complete Type Safety** - Full TypeScript coverage with comprehensive interfaces for both clean API objects and XML structures, ensuring type safety throughout the entire request/response lifecycle
679
+ - **Customer Mapper** - Full `Customer` to `MasterRecord` conversion with `mapCustomerToXml`
680
+ - **Global Module** - NestJS global module for application-wide availability
681
+ - **Enhanced Error Handling** - Structured error handling with AVES-specific codes
682
+ - **Comprehensive Documentation** - Complete API reference and examples
683
+ - **Production Ready** - Enterprise-grade implementation following NestJS best practices
684
+
685
+ ### Breaking Changes from v0.x
686
+
687
+ - Replaced `class-validator` with Zod validation
688
+ - Introduced clean API interfaces alongside XML interfaces
689
+ - Added branded types for better type safety
690
+ - Updated module configuration with enhanced validation
691
+ - Improved error handling structure