aves-sdk 1.0.3 → 1.1.1
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 +264 -557
- package/dist/index.cjs +2 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3180 -1963
- package/dist/index.d.ts +3180 -1963
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/package.json +13 -6
package/README.md
CHANGED
|
@@ -1,19 +1,15 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Aves SDK
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
TypeScript SDK for integrating with the Aves XML 1.8.0 Booking API in NestJS applications. 100% type-safe, fully validated, and compliant with the official Aves XML specification.
|
|
4
4
|
|
|
5
5
|
## Features
|
|
6
6
|
|
|
7
|
-
- **
|
|
8
|
-
- **
|
|
9
|
-
- **
|
|
10
|
-
- **
|
|
11
|
-
- **
|
|
12
|
-
- **
|
|
13
|
-
- **Dependency Injection** - Interface-based DI following NestJS patterns
|
|
14
|
-
- **Clean APIs** - Developer-friendly interfaces abstracting XML complexity
|
|
15
|
-
- **Bidirectional Mappers** - Seamless conversion between clean and XML interfaces
|
|
16
|
-
- **Production Ready** - Built for npm deployment with proper exports
|
|
7
|
+
- **100% Aves XML 1.8.0 Compliant** - Exact implementation of official spec
|
|
8
|
+
- **Full Type Safety** - Discriminated unions, type narrowing, zero `any` types
|
|
9
|
+
- **Smart Interfaces** - Type-safe search with discriminated unions
|
|
10
|
+
- **Zod Validation** - Runtime validation for all requests/responses
|
|
11
|
+
- **NestJS Native** - Proper module with DI support
|
|
12
|
+
- **Production Ready** - Tested, validated, optimized bundle
|
|
17
13
|
|
|
18
14
|
## Installation
|
|
19
15
|
|
|
@@ -29,48 +25,32 @@ bun add aves-sdk
|
|
|
29
25
|
|
|
30
26
|
## Quick Start
|
|
31
27
|
|
|
32
|
-
### 1. Environment
|
|
33
|
-
|
|
34
|
-
Create a `.env` file:
|
|
28
|
+
### 1. Configure Environment
|
|
35
29
|
|
|
36
30
|
```env
|
|
37
|
-
AVES_BASE_URL=https://
|
|
31
|
+
AVES_BASE_URL=https://your-aves-instance.com
|
|
38
32
|
AVES_HOST_ID=123456
|
|
39
|
-
AVES_XTOKEN=
|
|
33
|
+
AVES_XTOKEN=your_token_here
|
|
40
34
|
AVES_LANGUAGE_CODE=01
|
|
41
|
-
AVES_TIMEOUT=30000
|
|
42
35
|
```
|
|
43
36
|
|
|
44
|
-
### 2. Module
|
|
37
|
+
### 2. Import Module
|
|
45
38
|
|
|
46
39
|
```typescript
|
|
47
40
|
import { Module } from '@nestjs/common';
|
|
48
|
-
import { ConfigModule } from '@nestjs/config';
|
|
41
|
+
import { ConfigModule, ConfigService } from '@nestjs/config';
|
|
49
42
|
import { AvesModule } from 'aves-sdk';
|
|
50
43
|
|
|
51
44
|
@Module({
|
|
52
45
|
imports: [
|
|
53
|
-
ConfigModule.forRoot({
|
|
54
|
-
isGlobal: true,
|
|
55
|
-
}),
|
|
56
|
-
// Synchronous configuration
|
|
57
|
-
AvesModule.forRoot({
|
|
58
|
-
baseUrl: process.env.AVES_BASE_URL!,
|
|
59
|
-
hostId: process.env.AVES_HOST_ID!,
|
|
60
|
-
xtoken: process.env.AVES_XTOKEN!,
|
|
61
|
-
languageCode: process.env.AVES_LANGUAGE_CODE,
|
|
62
|
-
timeout: parseInt(process.env.AVES_TIMEOUT || '30000'),
|
|
63
|
-
}),
|
|
64
|
-
|
|
65
|
-
// OR Asynchronous configuration
|
|
46
|
+
ConfigModule.forRoot({ isGlobal: true }),
|
|
66
47
|
AvesModule.forRootAsync({
|
|
67
48
|
imports: [ConfigModule],
|
|
68
|
-
useFactory: (
|
|
69
|
-
baseUrl:
|
|
70
|
-
hostId:
|
|
71
|
-
xtoken:
|
|
72
|
-
languageCode:
|
|
73
|
-
timeout: configService.get('AVES_TIMEOUT'),
|
|
49
|
+
useFactory: (config: ConfigService) => ({
|
|
50
|
+
baseUrl: config.get('AVES_BASE_URL')!,
|
|
51
|
+
hostId: config.get('AVES_HOST_ID')!,
|
|
52
|
+
xtoken: config.get('AVES_XTOKEN')!,
|
|
53
|
+
languageCode: config.get('AVES_LANGUAGE_CODE'),
|
|
74
54
|
}),
|
|
75
55
|
inject: [ConfigService],
|
|
76
56
|
}),
|
|
@@ -79,623 +59,350 @@ import { AvesModule } from 'aves-sdk';
|
|
|
79
59
|
export class AppModule {}
|
|
80
60
|
```
|
|
81
61
|
|
|
82
|
-
### 3.
|
|
62
|
+
### 3. Use the Service
|
|
83
63
|
|
|
84
64
|
```typescript
|
|
85
65
|
import { Injectable } from '@nestjs/common';
|
|
86
|
-
import {
|
|
87
|
-
AvesService,
|
|
88
|
-
SearchCustomerRequest,
|
|
89
|
-
CreateBookingRequest,
|
|
90
|
-
Customer,
|
|
91
|
-
BookingResponse,
|
|
92
|
-
} from 'aves-sdk';
|
|
66
|
+
import { AvesService, SearchCustomerRequest } from 'aves-sdk';
|
|
93
67
|
|
|
94
68
|
@Injectable()
|
|
95
69
|
export class BookingService {
|
|
96
|
-
constructor(private readonly
|
|
97
|
-
|
|
98
|
-
async
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
value: searchTerm,
|
|
105
|
-
operator: 'contains',
|
|
106
|
-
},
|
|
107
|
-
],
|
|
70
|
+
constructor(private readonly aves: AvesService) {}
|
|
71
|
+
|
|
72
|
+
async findCustomer(code: string) {
|
|
73
|
+
// Type-safe discriminated union
|
|
74
|
+
const request: SearchCustomerRequest = {
|
|
75
|
+
type: 'code',
|
|
76
|
+
code: code,
|
|
77
|
+
pagination: { pages: 50, page: 1 },
|
|
108
78
|
};
|
|
109
79
|
|
|
110
|
-
const
|
|
111
|
-
return
|
|
80
|
+
const result = await this.aves.searchCustomers(request);
|
|
81
|
+
return result.customers; // Fully typed Customer[]
|
|
112
82
|
}
|
|
83
|
+
}
|
|
84
|
+
```
|
|
113
85
|
|
|
114
|
-
|
|
115
|
-
customerId: string;
|
|
116
|
-
passengers: any[];
|
|
117
|
-
services: any[];
|
|
118
|
-
}): Promise<BookingResponse> {
|
|
119
|
-
const bookingRequest: CreateBookingRequest = {
|
|
120
|
-
type: 'individual',
|
|
121
|
-
priority: 'normal',
|
|
122
|
-
customerId: bookingData.customerId,
|
|
123
|
-
passengers: bookingData.passengers,
|
|
124
|
-
services: bookingData.services,
|
|
125
|
-
};
|
|
86
|
+
## Type-Safe Search (Discriminated Union)
|
|
126
87
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
88
|
+
The search interface uses **discriminated unions** for perfect type safety:
|
|
89
|
+
|
|
90
|
+
```typescript
|
|
91
|
+
// Search by customer code - TypeScript knows only 'code' is available
|
|
92
|
+
const searchByCode: SearchCustomerRequest = {
|
|
93
|
+
type: 'code',
|
|
94
|
+
code: '123456',
|
|
95
|
+
// Only 'code' property available - type-safe!
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
// Search by name - different fields available
|
|
99
|
+
const searchByName: SearchCustomerRequest = {
|
|
100
|
+
type: 'name',
|
|
101
|
+
name: 'Smith',
|
|
102
|
+
city: 'New York', // Optional for 'name' type
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
// Search by VAT code
|
|
106
|
+
const searchByVat: SearchCustomerRequest = {
|
|
107
|
+
type: 'vat_code',
|
|
108
|
+
vatCode: 'IT12345678',
|
|
109
|
+
phoneNumber: '+39123456', // Optional for 'vat_code' type
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
// Search by last modification date
|
|
113
|
+
const searchByDate: SearchCustomerRequest = {
|
|
114
|
+
type: 'last_mod_date',
|
|
115
|
+
from: '2025-01-01',
|
|
116
|
+
to: '2025-12-31',
|
|
117
|
+
// 'from' and 'to' are required for this type
|
|
118
|
+
};
|
|
130
119
|
```
|
|
131
120
|
|
|
132
|
-
|
|
121
|
+
### Available Search Types
|
|
133
122
|
|
|
134
|
-
|
|
123
|
+
| Type | Required Fields | Optional Fields |
|
|
124
|
+
| ------------------- | ----------------- | ---------------------------------- |
|
|
125
|
+
| `code` | `code` | `pagination` |
|
|
126
|
+
| `name` | `name` | `city`, `pagination` |
|
|
127
|
+
| `vat_code` | `vatCode` | `phoneNumber`, `pagination` |
|
|
128
|
+
| `zone` | `zipCode` | `city`, `countyCode`, `pagination` |
|
|
129
|
+
| `category` | `categoryCode` | `pagination` |
|
|
130
|
+
| `email` | `email` | `pagination` |
|
|
131
|
+
| `last_mod_date` | `from`, `to` | `pagination` |
|
|
132
|
+
| `search_field` | `searchField` | `pagination` |
|
|
133
|
+
| `external_ref_code` | `externalRefCode` | `pagination` |
|
|
134
|
+
|
|
135
|
+
## API Methods
|
|
135
136
|
|
|
136
137
|
### Customer Management
|
|
137
138
|
|
|
138
139
|
```typescript
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
id: '12345',
|
|
140
|
+
// Search customers
|
|
141
|
+
const result = await aves.searchCustomers({
|
|
142
|
+
type: 'name',
|
|
143
|
+
name: 'Rossi',
|
|
144
|
+
pagination: { pages: 25, page: 1 },
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
// Create customer
|
|
148
|
+
const customer = await aves.createCustomer({
|
|
149
|
+
id: '123456',
|
|
150
150
|
type: 'customer',
|
|
151
|
-
status: '
|
|
151
|
+
status: 'enabled',
|
|
152
152
|
personalInfo: {
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
lastName: 'Doe',
|
|
153
|
+
firstName: 'Mario',
|
|
154
|
+
lastName: 'Rossi',
|
|
156
155
|
dateOfBirth: '1990-01-01',
|
|
157
156
|
gender: 'male',
|
|
158
157
|
},
|
|
159
|
-
address: {
|
|
160
|
-
type: 'home',
|
|
161
|
-
street: '123 Main St',
|
|
162
|
-
city: 'New York',
|
|
163
|
-
postalCode: '10001',
|
|
164
|
-
country: 'US',
|
|
165
|
-
},
|
|
166
158
|
contact: {
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
number: '+1234567890',
|
|
170
|
-
},
|
|
171
|
-
email: {
|
|
172
|
-
type: 'work',
|
|
173
|
-
address: 'john.doe@example.com',
|
|
174
|
-
},
|
|
159
|
+
email: { address: 'mario.rossi@example.com' },
|
|
160
|
+
phone: { number: '+39123456789' },
|
|
175
161
|
},
|
|
176
|
-
};
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
// Update customer
|
|
165
|
+
await aves.updateCustomer(customer);
|
|
166
|
+
|
|
167
|
+
// Upsert customer (insert or update secondary fields)
|
|
168
|
+
await aves.upsertCustomer(customer);
|
|
177
169
|
```
|
|
178
170
|
|
|
179
171
|
### Booking Management
|
|
180
172
|
|
|
181
173
|
```typescript
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
const booking: CreateBookingRequest = {
|
|
191
|
-
type: 'individual',
|
|
192
|
-
priority: 'normal',
|
|
193
|
-
customerId: '12345',
|
|
174
|
+
// Create booking
|
|
175
|
+
const booking = await aves.createBooking({
|
|
176
|
+
customerId: '123456',
|
|
177
|
+
description: 'Summer vacation package',
|
|
178
|
+
startDate: '2025-07-01',
|
|
179
|
+
endDate: '2025-07-14',
|
|
180
|
+
currency: 'EUR',
|
|
194
181
|
passengers: [
|
|
195
182
|
{
|
|
196
|
-
id: '
|
|
183
|
+
id: '001',
|
|
197
184
|
type: 'adult',
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
lastName: 'Doe',
|
|
185
|
+
firstName: 'Mario',
|
|
186
|
+
lastName: 'Rossi',
|
|
201
187
|
dateOfBirth: '1990-01-01',
|
|
202
188
|
gender: 'male',
|
|
203
189
|
},
|
|
204
190
|
],
|
|
205
191
|
services: [
|
|
206
192
|
{
|
|
207
|
-
id: '
|
|
208
|
-
type: '
|
|
209
|
-
status: '
|
|
210
|
-
|
|
211
|
-
startDate: '
|
|
212
|
-
endDate: '
|
|
193
|
+
id: 'HTL001',
|
|
194
|
+
type: 'hotel',
|
|
195
|
+
status: 'pending',
|
|
196
|
+
name: 'Hotel Paradise',
|
|
197
|
+
startDate: '2025-07-01',
|
|
198
|
+
endDate: '2025-07-14',
|
|
213
199
|
},
|
|
214
200
|
],
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
### Complete Type Safety
|
|
219
|
-
|
|
220
|
-
The SDK provides **zero `any` types** and complete type safety throughout:
|
|
221
|
-
|
|
222
|
-
```typescript
|
|
223
|
-
import {
|
|
224
|
-
CreateBookingRequest,
|
|
225
|
-
Customer,
|
|
226
|
-
CustomerAddress,
|
|
227
|
-
CustomerContact,
|
|
228
|
-
} from 'aves-sdk';
|
|
229
|
-
|
|
230
|
-
// Fully type-safe customer details in booking
|
|
231
|
-
const booking: CreateBookingRequest = {
|
|
232
|
-
type: 'individual',
|
|
233
|
-
priority: 'normal',
|
|
234
|
-
customerId: '12345',
|
|
235
|
-
// customerDetails is now properly typed as Customer interface
|
|
236
|
-
customerDetails: {
|
|
237
|
-
id: 'CUST001',
|
|
238
|
-
type: 'customer',
|
|
239
|
-
status: 'active',
|
|
240
|
-
personalInfo: {
|
|
241
|
-
title: 'mr',
|
|
242
|
-
firstName: 'John',
|
|
243
|
-
lastName: 'Doe',
|
|
244
|
-
dateOfBirth: '1990-01-01',
|
|
245
|
-
gender: 'male',
|
|
246
|
-
},
|
|
247
|
-
contact: {
|
|
248
|
-
phone: {
|
|
249
|
-
type: 'mobile',
|
|
250
|
-
number: '+1234567890',
|
|
251
|
-
},
|
|
252
|
-
email: {
|
|
253
|
-
type: 'work',
|
|
254
|
-
address: 'john.doe@example.com',
|
|
255
|
-
},
|
|
256
|
-
},
|
|
257
|
-
address: {
|
|
258
|
-
type: 'home',
|
|
259
|
-
street: '123 Main St',
|
|
260
|
-
city: 'New York',
|
|
261
|
-
postalCode: '10001',
|
|
262
|
-
country: 'US',
|
|
263
|
-
},
|
|
201
|
+
statisticCodes: {
|
|
202
|
+
code2: 'USA',
|
|
203
|
+
code3: 'GEN',
|
|
264
204
|
},
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
};
|
|
268
|
-
|
|
269
|
-
// Automatic conversion to XML format with full type safety
|
|
270
|
-
const xmlBooking = mapCreateBookingToXml(booking);
|
|
271
|
-
```
|
|
272
|
-
|
|
273
|
-
## API Reference
|
|
274
|
-
|
|
275
|
-
### Core Services
|
|
276
|
-
|
|
277
|
-
#### AvesService
|
|
278
|
-
|
|
279
|
-
The main service for interacting with the AVES API with clean interfaces.
|
|
280
|
-
|
|
281
|
-
**Customer Management:**
|
|
282
|
-
|
|
283
|
-
- `searchCustomer(request: SearchCustomerRequest)` - Search for customers
|
|
284
|
-
- `createCustomer(customer: Customer)` - Create new customer
|
|
285
|
-
- `updateCustomer(customer: Customer)` - Update existing customer
|
|
286
|
-
|
|
287
|
-
**Booking Management:**
|
|
288
|
-
|
|
289
|
-
- `createBooking(request: CreateBookingRequest)` - Create new booking
|
|
290
|
-
- `updateBooking(bookingId: string, updates: Partial<CreateBookingRequest>)` - Update booking
|
|
291
|
-
- `cancelBooking(request: CancelBookingRequest)` - Cancel booking
|
|
292
|
-
- `getBooking(bookingId: string)` - Get booking details
|
|
293
|
-
|
|
294
|
-
**Payment Management:**
|
|
295
|
-
|
|
296
|
-
- `addPayment(request: AddPaymentRequest)` - Add payment to booking
|
|
297
|
-
- `getPayments(bookingId: string)` - Get payment history
|
|
298
|
-
|
|
299
|
-
**Document Management:**
|
|
300
|
-
|
|
301
|
-
- `printDocument(request: PrintDocumentRequest)` - Generate documents
|
|
302
|
-
|
|
303
|
-
#### AvesValidator
|
|
304
|
-
|
|
305
|
-
Advanced validation class for comprehensive data validation scenarios.
|
|
306
|
-
|
|
307
|
-
**Core Methods:**
|
|
308
|
-
|
|
309
|
-
- `validate(data, schema?)` - Synchronous validation with error throwing
|
|
310
|
-
- `asyncValidate(data, schema?)` - Asynchronous validation with error throwing
|
|
311
|
-
- `safeValidateAndParse(data, schema?)` - Safe validation without throwing errors
|
|
312
|
-
- `safeAsyncValidateAndParse(data, schema?)` - Safe async validation
|
|
313
|
-
|
|
314
|
-
**Utility Methods:**
|
|
205
|
+
printDocument: false,
|
|
206
|
+
sendDocumentViaEmail: false,
|
|
207
|
+
});
|
|
315
208
|
|
|
316
|
-
|
|
317
|
-
|
|
209
|
+
// Update booking header
|
|
210
|
+
await aves.updateBookingHeader('123456', 'BK/2025/001', '2025-07-01', {
|
|
211
|
+
notes: 'Updated booking notes',
|
|
212
|
+
passengers: [
|
|
213
|
+
/* updated passengers */
|
|
214
|
+
],
|
|
215
|
+
});
|
|
318
216
|
|
|
319
|
-
|
|
217
|
+
// Set booking status
|
|
218
|
+
await aves.setBookingStatus('123456', 'BK/2025/001', 'confirmed');
|
|
320
219
|
|
|
321
|
-
|
|
220
|
+
// Cancel booking
|
|
221
|
+
await aves.cancelBooking({
|
|
222
|
+
bookingId: 'BK/2025/001',
|
|
223
|
+
customerId: '123456',
|
|
224
|
+
});
|
|
225
|
+
```
|
|
322
226
|
|
|
323
|
-
|
|
227
|
+
### Document Management
|
|
324
228
|
|
|
325
|
-
|
|
326
|
-
|
|
229
|
+
```typescript
|
|
230
|
+
// Print booking documents
|
|
231
|
+
const result = await aves.printDocument({
|
|
232
|
+
bookingId: 'BK/2025/001',
|
|
233
|
+
customerId: '123456',
|
|
234
|
+
documentType: 'voucher',
|
|
235
|
+
format: 'pdf',
|
|
236
|
+
language: '01',
|
|
237
|
+
});
|
|
327
238
|
|
|
328
|
-
|
|
239
|
+
// Access generated documents
|
|
240
|
+
result.data.documents.forEach((doc) => {
|
|
241
|
+
console.log(doc.fileName);
|
|
242
|
+
console.log(doc.content); // Base64 content
|
|
243
|
+
console.log(doc.contentSize);
|
|
244
|
+
});
|
|
245
|
+
```
|
|
329
246
|
|
|
330
|
-
|
|
247
|
+
### Payment Management
|
|
331
248
|
|
|
332
249
|
```typescript
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
250
|
+
// Add payment
|
|
251
|
+
await aves.addPayment({
|
|
252
|
+
bookingId: 'BK/2025/001',
|
|
253
|
+
payments: [
|
|
254
|
+
{
|
|
255
|
+
id: 'PAY001',
|
|
256
|
+
type: 'cash',
|
|
257
|
+
status: 'confirmed',
|
|
258
|
+
amount: {
|
|
259
|
+
currency: 'EUR',
|
|
260
|
+
amount: 500.0,
|
|
261
|
+
},
|
|
262
|
+
},
|
|
263
|
+
],
|
|
264
|
+
enableMultiple: true,
|
|
265
|
+
operationType: 'absolute',
|
|
266
|
+
});
|
|
340
267
|
```
|
|
341
268
|
|
|
342
|
-
|
|
269
|
+
## Type Definitions
|
|
343
270
|
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
The SDK provides strongly-typed union types for better type safety:
|
|
271
|
+
### Customer Types
|
|
347
272
|
|
|
348
273
|
```typescript
|
|
349
|
-
type
|
|
350
|
-
type
|
|
351
|
-
type
|
|
352
|
-
type
|
|
353
|
-
type CustomerType = 'customer' | 'agent' | 'supplier';
|
|
354
|
-
type BookingType = 'individual' | 'group' | 'corporate';
|
|
274
|
+
type CustomerType = 'customer' | 'supplier' | 'voucher' | 'supplier_voucher';
|
|
275
|
+
type CustomerStatusType = 'enabled' | 'warning' | 'blacklisted' | 'disabled';
|
|
276
|
+
type PassengerType = 'adult' | 'child' | 'infant' | 'senior';
|
|
277
|
+
type GenderType = 'male' | 'female';
|
|
355
278
|
```
|
|
356
279
|
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
Enhanced date manipulation with native JavaScript Date:
|
|
280
|
+
### Booking Types
|
|
360
281
|
|
|
361
282
|
```typescript
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
isValidBookingDate,
|
|
370
|
-
} from 'aves-sdk';
|
|
371
|
-
|
|
372
|
-
// Create validated date strings
|
|
373
|
-
const dateString = createDateString('2024-01-01');
|
|
374
|
-
const dateTimeString = createDateTimeString('2024-01-01T10:30:00');
|
|
375
|
-
const timeString = createTimeString('10:30:00');
|
|
376
|
-
|
|
377
|
-
// Format dates for display
|
|
378
|
-
const formattedDate = formatDateString('2024-01-01', 'MMM dd, yyyy'); // "Jan 01, 2024"
|
|
379
|
-
|
|
380
|
-
// Validate date strings
|
|
381
|
-
const isValid = isValidDateString('2024-01-01'); // true
|
|
382
|
-
|
|
383
|
-
// AVES-specific utilities
|
|
384
|
-
const age = calculateAge('1990-01-01'); // Calculate customer age
|
|
385
|
-
const isBookingValid = isValidBookingDate('2024-06-01'); // Check if booking date is valid
|
|
283
|
+
type BookingStatusType =
|
|
284
|
+
| 'quotation'
|
|
285
|
+
| 'work_in_progress'
|
|
286
|
+
| 'confirmed'
|
|
287
|
+
| 'optioned'
|
|
288
|
+
| 'nullified'
|
|
289
|
+
| 'canceled';
|
|
386
290
|
```
|
|
387
291
|
|
|
388
|
-
###
|
|
389
|
-
|
|
390
|
-
Built-in Zod validation with descriptive error messages:
|
|
292
|
+
### Document Types
|
|
391
293
|
|
|
392
294
|
```typescript
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
SearchCustomerRequestValidation.safeParse(searchRequest);
|
|
409
|
-
const bookingValidation =
|
|
410
|
-
CreateBookingRequestValidation.safeParse(bookingRequest);
|
|
295
|
+
type DocumentType =
|
|
296
|
+
| 'visa_request'
|
|
297
|
+
| 'travel_information'
|
|
298
|
+
| 'voucher'
|
|
299
|
+
| 'booking_contract'
|
|
300
|
+
| 'booking_confirmation'
|
|
301
|
+
| 'supplier_service_list'
|
|
302
|
+
| 'invoice'
|
|
303
|
+
| 'proforma_invoice'
|
|
304
|
+
| 'adeguamento'
|
|
305
|
+
| 'reservation_form'
|
|
306
|
+
| 'open_xml'
|
|
307
|
+
| 'sales_invoice'
|
|
308
|
+
| 'ticketing_tmaster'
|
|
309
|
+
| 'summary_form';
|
|
411
310
|
```
|
|
412
311
|
|
|
413
|
-
|
|
312
|
+
## Response Interfaces
|
|
414
313
|
|
|
415
|
-
|
|
314
|
+
### Search Response with Pagination
|
|
416
315
|
|
|
417
316
|
```typescript
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
// Synchronous validation with error throwing
|
|
428
|
-
try {
|
|
429
|
-
const validConfig = configValidator.validate(configData);
|
|
430
|
-
console.log('Valid config:', validConfig);
|
|
431
|
-
} catch (error) {
|
|
432
|
-
if (error instanceof ZodError) {
|
|
433
|
-
console.error('Validation errors:', configValidator.getErrorMessage(error));
|
|
434
|
-
}
|
|
435
|
-
}
|
|
436
|
-
|
|
437
|
-
// Safe validation without throwing errors
|
|
438
|
-
const result = configValidator.safeValidateAndParse(configData);
|
|
439
|
-
if (result.success) {
|
|
440
|
-
console.log('Valid config:', result.data);
|
|
441
|
-
} else {
|
|
442
|
-
console.error('Validation errors:', result.error.issues);
|
|
317
|
+
interface CustomerSearchResult {
|
|
318
|
+
customers: Customer[];
|
|
319
|
+
pagination: {
|
|
320
|
+
page: number; // Current page
|
|
321
|
+
pages: number; // Minimum known pages
|
|
322
|
+
totalItems: number; // Items in this response
|
|
323
|
+
hasMore: boolean; // More results available
|
|
324
|
+
};
|
|
443
325
|
}
|
|
444
|
-
|
|
445
|
-
// Asynchronous validation
|
|
446
|
-
const asyncResult = await configValidator.asyncValidate(configData);
|
|
447
|
-
|
|
448
|
-
// Method approach - validator without default schema
|
|
449
|
-
const validator = new AvesValidator();
|
|
450
|
-
|
|
451
|
-
// Validate with different schemas
|
|
452
|
-
const configResult = validator.validate(configData, configValidationSchema);
|
|
453
|
-
const searchResult = validator.safeValidateAndParse(
|
|
454
|
-
searchData,
|
|
455
|
-
SearchCustomerRequestValidation
|
|
456
|
-
);
|
|
457
|
-
|
|
458
|
-
// Factory function approach
|
|
459
|
-
const validator = createValidator(configValidationSchema);
|
|
460
|
-
const result = validator.validate(configData);
|
|
461
326
|
```
|
|
462
327
|
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
- `validate(data, schema?)` - Synchronous validation with error throwing
|
|
466
|
-
- `asyncValidate(data, schema?)` - Asynchronous validation with error throwing
|
|
467
|
-
- `safeValidateAndParse(data, schema?)` - Safe validation without throwing errors
|
|
468
|
-
- `safeAsyncValidateAndParse(data, schema?)` - Safe async validation
|
|
469
|
-
- `getErrorMessage(error, separator?)` - Format ZodError messages
|
|
470
|
-
- `getSchema()` - Get current default schema
|
|
471
|
-
- `setSchema(schema)` - Set new default schema
|
|
472
|
-
|
|
473
|
-
### Error Handling
|
|
474
|
-
|
|
475
|
-
Structured error handling with AVES-specific error codes:
|
|
328
|
+
### Document Print Result
|
|
476
329
|
|
|
477
330
|
```typescript
|
|
478
|
-
|
|
331
|
+
interface DocumentPrintResult {
|
|
332
|
+
emailRecipient?: string;
|
|
333
|
+
documents: PrintedDocument[];
|
|
334
|
+
additionalDocuments?: {
|
|
335
|
+
emailRecipient: string;
|
|
336
|
+
documents: PrintedDocument[];
|
|
337
|
+
}[];
|
|
338
|
+
}
|
|
479
339
|
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
private readonly errorHandler: AvesErrorHandler
|
|
485
|
-
) {}
|
|
486
|
-
|
|
487
|
-
async createBooking(data: CreateBookingRequest) {
|
|
488
|
-
try {
|
|
489
|
-
const response = await this.avesService.createBooking(data);
|
|
490
|
-
return response;
|
|
491
|
-
} catch (error) {
|
|
492
|
-
const avesError = this.errorHandler.handleHttpError(error);
|
|
493
|
-
|
|
494
|
-
switch (avesError.code) {
|
|
495
|
-
case AvesErrorCodes.BOOKING_NOT_FOUND:
|
|
496
|
-
throw new NotFoundException('Booking not found');
|
|
497
|
-
case AvesErrorCodes.INVALID_REQUEST_FORMAT:
|
|
498
|
-
throw new BadRequestException('Invalid booking data');
|
|
499
|
-
case AvesErrorCodes.PAYMENT_FAILED:
|
|
500
|
-
throw new PaymentRequiredException('Payment processing failed');
|
|
501
|
-
default:
|
|
502
|
-
throw new InternalServerErrorException(avesError.message);
|
|
503
|
-
}
|
|
504
|
-
}
|
|
505
|
-
}
|
|
340
|
+
interface PrintedDocument {
|
|
341
|
+
fileName: string;
|
|
342
|
+
content?: string; // Base64 content
|
|
343
|
+
contentSize: number;
|
|
506
344
|
}
|
|
507
345
|
```
|
|
508
346
|
|
|
509
|
-
##
|
|
347
|
+
## Validation
|
|
510
348
|
|
|
511
|
-
|
|
349
|
+
All requests are validated using Zod schemas:
|
|
512
350
|
|
|
513
351
|
```typescript
|
|
514
|
-
|
|
515
|
-
export class CustomAvesConfigService implements AvesOptionsFactory {
|
|
516
|
-
constructor(private configService: ConfigService) {}
|
|
517
|
-
|
|
518
|
-
async createAvesOptions(): Promise<AvesSdkConfig> {
|
|
519
|
-
// Custom logic to build configuration
|
|
520
|
-
return {
|
|
521
|
-
baseUrl: this.configService.get('AVES_BASE_URL')!,
|
|
522
|
-
hostId: this.configService.get('AVES_HOST_ID')!,
|
|
523
|
-
xtoken: await this.getTokenFromVault(),
|
|
524
|
-
languageCode: '01',
|
|
525
|
-
timeout: 60000,
|
|
526
|
-
};
|
|
527
|
-
}
|
|
352
|
+
import { searchCustomerRequestSchema } from 'aves-sdk';
|
|
528
353
|
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
}
|
|
354
|
+
const result = searchCustomerRequestSchema.safeParse(request);
|
|
355
|
+
if (!result.success) {
|
|
356
|
+
console.error(result.error.issues);
|
|
533
357
|
}
|
|
534
|
-
|
|
535
|
-
// Use in module
|
|
536
|
-
AvesModule.forRootAsync({
|
|
537
|
-
useClass: CustomAvesConfigService,
|
|
538
|
-
});
|
|
539
358
|
```
|
|
540
359
|
|
|
541
|
-
|
|
360
|
+
## Error Handling
|
|
542
361
|
|
|
543
362
|
```typescript
|
|
544
|
-
|
|
545
|
-
export class AvesErrorInterceptor implements NestInterceptor {
|
|
546
|
-
constructor(private errorHandler: AvesErrorHandler) {}
|
|
547
|
-
|
|
548
|
-
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
|
|
549
|
-
return next.handle().pipe(
|
|
550
|
-
catchError((error) => {
|
|
551
|
-
const avesError = this.errorHandler.handleHttpError(error);
|
|
552
|
-
|
|
553
|
-
// Custom error mapping
|
|
554
|
-
const httpStatus = this.mapAvesErrorToHttpStatus(avesError.code);
|
|
555
|
-
|
|
556
|
-
throw new HttpException(
|
|
557
|
-
{
|
|
558
|
-
message: avesError.message,
|
|
559
|
-
code: avesError.code,
|
|
560
|
-
timestamp: avesError.timestamp,
|
|
561
|
-
},
|
|
562
|
-
httpStatus
|
|
563
|
-
);
|
|
564
|
-
})
|
|
565
|
-
);
|
|
566
|
-
}
|
|
567
|
-
|
|
568
|
-
private mapAvesErrorToHttpStatus(code: string): number {
|
|
569
|
-
const statusMap: Record<string, number> = {
|
|
570
|
-
[AvesErrorCodes.BOOKING_NOT_FOUND]: 404,
|
|
571
|
-
[AvesErrorCodes.INVALID_REQUEST_FORMAT]: 400,
|
|
572
|
-
[AvesErrorCodes.PAYMENT_FAILED]: 402,
|
|
573
|
-
};
|
|
363
|
+
import { AvesErrorHandler, AvesErrorCodes } from 'aves-sdk';
|
|
574
364
|
|
|
575
|
-
|
|
576
|
-
|
|
365
|
+
try {
|
|
366
|
+
const booking = await aves.createBooking(request);
|
|
367
|
+
} catch (error) {
|
|
368
|
+
const avesError = errorHandler.handleHttpError(error);
|
|
369
|
+
console.error(avesError.code, avesError.message);
|
|
577
370
|
}
|
|
578
371
|
```
|
|
579
372
|
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
```typescript
|
|
583
|
-
import {
|
|
584
|
-
mapCustomerToXml,
|
|
585
|
-
mapCustomerFromXml,
|
|
586
|
-
mapCreateBookingToXml,
|
|
587
|
-
mapBookingFromXml,
|
|
588
|
-
} from 'aves-sdk';
|
|
589
|
-
|
|
590
|
-
// Convert clean API data to XML format
|
|
591
|
-
const xmlCustomer = mapCustomerToXml(cleanCustomer);
|
|
592
|
-
const xmlBooking = mapCreateBookingToXml(cleanBooking);
|
|
593
|
-
|
|
594
|
-
// Convert XML response to clean API format
|
|
595
|
-
const cleanCustomer = mapCustomerFromXml(xmlResponse);
|
|
596
|
-
const cleanBooking = mapBookingFromXml(xmlResponse);
|
|
597
|
-
```
|
|
598
|
-
|
|
599
|
-
## Development
|
|
373
|
+
## Bundle Size
|
|
600
374
|
|
|
601
|
-
|
|
375
|
+
Optimized for production:
|
|
602
376
|
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
377
|
+
- **ESM**: 51.75 KB (gzipped)
|
|
378
|
+
- **CJS**: 55.13 KB (gzipped)
|
|
379
|
+
- **DTS**: 137.03 KB
|
|
606
380
|
|
|
607
|
-
|
|
381
|
+
## Architecture
|
|
608
382
|
|
|
609
|
-
```bash
|
|
610
|
-
yarn test
|
|
611
383
|
```
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
384
|
+
aves-sdk/
|
|
385
|
+
├── validation/
|
|
386
|
+
│ └── api-schemas.ts # Zod schemas + inferred types (single source of truth)
|
|
387
|
+
├── types/
|
|
388
|
+
│ ├── interfaces.ts # XML layer (Aves API)
|
|
389
|
+
│ └── common.ts # Shared types
|
|
390
|
+
├── mappers/
|
|
391
|
+
│ ├── request-mappers.ts # API → XML
|
|
392
|
+
│ ├── response-mappers.ts # XML → API
|
|
393
|
+
│ └── type-mappers.ts # Enum conversions
|
|
394
|
+
├── nest/
|
|
395
|
+
│ ├── aves.module.ts # NestJS module
|
|
396
|
+
│ └── aves.service.ts # Main service
|
|
397
|
+
└── config/
|
|
398
|
+
├── endpoints.ts # API endpoints
|
|
399
|
+
└── root-elements.ts # XML root elements
|
|
617
400
|
```
|
|
618
401
|
|
|
619
|
-
## Migration Guide
|
|
620
|
-
|
|
621
|
-
### From v0.x to v1.x
|
|
622
|
-
|
|
623
|
-
The SDK has been completely rewritten with clean APIs and Zod validation:
|
|
624
|
-
|
|
625
|
-
**Old (v0.x):**
|
|
626
|
-
|
|
627
|
-
```typescript
|
|
628
|
-
// Complex XML interfaces
|
|
629
|
-
const searchRequest: SearchMasterRecordRQ = {
|
|
630
|
-
SearchCriteria: {
|
|
631
|
-
MasterRecordType: 'CUSTOMER',
|
|
632
|
-
SearchFields: {
|
|
633
|
-
Field: [
|
|
634
|
-
{
|
|
635
|
-
'@Name': 'LastName',
|
|
636
|
-
'@Value': 'Smith',
|
|
637
|
-
'@Operator': 'CONTAINS',
|
|
638
|
-
},
|
|
639
|
-
],
|
|
640
|
-
},
|
|
641
|
-
},
|
|
642
|
-
};
|
|
643
|
-
```
|
|
644
|
-
|
|
645
|
-
**New (v1.x):**
|
|
646
|
-
|
|
647
|
-
```typescript
|
|
648
|
-
// Clean, developer-friendly interfaces
|
|
649
|
-
const searchRequest: SearchCustomerRequest = {
|
|
650
|
-
type: 'customer',
|
|
651
|
-
fields: [
|
|
652
|
-
{
|
|
653
|
-
name: 'LastName',
|
|
654
|
-
value: 'Smith',
|
|
655
|
-
operator: 'contains',
|
|
656
|
-
},
|
|
657
|
-
],
|
|
658
|
-
};
|
|
659
|
-
```
|
|
660
|
-
|
|
661
|
-
## Contributing
|
|
662
|
-
|
|
663
|
-
1. Fork the repository
|
|
664
|
-
2. Create a feature branch
|
|
665
|
-
3. Make your changes
|
|
666
|
-
4. Add tests
|
|
667
|
-
5. Submit a pull request
|
|
668
|
-
|
|
669
402
|
## License
|
|
670
403
|
|
|
671
|
-
MIT
|
|
672
|
-
|
|
673
|
-
## Support
|
|
674
|
-
|
|
675
|
-
For issues and questions:
|
|
676
|
-
|
|
677
|
-
- Create an issue on GitHub
|
|
678
|
-
- Check the examples in `/examples` directory
|
|
679
|
-
- Review the AVES technical documentation
|
|
680
|
-
|
|
681
|
-
## Changelog
|
|
682
|
-
|
|
683
|
-
### v1.0.0
|
|
684
|
-
|
|
685
|
-
- **Clean API Interfaces** - Developer-friendly interfaces abstracting XML complexity
|
|
686
|
-
- **Bidirectional Mappers** - Seamless conversion between clean and XML formats
|
|
687
|
-
- **AvesValidator Class** - Comprehensive validation class with sync/async methods and utility functions
|
|
688
|
-
- **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
|
|
689
|
-
- **Customer Mapper** - Full `Customer` to `MasterRecord` conversion with `mapCustomerToXml`
|
|
690
|
-
- **Global Module** - NestJS global module for application-wide availability
|
|
691
|
-
- **Enhanced Error Handling** - Structured error handling with AVES-specific codes
|
|
692
|
-
- **Comprehensive Documentation** - Complete API reference and examples
|
|
693
|
-
- **Production Ready** - Enterprise-grade implementation following NestJS best practices
|
|
404
|
+
MIT
|
|
694
405
|
|
|
695
|
-
|
|
406
|
+
## Credits
|
|
696
407
|
|
|
697
|
-
|
|
698
|
-
- Introduced clean API interfaces alongside XML interfaces
|
|
699
|
-
- Enhanced date utilities with native JavaScript Date
|
|
700
|
-
- Updated module configuration with enhanced validation
|
|
701
|
-
- Improved error handling structure
|
|
408
|
+
Built for the Aves XML 1.8.0 Booking CPX API specification.
|