@voyant-travel/flights 0.131.1 → 0.133.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/dist/index.d.ts CHANGED
@@ -2,6 +2,7 @@ export { type AdapterLogger, CAPABILITY_NOT_SUPPORTED, type FlightAdapterCapabil
2
2
  export * from "./contract/schemas.js";
3
3
  export * from "./contract/types.js";
4
4
  export { createFlightAdminRoutes, createFlightsHonoModule, type FlightOrderPaymentSummary, type FlightPaymentIntegration, type FlightsHonoModuleOptions, type FlightsRouteOptions, } from "./hono.js";
5
+ export { FLIGHTS_ENTITY_MODULE, mergedFlightOffersToCandidates, mergedFlightOfferToCandidate, } from "./orchestration/availability-bridge.js";
5
6
  export { type ConnectionResult, type ConnectionSearchStatus, type FanOutFlightSearchOptions, type FanOutFlightSearchResult, fanOutFlightSearch, type MergedFlightOffer, } from "./orchestration/fan-out.js";
6
7
  export { itineraryFingerprint } from "./orchestration/fingerprint.js";
7
8
  export { buildFlightSummary, createFlightOrderPaymentIntegration, type FlightCardBilling, type FlightOrderPaymentIntegrationDeps, formatDay, type OrderPaymentSessionsLike, parseAmountToCents, synthesizeBilling, } from "./payment-integration.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,KAAK,aAAa,EAClB,wBAAwB,EACxB,KAAK,yBAAyB,EAC9B,KAAK,oBAAoB,EACzB,KAAK,wBAAwB,EAC7B,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,EACvB,KAAK,oBAAoB,EACzB,iCAAiC,EACjC,KAAK,sBAAsB,EAC3B,KAAK,sBAAsB,EAC3B,KAAK,kBAAkB,EACvB,KAAK,mBAAmB,EACxB,KAAK,oBAAoB,EACzB,iBAAiB,GAClB,MAAM,uBAAuB,CAAA;AAC9B,cAAc,uBAAuB,CAAA;AACrC,cAAc,qBAAqB,CAAA;AAGnC,OAAO,EACL,uBAAuB,EACvB,uBAAuB,EACvB,KAAK,yBAAyB,EAC9B,KAAK,wBAAwB,EAC7B,KAAK,wBAAwB,EAC7B,KAAK,mBAAmB,GACzB,MAAM,WAAW,CAAA;AAClB,OAAO,EACL,KAAK,gBAAgB,EACrB,KAAK,sBAAsB,EAC3B,KAAK,yBAAyB,EAC9B,KAAK,wBAAwB,EAC7B,kBAAkB,EAClB,KAAK,iBAAiB,GACvB,MAAM,4BAA4B,CAAA;AAEnC,OAAO,EAAE,oBAAoB,EAAE,MAAM,gCAAgC,CAAA;AAGrE,OAAO,EACL,kBAAkB,EAClB,mCAAmC,EACnC,KAAK,iBAAiB,EACtB,KAAK,iCAAiC,EACtC,SAAS,EACT,KAAK,wBAAwB,EAC7B,kBAAkB,EAClB,iBAAiB,GAClB,MAAM,0BAA0B,CAAA;AAEjC,OAAO,EACL,KAAK,QAAQ,EACb,KAAK,OAAO,EACZ,KAAK,OAAO,EACZ,WAAW,EACX,KAAK,yBAAyB,EAC9B,KAAK,qBAAqB,GAC3B,MAAM,yBAAyB,CAAA;AAChC,OAAO,EACL,oCAAoC,EACpC,KAAK,qCAAqC,EAC1C,iBAAiB,EACjB,iBAAiB,EACjB,iBAAiB,GAClB,MAAM,+BAA+B,CAAA;AACtC,OAAO,EACL,mCAAmC,EACnC,KAAK,2BAA2B,EAChC,KAAK,yBAAyB,GAC/B,MAAM,8BAA8B,CAAA;AAErC,OAAO,EACL,KAAK,+BAA+B,EACpC,wBAAwB,GACzB,MAAM,eAAe,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,KAAK,aAAa,EAClB,wBAAwB,EACxB,KAAK,yBAAyB,EAC9B,KAAK,oBAAoB,EACzB,KAAK,wBAAwB,EAC7B,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,EACvB,KAAK,oBAAoB,EACzB,iCAAiC,EACjC,KAAK,sBAAsB,EAC3B,KAAK,sBAAsB,EAC3B,KAAK,kBAAkB,EACvB,KAAK,mBAAmB,EACxB,KAAK,oBAAoB,EACzB,iBAAiB,GAClB,MAAM,uBAAuB,CAAA;AAC9B,cAAc,uBAAuB,CAAA;AACrC,cAAc,qBAAqB,CAAA;AAGnC,OAAO,EACL,uBAAuB,EACvB,uBAAuB,EACvB,KAAK,yBAAyB,EAC9B,KAAK,wBAAwB,EAC7B,KAAK,wBAAwB,EAC7B,KAAK,mBAAmB,GACzB,MAAM,WAAW,CAAA;AAClB,OAAO,EACL,qBAAqB,EACrB,8BAA8B,EAC9B,4BAA4B,GAC7B,MAAM,wCAAwC,CAAA;AAC/C,OAAO,EACL,KAAK,gBAAgB,EACrB,KAAK,sBAAsB,EAC3B,KAAK,yBAAyB,EAC9B,KAAK,wBAAwB,EAC7B,kBAAkB,EAClB,KAAK,iBAAiB,GACvB,MAAM,4BAA4B,CAAA;AAEnC,OAAO,EAAE,oBAAoB,EAAE,MAAM,gCAAgC,CAAA;AAGrE,OAAO,EACL,kBAAkB,EAClB,mCAAmC,EACnC,KAAK,iBAAiB,EACtB,KAAK,iCAAiC,EACtC,SAAS,EACT,KAAK,wBAAwB,EAC7B,kBAAkB,EAClB,iBAAiB,GAClB,MAAM,0BAA0B,CAAA;AAEjC,OAAO,EACL,KAAK,QAAQ,EACb,KAAK,OAAO,EACZ,KAAK,OAAO,EACZ,WAAW,EACX,KAAK,yBAAyB,EAC9B,KAAK,qBAAqB,GAC3B,MAAM,yBAAyB,CAAA;AAChC,OAAO,EACL,oCAAoC,EACpC,KAAK,qCAAqC,EAC1C,iBAAiB,EACjB,iBAAiB,EACjB,iBAAiB,GAClB,MAAM,+BAA+B,CAAA;AACtC,OAAO,EACL,mCAAmC,EACnC,KAAK,2BAA2B,EAChC,KAAK,yBAAyB,GAC/B,MAAM,8BAA8B,CAAA;AAErC,OAAO,EACL,KAAK,+BAA+B,EACpC,wBAAwB,GACzB,MAAM,eAAe,CAAA"}
