aves-sdk 4.0.0 → 5.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/CHANGELOG.md +136 -1
- package/README.md +169 -51
- package/dist/CHANGELOG.md +538 -0
- package/dist/index.d.mts +7122 -20872
- package/dist/index.mjs +1 -1
- package/package.json +5 -4
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,118 @@ All notable changes to this project are documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
<a id="v5.0.0"></a>
|
|
9
|
+
## [5.0.0] - 2026-08-24
|
|
10
|
+
|
|
11
|
+
Effect-native core: **Effect Schema** + **`@effect/platform` HttpClient**, Promise `Result` facade at the edge, optional Layers / `ManagedRuntime` for Effect apps.
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
|
|
15
|
+
- `makeAvesRuntime(options, deps?)` — `ManagedRuntime` over `avesClientLayer` for `yield* AvesBooking` / `AvesMaster` / `AvesPackages` / `AvesTransport`
|
|
16
|
+
- `avesClientLayer` / `AvesClientLive` — composable Effect Layers (`config → http → transport → domains`)
|
|
17
|
+
- Domain Tags: `AvesBooking`, `AvesMaster`, `AvesPackages`, `AvesTransport`, `AvesHttp`, `AvesConfig`
|
|
18
|
+
- `createAvesClient` — plain-object Promise facade (same shape as `AvesClient`)
|
|
19
|
+
- Public `Result` / `ok` / `err`; `isAvesError`; tagged errors `AvesValidationError` / `AvesApiError` / `AvesUnknownError` (+ factories)
|
|
20
|
+
- Test DI: `deps.httpClient` (`HttpClient.make`) and/or `deps.http` / domain service overrides
|
|
21
|
+
|
|
22
|
+
### Changed
|
|
23
|
+
|
|
24
|
+
- **Breaking:** Validation stack is **Effect Schema** (`effect`). Valibot is removed.
|
|
25
|
+
- **Breaking:** HTTP is **`@effect/platform`** (`FetchHttpClient` by default). Undici is no longer a dependency; do not use `MockAgent` / `setGlobalDispatcher` for SDK tests — inject `HttpClient.make` via `deps.httpClient`.
|
|
26
|
+
- **Breaking:** Domains are Effect-native (`Effect.Effect<…, AvesError>`). The Promise API is a thin `toPromiseFacade` edge on `createAvesClient` / `AvesClient`.
|
|
27
|
+
- **Breaking:** `client.transport` is **removed** from the Promise facade. Effect programs use `yield* AvesTransport` (or domain Tags) with `makeAvesRuntime` / `avesClientLayer`.
|
|
28
|
+
- **Breaking:** `AvesError` is a **tagged union**, not a single constructible class. Prefer `isAvesError(e)`, `e instanceof AvesApiError`, or `Effect.catchTag("AvesApiError", …)`. Promise `error.kind` (`validation` | `api` | `unknown`) is unchanged.
|
|
29
|
+
- **Breaking:** DI no longer uses `new AvesTransport(options)` / `new BookingClient(transport)`. Use `AvesClientDeps`: `{ httpClient?, http?, transport?, master?, booking?, packages? }`.
|
|
30
|
+
- Internal layout: `src/client/{booking,master,packages,http,transport,config}/` (types / tag / service / layer).
|
|
31
|
+
- Published types shrank from 1.21 MB to 404 kB (npm tarball 115 kB → 72 kB): op params/results and the domain service types are now written against named types instead of inferred, so the declaration bundle references `BookingInput` & co. instead of inlining every schema structure. The public API is unchanged — `src/client/{ops,services}.test-d.ts` pin each op and domain method against the schema the transport actually uses.
|
|
32
|
+
|
|
33
|
+
### Migration (4.x → 5.x)
|
|
34
|
+
|
|
35
|
+
1. **Install** — `aves-sdk@5` pulls `effect` and `@effect/platform`. No Valibot/undici required.
|
|
36
|
+
2. **Promise apps** — keep `new AvesClient(options)` / `createAvesClient(options)`. Import `Result` from `aves-sdk` if you typed it locally. Stop reading `client.transport`.
|
|
37
|
+
3. **Errors** — replace `instanceof AvesError` with `isAvesError(error)` (or the concrete tagged class). `error.kind` / `message` / `status` / `code` still work on the Promise path.
|
|
38
|
+
4. **Tests / DI** — replace undici `MockAgent` with platform mocks:
|
|
39
|
+
|
|
40
|
+
```ts
|
|
41
|
+
import { HttpClient, HttpClientResponse } from "@effect/platform";
|
|
42
|
+
import { Effect } from "effect";
|
|
43
|
+
import { AvesClient } from "aves-sdk";
|
|
44
|
+
|
|
45
|
+
const httpClient = HttpClient.make((request, url) =>
|
|
46
|
+
Effect.succeed(
|
|
47
|
+
HttpClientResponse.fromWeb(
|
|
48
|
+
request,
|
|
49
|
+
new Response(`<SearchMasterRecordRS><RsStatus Status="OK"/></SearchMasterRecordRS>`, {
|
|
50
|
+
status: 200,
|
|
51
|
+
}),
|
|
52
|
+
),
|
|
53
|
+
),
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
const client = new AvesClient(options, { httpClient });
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
5. **Effect apps** — use Layers instead of the Promise facade:
|
|
60
|
+
|
|
61
|
+
```ts
|
|
62
|
+
import { Effect } from "effect";
|
|
63
|
+
import { AvesMaster, makeAvesRuntime } from "aves-sdk";
|
|
64
|
+
|
|
65
|
+
const runtime = makeAvesRuntime(options);
|
|
66
|
+
const records = await runtime.runPromise(
|
|
67
|
+
Effect.gen(function* () {
|
|
68
|
+
const master = yield* AvesMaster;
|
|
69
|
+
return yield* master.search({ searchType: "CODE", recordCode: "508558" });
|
|
70
|
+
}),
|
|
71
|
+
);
|
|
72
|
+
await runtime.dispose();
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Or `Effect.provide(avesClientLayer(options, deps))` without a ManagedRuntime. Recover with `Effect.catchTag("AvesApiError", …)` / `"AvesValidationError"` / `"AvesUnknownError"`.
|
|
76
|
+
|
|
77
|
+
XML wire shapes, facade aliases, and domain method names from 4.x are unchanged.
|
|
78
|
+
|
|
79
|
+
<a id="v4.1.0"></a>
|
|
80
|
+
## [4.1.0] - 2026-08-07
|
|
81
|
+
|
|
82
|
+
### Added
|
|
83
|
+
|
|
84
|
+
- `client.booking.exportData(params)` — **ExportBookingData** (`BookingDataExportRQ` / `BookingDataExportRS`). The only AVES operation that reads a booking file back whole: header, passengers, booked services with per-line `amountsDetail`, file-level `bookedFileAmounts`, and **registered payments**. `addPayments` finally has a read counterpart.
|
|
85
|
+
- `ExtraInfo` lookup tables on the response: `currencyList`, `vatList`, `nationList`, `travelAgentList`, `programList`, `statisticList`, `priceOffertList`, `userList`, `passengerCategoryList`, `masterDataSet`, `masterDataSetExtraInfo`. `nationList[].territoriality` (`IN_UE` / `OUT_UE` / `MIXED_UE`) is the VAT-regime input.
|
|
86
|
+
- Object enums (+ schemas) for every closed picklist the export returns: `ExportType`, `Territoriality`, `StatisticType`, `ToSubServiceType`, `SellingType`, `Printable`, `PrintType`, `DeadlineStatus`, `CommissionIncomeType`, `CommissionOwedType`.
|
|
87
|
+
- `RecordTypeWire` — `RecordType` plus `NOT_SET`, for read responses. Mirrors the existing `BookingFileStatus` / `BookingFileStatusWire` split.
|
|
88
|
+
- Remaining documented export structures are now typed: `customerProcessedPrintList`, `instalmentPlanList`, `supplierInstalmentPlanList`, file- and service-level `deadlineList`, `commissionIncomeDetails`, `commissionOwedDetails`.
|
|
89
|
+
- Types `ExportBookingDataRQ` / `ExportBookingDataRS`, `ExportedBookingFile`, `ExportExtraInfo`, and facade aliases `BookingExportInput` / `BookingExportResult`.
|
|
90
|
+
- Facade output aliases: `bookingFileList` → `bookings`, `bookedServices` → `services`, `amountsDetail` → `amounts`, `bookedFileAmounts` → `totals`.
|
|
91
|
+
|
|
92
|
+
### Fixed
|
|
93
|
+
|
|
94
|
+
- `master.search` / `master.upsert` responses no longer reject a record whose `RecordType` is `NOT_SET`. The response validation schema was reusing the request picklist, which omits it. Server-only fields AVES returns on read (`AreaCode`, `LastDateContact`, `UseSupplierDataOnTravelDoc`, `BookingEnabled`, `PrivacyPolicyAccepted`, and the misspelled `ModifitedDate`) are no longer dropped.
|
|
95
|
+
|
|
96
|
+
Note for TypeScript consumers: `MasterRecordDetailResponse["recordType"]` widens from `RecordType` to `RecordTypeWire`, so an exhaustive `switch` over it now needs a `NOT_SET` branch. Input types are unchanged.
|
|
97
|
+
- Facade arrays now expose public aliases when **iterated**, not only when indexed. `withPublicAliases` bound array methods to the raw target, so `for…of`, destructuring, spread, `Array.from`, `map`, `filter`, `find`, `forEach` and `at` all handed back rows without their alias keys — `const [p] = result.data.payments` yielded a row with `paymentDate` but no aliases, while `result.data.payments[0]` worked. Methods now run with `this` bound to the proxy. This also makes `indexOf` / `includes` consistent: `arr.indexOf(arr[0])` returned `-1` before, since it compared wrapped items against raw ones.
|
|
98
|
+
|
|
99
|
+
### Changed
|
|
100
|
+
|
|
101
|
+
- `BoolishSchema` moved from `schemas/booking-shared.ts` to `schemas/common.ts`, next to `StringishSchema` — it is a cross-domain wire primitive, and `master-record` / `package-catalog` were already importing it out of the booking module. Internal only; it is not part of the published entry point.
|
|
102
|
+
|
|
103
|
+
### Notes
|
|
104
|
+
|
|
105
|
+
- Request roots are `BookingDataExport*`, not `ExportBookingData*`: the spec's section tables name the endpoint, while its index and both worked XML examples name the elements.
|
|
106
|
+
- `limitRange` enforces the documented bounds (`skip` ≥ 0, `take` ≤ 1000) before the request leaves the SDK.
|
|
107
|
+
- Wire misspellings are normalized on the way in: `PaumentNote` → `paymentNote`, `FirstConfemationDate` → `firstConfirmationDate`, `UsersList` → `userList`, `TOSubServiceType` → `toSubServiceType`.
|
|
108
|
+
- `extraInfo.masterDataSet` rows validate as full master records, reusing the schema behind `master.search`.
|
|
109
|
+
- `regimeType` and `customerPayAt` are the only response fields left as plain strings: Booking.txt:11312 documents no value list for the first, and the second appears nowhere in the response table — only in the example, as `OUR_AGENCY`. There is nothing to validate against; an enum built from one sample would reject every other value.
|
|
110
|
+
- `Printable` values are rejoined from a spec table that hard-wraps identifiers mid-token. If a live response is ever rejected on that field, check the reconstruction against Booking.txt:11261-11289 first.
|
|
111
|
+
|
|
112
|
+
<a id="v4.0.1"></a>
|
|
113
|
+
## [4.0.1] - 2026-08-06
|
|
114
|
+
|
|
115
|
+
### Added
|
|
116
|
+
|
|
117
|
+
- Copy `CHANGELOG.md` into `dist/` on build (`tsdown` `copy`) and include `dist/CHANGELOG.md` in published `files`.
|
|
118
|
+
|
|
119
|
+
<a id="v4.0.0"></a>
|
|
8
120
|
## [4.0.0] - 2026-08-06
|
|
9
121
|
|
|
10
122
|
### Added
|
|
@@ -50,6 +162,7 @@ await client.packages.search(params);
|
|
|
50
162
|
await client.master.upsert(record);
|
|
51
163
|
```
|
|
52
164
|
|
|
165
|
+
<a id="v3.1.1"></a>
|
|
53
166
|
## [3.1.1] - 2026-08-06
|
|
54
167
|
|
|
55
168
|
### Added
|
|
@@ -70,9 +183,10 @@ await client.master.upsert(record);
|
|
|
70
183
|
- WeakMap cache for `itemShape` / `encodeShapeFor` on static WireShape refs.
|
|
71
184
|
- `toWireBody` single shape-driven walk (list wrap + pax normalize + wire keys).
|
|
72
185
|
- Zero-copy `withPublicAliases` via hardened lazy Proxy (WeakMap identity, proto-pollution blocked).
|
|
73
|
-
-
|
|
186
|
+
- `createResponseSchema` camelizes Valibot output **in place** (`pascalToCamelKeysInPlace`) — no second deep-copy.
|
|
74
187
|
- Performance harness: `yarn test:bench` (Vitest bench) and `AVES_PERF=1 yarn test:perf` (relative hot-path asserts).
|
|
75
188
|
|
|
189
|
+
<a id="v3.0.0"></a>
|
|
76
190
|
## [3.0.0] - 2026-08-06
|
|
77
191
|
|
|
78
192
|
### Changed
|
|
@@ -119,6 +233,7 @@ if (result.success) {
|
|
|
119
233
|
|
|
120
234
|
3.1.x on top of 3.0 is additive (facade aliases / internal transport). No further breaking migration from 3.0 → 3.1.1.
|
|
121
235
|
|
|
236
|
+
<a id="v2.0.1"></a>
|
|
122
237
|
## [2.0.1] - 2026-08-05
|
|
123
238
|
|
|
124
239
|
### Changed
|
|
@@ -126,6 +241,7 @@ if (result.success) {
|
|
|
126
241
|
- Omit source maps from the published package; `files` now ships only
|
|
127
242
|
`dist/index.mjs` and `dist/index.d.mts`.
|
|
128
243
|
|
|
244
|
+
<a id="v2.0.0"></a>
|
|
129
245
|
## [2.0.0] - 2026-08-05
|
|
130
246
|
|
|
131
247
|
### Changed
|
|
@@ -149,6 +265,7 @@ if (result.success) {
|
|
|
149
265
|
|
|
150
266
|
---
|
|
151
267
|
|
|
268
|
+
<a id="v1.9.0"></a>
|
|
152
269
|
## [1.9.0] - 2026-08-03
|
|
153
270
|
|
|
154
271
|
### Changed
|
|
@@ -169,6 +286,7 @@ if (result.success) {
|
|
|
169
286
|
|
|
170
287
|
---
|
|
171
288
|
|
|
289
|
+
<a id="v1.8.0"></a>
|
|
172
290
|
## [1.8.0] - 2026-08-03
|
|
173
291
|
|
|
174
292
|
### Added
|
|
@@ -184,6 +302,7 @@ if (result.success) {
|
|
|
184
302
|
|
|
185
303
|
---
|
|
186
304
|
|
|
305
|
+
<a id="v1.7.0"></a>
|
|
187
306
|
## [1.7.0] - 2026-08-03
|
|
188
307
|
|
|
189
308
|
### Added
|
|
@@ -212,6 +331,7 @@ if (result.success) {
|
|
|
212
331
|
|
|
213
332
|
---
|
|
214
333
|
|
|
334
|
+
<a id="v1.6.0"></a>
|
|
215
335
|
## [1.6.0] - 2026-07-29
|
|
216
336
|
|
|
217
337
|
### Changed
|
|
@@ -223,6 +343,7 @@ if (result.success) {
|
|
|
223
343
|
|
|
224
344
|
---
|
|
225
345
|
|
|
346
|
+
<a id="v1.5.1"></a>
|
|
226
347
|
## [1.5.1] - 2026-07-29
|
|
227
348
|
|
|
228
349
|
### Changed
|
|
@@ -232,6 +353,7 @@ if (result.success) {
|
|
|
232
353
|
|
|
233
354
|
---
|
|
234
355
|
|
|
356
|
+
<a id="v1.5.0"></a>
|
|
235
357
|
## [1.5.0] - 2026-07-29
|
|
236
358
|
|
|
237
359
|
### Added
|
|
@@ -242,6 +364,7 @@ if (result.success) {
|
|
|
242
364
|
|
|
243
365
|
---
|
|
244
366
|
|
|
367
|
+
<a id="v1.4.0"></a>
|
|
245
368
|
## [1.4.0] - 2026-07-29
|
|
246
369
|
|
|
247
370
|
### Added
|
|
@@ -256,6 +379,7 @@ if (result.success) {
|
|
|
256
379
|
|
|
257
380
|
---
|
|
258
381
|
|
|
382
|
+
<a id="v1.3.4"></a>
|
|
259
383
|
## [1.3.4] - 2026-03-09
|
|
260
384
|
|
|
261
385
|
### Added
|
|
@@ -273,6 +397,7 @@ if (result.success) {
|
|
|
273
397
|
|
|
274
398
|
---
|
|
275
399
|
|
|
400
|
+
<a id="v1.3.3"></a>
|
|
276
401
|
## [1.3.3] - 2026-02-26
|
|
277
402
|
|
|
278
403
|
### Fixed
|
|
@@ -281,6 +406,7 @@ if (result.success) {
|
|
|
281
406
|
|
|
282
407
|
---
|
|
283
408
|
|
|
409
|
+
<a id="v1.3.2"></a>
|
|
284
410
|
## [1.3.2] - 2026-02-10
|
|
285
411
|
|
|
286
412
|
### Added
|
|
@@ -294,6 +420,7 @@ if (result.success) {
|
|
|
294
420
|
|
|
295
421
|
---
|
|
296
422
|
|
|
423
|
+
<a id="v1.3.1"></a>
|
|
297
424
|
## [1.3.1] - 2026-02-01
|
|
298
425
|
|
|
299
426
|
### Changed
|
|
@@ -303,6 +430,7 @@ if (result.success) {
|
|
|
303
430
|
|
|
304
431
|
---
|
|
305
432
|
|
|
433
|
+
<a id="v1.3.0"></a>
|
|
306
434
|
## [1.3.0] - 2026-02-01
|
|
307
435
|
|
|
308
436
|
### Added
|
|
@@ -318,6 +446,7 @@ if (result.success) {
|
|
|
318
446
|
|
|
319
447
|
---
|
|
320
448
|
|
|
449
|
+
<a id="v1.2.16"></a>
|
|
321
450
|
## [1.2.16] - 2026-01-27
|
|
322
451
|
|
|
323
452
|
### Changed
|
|
@@ -326,6 +455,7 @@ if (result.success) {
|
|
|
326
455
|
|
|
327
456
|
---
|
|
328
457
|
|
|
458
|
+
<a id="v1.2.15"></a>
|
|
329
459
|
## [1.2.15] - 2026-01-27
|
|
330
460
|
|
|
331
461
|
### Fixed
|
|
@@ -334,6 +464,7 @@ if (result.success) {
|
|
|
334
464
|
|
|
335
465
|
---
|
|
336
466
|
|
|
467
|
+
<a id="v1.2.14"></a>
|
|
337
468
|
## [1.2.14] - 2026-01-27
|
|
338
469
|
|
|
339
470
|
### Changed
|
|
@@ -342,6 +473,7 @@ if (result.success) {
|
|
|
342
473
|
|
|
343
474
|
---
|
|
344
475
|
|
|
476
|
+
<a id="v1.2.13"></a>
|
|
345
477
|
## [1.2.13] - 2026-01-27
|
|
346
478
|
|
|
347
479
|
### Added
|
|
@@ -358,6 +490,7 @@ if (result.success) {
|
|
|
358
490
|
|
|
359
491
|
---
|
|
360
492
|
|
|
493
|
+
<a id="v1.2.12"></a>
|
|
361
494
|
## [1.2.12] - 2026-01-26
|
|
362
495
|
|
|
363
496
|
### Added
|
|
@@ -376,6 +509,7 @@ if (result.success) {
|
|
|
376
509
|
|
|
377
510
|
---
|
|
378
511
|
|
|
512
|
+
<a id="v1.2.11"></a>
|
|
379
513
|
## [1.2.11] - 2026-01-21
|
|
380
514
|
|
|
381
515
|
### Fixed
|
|
@@ -384,6 +518,7 @@ if (result.success) {
|
|
|
384
518
|
|
|
385
519
|
---
|
|
386
520
|
|
|
521
|
+
<a id="v1.0.3"></a>
|
|
387
522
|
## [1.0.3] - 2025-10-04
|
|
388
523
|
|
|
389
524
|
Early tagged releases (`v1.0.0` … `v1.0.3`) from the initial NestJS-oriented AVES SDK work. Detailed commit notes for those tags are limited in the current branch history.
|
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# AVES SDK
|
|
2
2
|
|
|
3
|
-
Type-safe TypeScript SDK for the AVES XML REST API. Handles XML parsing,
|
|
3
|
+
Type-safe TypeScript SDK for the AVES XML REST API. Handles XML parsing, **Effect Schema** validation, camelCase ↔ PascalCase / `@` attrs, and `@effect/platform` HTTP. Public domain methods return `Result` (they do not throw). Effect apps can also `yield*` domain Tags via Layers / `makeAvesRuntime`.
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
@@ -14,61 +14,102 @@ pnpm add aves-sdk
|
|
|
14
14
|
bun add aves-sdk
|
|
15
15
|
```
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
`aves-sdk` depends on `effect` and `@effect/platform`.
|
|
18
|
+
|
|
19
|
+
## Quick start (Promise facade)
|
|
18
20
|
|
|
19
21
|
```typescript
|
|
20
|
-
import { AvesClient } from
|
|
22
|
+
import { AvesClient, isAvesError, type Result } from "aves-sdk";
|
|
21
23
|
|
|
22
24
|
const client = new AvesClient({
|
|
23
|
-
baseURL:
|
|
24
|
-
hostID:
|
|
25
|
-
xtoken:
|
|
26
|
-
languageCode:
|
|
25
|
+
baseURL: "https://api.example.com",
|
|
26
|
+
hostID: "000000", // 6 digits
|
|
27
|
+
xtoken: "TOKEN",
|
|
28
|
+
languageCode: "02", // optional: 01=Italian, 02=English
|
|
27
29
|
timeoutMs: 30_000, // optional
|
|
28
30
|
});
|
|
29
31
|
|
|
30
|
-
const result = await client.master.search({
|
|
31
|
-
searchType:
|
|
32
|
-
recordCode:
|
|
32
|
+
const result: Result<unknown> = await client.master.search({
|
|
33
|
+
searchType: "CODE",
|
|
34
|
+
recordCode: "508558",
|
|
33
35
|
});
|
|
34
36
|
|
|
35
37
|
if (result.success) {
|
|
36
38
|
const [record] = result.data;
|
|
37
39
|
console.log(record?.recordCode);
|
|
38
|
-
} else {
|
|
40
|
+
} else if (isAvesError(result.error)) {
|
|
39
41
|
console.error(result.error.kind, result.error.message, result.error.code);
|
|
40
42
|
}
|
|
41
43
|
```
|
|
42
44
|
|
|
45
|
+
`createAvesClient(options, deps?)` returns the same Promise API as a plain object.
|
|
46
|
+
|
|
47
|
+
## Quick start (Effect)
|
|
48
|
+
|
|
49
|
+
```typescript
|
|
50
|
+
import { Effect } from "effect";
|
|
51
|
+
import { AvesMaster, makeAvesRuntime } from "aves-sdk";
|
|
52
|
+
|
|
53
|
+
const runtime = makeAvesRuntime({
|
|
54
|
+
baseURL: "https://api.example.com",
|
|
55
|
+
hostID: "000000",
|
|
56
|
+
xtoken: "TOKEN",
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
const records = await runtime.runPromise(
|
|
60
|
+
Effect.gen(function* () {
|
|
61
|
+
const master = yield* AvesMaster;
|
|
62
|
+
return yield* master.search({
|
|
63
|
+
searchType: "CODE",
|
|
64
|
+
recordCode: "508558",
|
|
65
|
+
});
|
|
66
|
+
}).pipe(
|
|
67
|
+
Effect.catchTag("AvesApiError", (e) =>
|
|
68
|
+
Effect.succeed({ failed: true as const, code: e.code }),
|
|
69
|
+
),
|
|
70
|
+
),
|
|
71
|
+
);
|
|
72
|
+
|
|
73
|
+
await runtime.dispose();
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Also: `Effect.provide(avesClientLayer(options, deps))` or `AvesClientLive(options)` for the full stack including `AvesConfig` / `AvesHttp`.
|
|
77
|
+
|
|
43
78
|
## Client shape
|
|
44
79
|
|
|
45
|
-
`AvesClient`
|
|
80
|
+
`AvesClient` / `createAvesClient` expose **Promise** domain namespaces only (`master`, `booking`, `packages`). There is no `client.transport` on the Promise facade — use `AvesTransport` with Layers for Effect programs.
|
|
46
81
|
|
|
47
82
|
```typescript
|
|
48
83
|
await client.booking.create(params);
|
|
84
|
+
await client.booking.exportData(params);
|
|
49
85
|
await client.packages.search(params);
|
|
50
|
-
await client.master.search({ searchType:
|
|
86
|
+
await client.master.search({ searchType: "CODE", recordCode: "508558" });
|
|
51
87
|
```
|
|
52
88
|
|
|
53
89
|
Migration from 1.x: insert the appropriate domain namespace (for example,
|
|
54
|
-
`client.search` → `client.master.search`). See the [2.0.0 migration notes](
|
|
90
|
+
`client.search` → `client.master.search`). See the [2.0.0 migration notes](https://github.com/simoneguglielmi/aves-sdk/blob/main/CHANGELOG.md#v2.0.0).
|
|
55
91
|
|
|
56
92
|
Migration from 2.x: `master.search` success is a flat array — see the
|
|
57
|
-
[3.0.0 migration notes](
|
|
93
|
+
[3.0.0 migration notes](https://github.com/simoneguglielmi/aves-sdk/blob/main/CHANGELOG.md#v3.0.0).
|
|
58
94
|
|
|
59
95
|
Migration from 3.x: domain method names were shortened — see the
|
|
60
|
-
[4.0.0 migration notes](
|
|
96
|
+
[4.0.0 migration notes](https://github.com/simoneguglielmi/aves-sdk/blob/main/CHANGELOG.md#v4.0.0).
|
|
97
|
+
|
|
98
|
+
Migration from 4.x: Effect Schema + platform HTTP + tagged errors — see the
|
|
99
|
+
[5.0.0 migration notes](https://github.com/simoneguglielmi/aves-sdk/blob/main/CHANGELOG.md#v5.0.0).
|
|
61
100
|
|
|
62
101
|
| Namespace | Methods |
|
|
63
102
|
| --------- | ------- |
|
|
64
103
|
| `master` | `search`, `upsert` |
|
|
65
|
-
| `booking` | `create`, `updateServices`, `updateHeader`, `cancel`, `setStatus`, `setServiceStatus`, `addPayments`, `search` |
|
|
104
|
+
| `booking` | `create`, `updateServices`, `updateHeader`, `cancel`, `setStatus`, `setServiceStatus`, `addPayments`, `search`, `exportData` |
|
|
66
105
|
| `packages` | `search`, `searchServices`, `get`, `commit` |
|
|
67
106
|
|
|
68
107
|
### Constructor
|
|
69
108
|
|
|
70
109
|
```typescript
|
|
71
110
|
new AvesClient(options: AvesClientOptions, deps?: AvesClientDeps)
|
|
111
|
+
// or
|
|
112
|
+
createAvesClient(options, deps?)
|
|
72
113
|
```
|
|
73
114
|
|
|
74
115
|
| Option | Description |
|
|
@@ -79,28 +120,36 @@ new AvesClient(options: AvesClientOptions, deps?: AvesClientDeps)
|
|
|
79
120
|
| `languageCode` | Optional 2-digit language code |
|
|
80
121
|
| `timeoutMs` | Optional request timeout (default 30000) |
|
|
81
122
|
|
|
82
|
-
Optional DI (tests / custom
|
|
123
|
+
Optional DI (tests / custom HTTP):
|
|
83
124
|
|
|
84
125
|
```typescript
|
|
85
|
-
import {
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
126
|
+
import { HttpClient, HttpClientResponse } from "@effect/platform";
|
|
127
|
+
import { Effect } from "effect";
|
|
128
|
+
import { AvesClient } from "aves-sdk";
|
|
129
|
+
|
|
130
|
+
const httpClient = HttpClient.make((request, url) =>
|
|
131
|
+
Effect.succeed(
|
|
132
|
+
HttpClientResponse.fromWeb(
|
|
133
|
+
request,
|
|
134
|
+
new Response(xmlBody, { status: 200 }),
|
|
135
|
+
),
|
|
136
|
+
),
|
|
137
|
+
);
|
|
90
138
|
|
|
91
|
-
const transport = new AvesTransport(options);
|
|
92
139
|
new AvesClient(options, {
|
|
93
|
-
|
|
94
|
-
|
|
140
|
+
httpClient,
|
|
141
|
+
// or: http, transport, master, booking, packages service overrides
|
|
95
142
|
});
|
|
96
143
|
```
|
|
97
144
|
|
|
98
145
|
### Result type
|
|
99
146
|
|
|
100
|
-
|
|
147
|
+
Promise domain methods return `Result<T, AvesError>` — they do **not** throw. `Result` is exported from `aves-sdk`.
|
|
101
148
|
|
|
102
149
|
```typescript
|
|
103
|
-
type Result
|
|
150
|
+
import type { Result } from "aves-sdk";
|
|
151
|
+
|
|
152
|
+
type Result<T, E = Error> =
|
|
104
153
|
| { success: true; data: T }
|
|
105
154
|
| { success: false; error: E };
|
|
106
155
|
```
|
|
@@ -108,7 +157,7 @@ type Result<T, E> =
|
|
|
108
157
|
## Simple facade names
|
|
109
158
|
|
|
110
159
|
The facade exposes concise aliases for the AVES payload vocabulary. Inbound
|
|
111
|
-
dual keys are owned by
|
|
160
|
+
dual keys are owned by Effect Schema input schemas (`facadeObject` / `coalesceAliases`)
|
|
112
161
|
and coalesced to AVES camelCase before wire encoding. Outbound success payloads
|
|
113
162
|
keep AVES names and add concise compatibility aliases. XML shapes are unchanged.
|
|
114
163
|
|
|
@@ -410,6 +459,7 @@ if (result.success) {
|
|
|
410
459
|
| `setServiceStatus` | Nullify a single service line |
|
|
411
460
|
| `addPayments` | Register payments |
|
|
412
461
|
| `search` | Search practices (`FILE_CODE`, `PAX_NAME`, `PACKAGE_CODE`, `OTHER`) |
|
|
462
|
+
| `exportData` | Read practices back whole, **incl. registered payments and amounts** |
|
|
413
463
|
|
|
414
464
|
### Create
|
|
415
465
|
|
|
@@ -543,6 +593,54 @@ await client.booking.search({
|
|
|
543
593
|
});
|
|
544
594
|
```
|
|
545
595
|
|
|
596
|
+
### Read a practice back (`exportData`)
|
|
597
|
+
|
|
598
|
+
`search` returns the header and booked services. `exportData` is the only AVES
|
|
599
|
+
operation that also returns **registered payments**, per-line amounts and file
|
|
600
|
+
totals — use it to reconcile what was written with `addPayments` / `create`.
|
|
601
|
+
|
|
602
|
+
Every field is an optional filter. With none set AVES exports everything the
|
|
603
|
+
credentials can reach, so pass `limitRange` for anything broader than one
|
|
604
|
+
`bookingFileCode` (`skip` ≥ 0, `take` ≤ 1000 — enforced before sending).
|
|
605
|
+
|
|
606
|
+
```typescript
|
|
607
|
+
const result = await client.booking.exportData({
|
|
608
|
+
bookingFileCode: '14/036654',
|
|
609
|
+
// or filter a window:
|
|
610
|
+
// lastModificationDate: { minDate: '2026-08-01', maxDate: '2026-08-07' },
|
|
611
|
+
// statusLists: ['CONFIRMED'],
|
|
612
|
+
// limitRange: { skip: 0, take: 500 },
|
|
613
|
+
});
|
|
614
|
+
|
|
615
|
+
if (result.success) {
|
|
616
|
+
const file = result.data.bookingFileList?.[0];
|
|
617
|
+
|
|
618
|
+
for (const payment of file?.paymentList ?? []) {
|
|
619
|
+
console.log(payment.paymentDate, payment.amount, payment.paymentType);
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
for (const service of file?.bookedServices ?? []) {
|
|
623
|
+
console.log(service.serviceCode, service.amountsDetail?.costWithTax);
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
console.log(file?.bookedFileAmounts?.customerDueAmount);
|
|
627
|
+
|
|
628
|
+
// Lookup tables the exported codes resolve against.
|
|
629
|
+
// `territoriality` (IN_UE | OUT_UE | MIXED_UE) drives the VAT regime.
|
|
630
|
+
console.log(result.data.extraInfo?.nationList);
|
|
631
|
+
console.log(result.data.extraInfo?.vatList);
|
|
632
|
+
}
|
|
633
|
+
```
|
|
634
|
+
|
|
635
|
+
`extraInfo.masterDataSet` rows are validated as full master records — the same
|
|
636
|
+
shape `client.master.search` returns. Read responses accept `RecordType:
|
|
637
|
+
'NOT_SET'` via `RecordTypeWire`; the request-side `RecordType` stays strict.
|
|
638
|
+
|
|
639
|
+
Every picklist the spec closes is validated, so an undocumented value fails the
|
|
640
|
+
whole response rather than reaching your code. Two fields are deliberately
|
|
641
|
+
plain strings because AVES documents no values for them: `regimeType` (no list
|
|
642
|
+
given) and `customerPayAt` (absent from the response table entirely).
|
|
643
|
+
|
|
546
644
|
---
|
|
547
645
|
|
|
548
646
|
## Package / Program catalog
|
|
@@ -597,20 +695,29 @@ if (detail.success) console.log(detail.data.pCode, detail.data.serviceList?.[0])
|
|
|
597
695
|
|
|
598
696
|
## Errors
|
|
599
697
|
|
|
698
|
+
`AvesError` is a tagged union: `AvesValidationError` | `AvesApiError` | `AvesUnknownError`.
|
|
699
|
+
Each has `_tag` (for `Effect.catchTag`) and Promise-friendly `kind` (`validation` | `api` | `unknown`).
|
|
700
|
+
|
|
600
701
|
```typescript
|
|
601
|
-
import { AvesClient,
|
|
702
|
+
import { AvesClient, AvesApiError, isAvesError } from "aves-sdk";
|
|
602
703
|
|
|
603
704
|
const result = await client.master.search({
|
|
604
|
-
searchType:
|
|
605
|
-
recordCode:
|
|
705
|
+
searchType: "CODE",
|
|
706
|
+
recordCode: "508558",
|
|
606
707
|
});
|
|
607
708
|
|
|
608
709
|
if (!result.success) {
|
|
609
|
-
|
|
610
|
-
|
|
710
|
+
if (isAvesError(result.error)) {
|
|
711
|
+
console.error(result.error.kind, result.error.message, result.error.code);
|
|
712
|
+
}
|
|
713
|
+
if (result.error instanceof AvesApiError) {
|
|
714
|
+
console.error(result.error._tag, result.error.status);
|
|
715
|
+
}
|
|
611
716
|
}
|
|
612
717
|
```
|
|
613
718
|
|
|
719
|
+
Effect programs recover with `Effect.catchTag("AvesApiError", …)` (also `"AvesValidationError"`, `"AvesUnknownError"`).
|
|
720
|
+
|
|
614
721
|
---
|
|
615
722
|
|
|
616
723
|
## Case transformation & wire shapes
|
|
@@ -626,9 +733,9 @@ You do not handle XML attribute prefixes yourself. Attr vs element is decided by
|
|
|
626
733
|
|
|
627
734
|
One outbound path for all ops:
|
|
628
735
|
|
|
629
|
-
1.
|
|
736
|
+
1. Effect Schema validates camelCase input
|
|
630
737
|
2. `createApiSchema(schema, shape, wrap?)` → `toWireBody` (optional list wrap + `paxAssociated` string[]/empty normalize + `camelToPascalKeys`)
|
|
631
|
-
3. `
|
|
738
|
+
3. Transport `invoke` / `ops.*` adds `RqHeader`, optional `bodyKey` nest, POSTs XML
|
|
632
739
|
|
|
633
740
|
Inbound: `createResponseSchema` / `createFlattenedResponseSchema` / `createListResponseSchema` → camelCase + optional detail spread or typed list RS; `listDetailApiSchema` unwraps wire `*List`/`*Detail` to flat arrays; `coalesceWireAliases` normalizes dialect attrs. Input aliases: `valueFieldSchema`, `coalesceCustomerRecordCode`, `coalesceListHead`. Shared primitives: `LanguageCodeSchema`, `StringishSchema`, `DateRangeSchema`, `StatusOnlyResponseSchema`.
|
|
634
741
|
|
|
@@ -653,18 +760,23 @@ Editing CreateBooking shapes does not affect SearchFile or AvesSearch.
|
|
|
653
760
|
|
|
654
761
|
## Architecture
|
|
655
762
|
|
|
656
|
-
`
|
|
763
|
+
Promise edge: `createAvesClient` / `AvesClient` → `toPromiseFacade` on domain services.
|
|
764
|
+
Effect edge: `makeAvesRuntime` / `avesClientLayer` / `AvesClientLive` → `yield*` Tags.
|
|
657
765
|
|
|
658
766
|
| Module | Role |
|
|
659
767
|
| ------ | ---- |
|
|
660
|
-
| `
|
|
661
|
-
| `
|
|
662
|
-
| `
|
|
663
|
-
| `
|
|
664
|
-
| `client/
|
|
768
|
+
| `src/client.ts` | Promise facade + `makeAvesRuntime` |
|
|
769
|
+
| `src/client/layer.ts` | `avesClientLayer` / `AvesClientLive` composition |
|
|
770
|
+
| `src/client/booking/` | Booking Tag / service / layer |
|
|
771
|
+
| `src/client/master/` | Master-records Tag / service / layer |
|
|
772
|
+
| `src/client/packages/` | Package catalog Tag / service / layer |
|
|
773
|
+
| `src/client/transport/` | `invoke` / `ops` / response reader |
|
|
774
|
+
| `src/client/http/` | XML POST via `@effect/platform` HttpClient |
|
|
775
|
+
| `src/client/config/` | `AvesConfig` |
|
|
776
|
+
| `src/schemas/` | Effect Schema RQ/RS |
|
|
665
777
|
| `src/xml/` | XML root helpers + JSON ↔ XML |
|
|
666
778
|
|
|
667
|
-
Outbound path:
|
|
779
|
+
Outbound path: Schema decode → `createApiSchema` / `toWireBody` → transport → HTTP POST.
|
|
668
780
|
|
|
669
781
|
---
|
|
670
782
|
|
|
@@ -673,24 +785,30 @@ Outbound path: validate → `createApiSchema` / `toWireBody` → `invokeOp` →
|
|
|
673
785
|
Operations are available only through `client.master`, `client.booking`, and
|
|
674
786
|
`client.packages`; flat aliases were removed in 2.0.0. When upgrading from 2.x,
|
|
675
787
|
also update `master.search` consumers for the flat array success payload (3.0.0).
|
|
676
|
-
See the [CHANGELOG migration notes](
|
|
788
|
+
See the [CHANGELOG migration notes](https://github.com/simoneguglielmi/aves-sdk/blob/main/CHANGELOG.md).
|
|
677
789
|
|
|
678
790
|
```typescript
|
|
679
791
|
import type {
|
|
680
792
|
AvesClientOptions,
|
|
681
793
|
AvesClientDeps,
|
|
794
|
+
AvesError,
|
|
682
795
|
AvesSearchRQ,
|
|
683
796
|
BookingFileRQ,
|
|
797
|
+
Result,
|
|
684
798
|
SearchMasterRecord,
|
|
685
|
-
} from
|
|
799
|
+
} from "aves-sdk";
|
|
686
800
|
|
|
687
801
|
import {
|
|
688
802
|
AvesClient,
|
|
803
|
+
createAvesClient,
|
|
804
|
+
makeAvesRuntime,
|
|
805
|
+
AvesMaster,
|
|
806
|
+
AvesBooking,
|
|
807
|
+
AvesPackages,
|
|
689
808
|
AvesTransport,
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
AvesError,
|
|
809
|
+
avesClientLayer,
|
|
810
|
+
isAvesError,
|
|
811
|
+
AvesApiError,
|
|
694
812
|
// object enums
|
|
695
813
|
AvesSearchType,
|
|
696
814
|
BookingFileStatus,
|
|
@@ -699,7 +817,7 @@ import {
|
|
|
699
817
|
PaxQtyCriteria,
|
|
700
818
|
PaymentType,
|
|
701
819
|
SearchMasterType,
|
|
702
|
-
} from
|
|
820
|
+
} from "aves-sdk";
|
|
703
821
|
|
|
704
822
|
PaxQtyCriteria.GREATER_OR_EQUAL
|
|
705
823
|
AvesSearchType.PACKAGE
|
|
@@ -713,7 +831,7 @@ MIT
|
|
|
713
831
|
|
|
714
832
|
## Links
|
|
715
833
|
|
|
716
|
-
- [Changelog](
|
|
834
|
+
- [Changelog](https://github.com/simoneguglielmi/aves-sdk/blob/main/CHANGELOG.md)
|
|
717
835
|
- [GitHub Repository](https://github.com/simoneguglielmi/aves-sdk)
|
|
718
836
|
- [NPM Package](https://npmjs.com/package/aves-sdk)
|
|
719
837
|
- [Issue Tracker](https://github.com/simoneguglielmi/aves-sdk/issues)
|