package/dist/index.js CHANGED
@@ -6,6 +6,7 @@ export * from "./contract/types.js";
6
6
  // Flight admin HTTP routes (module-owned; the deployment supplies connector +
7
7
  // payment options).
8
8
  export { createFlightAdminRoutes, createFlightsHonoModule, } from "./hono.js";
9
+ export { FLIGHTS_ENTITY_MODULE, mergedFlightOffersToCandidates, mergedFlightOfferToCandidate, } from "./orchestration/availability-bridge.js";
9
10
  export { fanOutFlightSearch, } from "./orchestration/fan-out.js";
10
11
  // Orchestration — fingerprinting + multi-connection fan-out.
11
12
  export { itineraryFingerprint } from "./orchestration/fingerprint.js";
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Flights → AvailabilityCandidate bridge.
3
+ *
4
+ * Maps the flights-native `MergedFlightOffer` (produced by `fanOutFlightSearch`)
5
+ * onto the vertical-agnostic `AvailabilityCandidate` the dynamic-packaging
6
+ * composer ranks. This is a mapping, NOT proof that flights already satisfy the
7
+ * generic source-adapter contract — flights keep their own connector contract
8
+ * and fan-out; this only normalizes the result shape.
9
+ *
10
+ * See `docs/architecture/dynamic-packaging-rfc.md` §2 (Gap 1) and §4.
11
+ */
12
+ import type { AvailabilityCandidate } from "@voyant-travel/catalog-contracts";
13
+ import type { MergedFlightOffer } from "./fan-out.js";
14
+ /** Vertical key flights candidates carry. */
15
+ export declare const FLIGHTS_ENTITY_MODULE: "flights";
16
+ /**
17
+ * Convert one merged flight offer into a normalized availability candidate.
18
+ *
19
+ * The candidate's `selection` carries what the flights booking path needs to
20
+ * re-resolve and price the exact offer at reserve time (offer id + source +
21
+ * the connections that returned it). The per-search `offerId` is not
22
+ * replay-safe, so callers re-price before booking — same rule as the generic
23
+ * `AvailabilityCandidate.candidateRef`.
24
+ */
25
+ export declare function mergedFlightOfferToCandidate(merged: MergedFlightOffer): AvailabilityCandidate;
26
+ /** Convenience: map a whole fan-out result set to candidates, preserving rank. */
27
+ export declare function mergedFlightOffersToCandidates(merged: ReadonlyArray<MergedFlightOffer>): AvailabilityCandidate[];
28
+ //# sourceMappingURL=availability-bridge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"availability-bridge.d.ts","sourceRoot":"","sources":["../../src/orchestration/availability-bridge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,kCAAkC,CAAA;AAC7E,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAA;AAErD,6CAA6C;AAC7C,eAAO,MAAM,qBAAqB,EAAG,SAAkB,CAAA;AAEvD;;;;;;;;GAQG;AACH,wBAAgB,4BAA4B,CAAC,MAAM,EAAE,iBAAiB,GAAG,qBAAqB,CAoB7F;AAED,kFAAkF;AAClF,wBAAgB,8BAA8B,CAC5C,MAAM,EAAE,aAAa,CAAC,iBAAiB,CAAC,GACvC,qBAAqB,EAAE,CAEzB"}
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Flights → AvailabilityCandidate bridge.
3
+ *
4
+ * Maps the flights-native `MergedFlightOffer` (produced by `fanOutFlightSearch`)
5
+ * onto the vertical-agnostic `AvailabilityCandidate` the dynamic-packaging
6
+ * composer ranks. This is a mapping, NOT proof that flights already satisfy the
7
+ * generic source-adapter contract — flights keep their own connector contract
8
+ * and fan-out; this only normalizes the result shape.
9
+ *
10
+ * See `docs/architecture/dynamic-packaging-rfc.md` §2 (Gap 1) and §4.
11
+ */
12
+ /** Vertical key flights candidates carry. */
13
+ export const FLIGHTS_ENTITY_MODULE = "flights";
14
+ /**
15
+ * Convert one merged flight offer into a normalized availability candidate.
16
+ *
17
+ * The candidate's `selection` carries what the flights booking path needs to
18
+ * re-resolve and price the exact offer at reserve time (offer id + source +
19
+ * the connections that returned it). The per-search `offerId` is not
20
+ * replay-safe, so callers re-price before booking — same rule as the generic
21
+ * `AvailabilityCandidate.candidateRef`.
22
+ */
23
+ export function mergedFlightOfferToCandidate(merged) {
24
+ const offer = merged.cheapest;
25
+ return {
26
+ candidateRef: merged.itineraryFingerprint,
27
+ entity_module: FLIGHTS_ENTITY_MODULE,
28
+ entity_id: offer.offerId,
29
+ selection: {
30
+ offerId: offer.offerId,
31
+ source: offer.source,
32
+ itineraryFingerprint: merged.itineraryFingerprint,
33
+ sourceConnectionIds: merged.sourceConnectionIds,
34
+ },
35
+ price: { amount: offer.totalPrice.amount, currency: offer.totalPrice.currency },
36
+ expiresAt: offer.expiresAt ? new Date(offer.expiresAt) : undefined,
37
+ providerData: {
38
+ sourceConnectionIds: merged.sourceConnectionIds,
39
+ alternateCount: merged.alternates.length,
40
+ ...offer.providerData,
41
+ },
42
+ };
43
+ }
44
+ /** Convenience: map a whole fan-out result set to candidates, preserving rank. */
45
+ export function mergedFlightOffersToCandidates(merged) {
46
+ return merged.map(mergedFlightOfferToCandidate);
47
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=availability-bridge.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"availability-bridge.test.d.ts","sourceRoot":"","sources":["../../src/orchestration/availability-bridge.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,53 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { FLIGHTS_ENTITY_MODULE, mergedFlightOffersToCandidates, mergedFlightOfferToCandidate, } from "./availability-bridge.js";
3
+ function offer(overrides = {}) {
4
+ return {
5
+ offerId: overrides.offerId ?? "ofr_1",
6
+ source: overrides.source ?? "conn_amadeus",
7
+ itineraries: [],
8
+ fareBreakdowns: [],
9
+ totalPrice: overrides.totalPrice ?? { amount: "600", currency: "USD" },
10
+ ...overrides,
11
+ };
12
+ }
13
+ function merged(overrides = {}) {
14
+ return {
15
+ itineraryFingerprint: overrides.itineraryFingerprint ?? "fp_lhr_jfk",
16
+ cheapest: overrides.cheapest ?? offer(),
17
+ alternates: overrides.alternates ?? [],
18
+ sourceConnectionIds: overrides.sourceConnectionIds ?? ["conn_amadeus"],
19
+ };
20
+ }
21
+ describe("mergedFlightOfferToCandidate", () => {
22
+ it("maps a merged offer onto a normalized candidate", () => {
23
+ const candidate = mergedFlightOfferToCandidate(merged({
24
+ cheapest: offer({
25
+ offerId: "ofr_99",
26
+ expiresAt: "2026-10-15T10:00:00Z",
27
+ providerData: { fareKey: "abc" },
28
+ }),
29
+ alternates: [offer({ offerId: "ofr_alt" })],
30
+ sourceConnectionIds: ["conn_amadeus", "conn_sabre"],
31
+ }));
32
+ expect(candidate.entity_module).toBe(FLIGHTS_ENTITY_MODULE);
33
+ expect(candidate.entity_id).toBe("ofr_99");
34
+ expect(candidate.candidateRef).toBe("fp_lhr_jfk");
35
+ expect(candidate.price).toEqual({ amount: "600", currency: "USD" });
36
+ expect(candidate.selection).toMatchObject({
37
+ offerId: "ofr_99",
38
+ sourceConnectionIds: ["conn_amadeus", "conn_sabre"],
39
+ });
40
+ expect(candidate.expiresAt).toEqual(new Date("2026-10-15T10:00:00Z"));
41
+ expect(candidate.providerData).toMatchObject({ fareKey: "abc", alternateCount: 1 });
42
+ });
43
+ it("leaves expiresAt undefined when the offer has none", () => {
44
+ expect(mergedFlightOfferToCandidate(merged()).expiresAt).toBeUndefined();
45
+ });
46
+ it("maps a list preserving rank order", () => {
47
+ const candidates = mergedFlightOffersToCandidates([
48
+ merged({ itineraryFingerprint: "fp_a", cheapest: offer({ offerId: "a" }) }),
49
+ merged({ itineraryFingerprint: "fp_b", cheapest: offer({ offerId: "b" }) }),
50
+ ]);
51
+ expect(candidates.map((c) => c.entity_id)).toEqual(["a", "b"]);
52
+ });
53
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@voyant-travel/flights",
3
- "version": "0.131.1",
3
+ "version": "0.133.0",
4
4
  "license": "Apache-2.0",
5
5
  "type": "module",
6
6
  "exports": {
@@ -83,10 +83,11 @@
83
83
  "drizzle-orm": "^0.45.2",
84
84
  "hono": "^4.12.10",
85
85
  "zod": "^4.3.6",
86
- "@voyant-travel/db": "^0.108.5",
87
- "@voyant-travel/catalog": "^0.129.1",
88
- "@voyant-travel/flights-contracts": "^0.104.4",
89
- "@voyant-travel/hono": "^0.113.0"
86
+ "@voyant-travel/db": "^0.109.0",
87
+ "@voyant-travel/catalog": "^0.131.0",
88
+ "@voyant-travel/catalog-contracts": "^0.108.0",
89
+ "@voyant-travel/flights-contracts": "^0.104.5",
90
+ "@voyant-travel/hono": "^0.114.0"
90
91
  },
91
92
  "devDependencies": {
92
93
  "drizzle-kit": "^0.31.10",