@voyantjs/hospitality 0.32.3 → 0.34.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.
@@ -1 +1 @@
1
- {"version":3,"file":"catalog-policy.d.ts","sourceRoot":"","sources":["../src/catalog-policy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAAqB,KAAK,gBAAgB,EAAE,MAAM,4BAA4B,CAAA;AAErF,QAAA,MAAM,wBAAwB,EAAE,gBAAgB,EAwY/C,CAAA;AAED,eAAO,MAAM,wBAAwB,2CAA8C,CAAA;AAEnF,OAAO,EAAE,wBAAwB,EAAE,CAAA"}
1
+ {"version":3,"file":"catalog-policy.d.ts","sourceRoot":"","sources":["../src/catalog-policy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAAqB,KAAK,gBAAgB,EAAE,MAAM,4BAA4B,CAAA;AAErF,QAAA,MAAM,wBAAwB,EAAE,gBAAgB,EAsZ/C,CAAA;AAED,eAAO,MAAM,wBAAwB,2CAA8C,CAAA;AAEnF,OAAO,EAAE,wBAAwB,EAAE,CAAA"}
@@ -191,6 +191,20 @@ const HOSPITALITY_FIELD_POLICY = [
191
191
  overrideFriction: "confirm",
192
192
  sourceFreshness: "sync",
193
193
  },
194
+ {
195
+ path: "thumbnailUrl",
196
+ class: "merchandisable",
197
+ merge: "source-only",
198
+ drift: "low",
199
+ reindex: "entry",
200
+ snapshot: "on-book",
201
+ query: "indexed-column",
202
+ localized: false,
203
+ visibility: ["staff", "customer", "partner"],
204
+ editRole: "none",
205
+ overrideFriction: "none",
206
+ sourceFreshness: "sync",
207
+ },
194
208
  // ── Structural / facet-affecting ───────────────────────────────────────
195
209
  {
196
210
  path: "inventoryMode",
@@ -931,9 +931,9 @@ export declare const hospitalityAccommodationRoutes: import("hono/hono-base").Ho
931
931
  active: boolean;
932
932
  sortOrder: number;
933
933
  ratePlanId: string;
934
+ roomTypeId: string;
934
935
  productId: string | null;
935
936
  optionId: string | null;
936
- roomTypeId: string;
937
937
  unitId: string | null;
938
938
  } | null;
939
939
  };
@@ -1230,8 +1230,8 @@ export declare const hospitalityOperationsRoutes: import("hono/hono-base").HonoB
1230
1230
  } | null;
1231
1231
  notes: string | null;
1232
1232
  ratePlanId: string;
1233
- bookingItemId: string;
1234
1233
  roomTypeId: string;
1234
+ bookingItemId: string;
1235
1235
  mealPlanId: string | null;
1236
1236
  roomUnitId: string | null;
1237
1237
  checkInDate: string;
@@ -252,8 +252,8 @@ export declare const hospitalityStayRoutes: import("hono/hono-base").HonoBase<En
252
252
  } | null;
253
253
  notes: string | null;
254
254
  ratePlanId: string;
255
- bookingItemId: string;
256
255
  roomTypeId: string;
256
+ bookingItemId: string;
257
257
  mealPlanId: string | null;
258
258
  roomUnitId: string | null;
259
259
  checkInDate: string;
package/dist/routes.d.ts CHANGED
@@ -931,9 +931,9 @@ export declare const hospitalityRoutes: import("hono/hono-base").HonoBase<Env, i
931
931
  active: boolean;
932
932
  sortOrder: number;
933
933
  ratePlanId: string;
934
+ roomTypeId: string;
934
935
  productId: string | null;
935
936
  optionId: string | null;
936
- roomTypeId: string;
937
937
  unitId: string | null;
938
938
  } | null;
939
939
  };
@@ -2431,8 +2431,8 @@ export declare const hospitalityRoutes: import("hono/hono-base").HonoBase<Env, i
2431
2431
  } | null;
2432
2432
  notes: string | null;
2433
2433
  ratePlanId: string;
2434
- bookingItemId: string;
2435
2434
  roomTypeId: string;
2435
+ bookingItemId: string;
2436
2436
  mealPlanId: string | null;
2437
2437
  roomUnitId: string | null;
2438
2438
  checkInDate: string;
@@ -1 +1 @@
1
- {"version":3,"file":"service-catalog-plane.d.ts","sourceRoot":"","sources":["../src/service-catalog-plane.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAGL,KAAK,oBAAoB,EAEzB,KAAK,eAAe,EACpB,KAAK,eAAe,EAEpB,KAAK,eAAe,EACpB,KAAK,YAAY,EACjB,KAAK,YAAY,EACjB,KAAK,UAAU,EACf,KAAK,YAAY,EACjB,KAAK,aAAa,EAEnB,MAAM,mBAAmB,CAAA;AAC1B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAIhD,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAA;AAUjD;;;;GAIG;AACH,wBAAgB,uBAAuB,CACrC,GAAG,EAAE,OAAO,SAAS,CAAC,YAAY,EAClC,OAAO,EAAE;IAAE,gBAAgB,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,GAC7E,WAAW,CAAC,MAAM,EAAE,OAAO,CAAC,CA2C9B;AAED,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,OAAO,SAAS,CAAC,YAAY,EACnC,OAAO,EAAE;IAAE,gBAAgB,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,GAC7E,UAAU,CAMZ;AAED,MAAM,WAAW,sBAAsB;IACrC,gBAAgB,EAAE,MAAM,CAAA;IACxB,KAAK,EAAE,aAAa,CAAA;IACpB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,wBAAsB,uBAAuB,CAC3C,EAAE,EAAE,YAAY,EAChB,EAAE,EAAE,MAAM,EACV,OAAO,EAAE,sBAAsB,GAC9B,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAkB9B;AAED,wBAAsB,qBAAqB,CACzC,EAAE,EAAE,YAAY,EAChB,IAAI,EAAE,aAAa,CAAC,OAAO,SAAS,CAAC,YAAY,CAAC,EAClD,OAAO,EAAE,sBAAsB,GAC9B,OAAO,CAAC,YAAY,EAAE,CAAC,CAoBzB;AAED;;;GAGG;AACH,wBAAsB,0BAA0B,CAC9C,EAAE,EAAE,YAAY,EAChB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,sBAAsB,GAAG;IAAE,YAAY,CAAC,EAAE,YAAY,CAAA;CAAE,GAChE,OAAO,CAAC,IAAI,CAAC,oBAAoB,EAAE,WAAW,CAAC,GAAG,IAAI,CAAC,CAUzD;AAMD,wBAAgB,6BAA6B,CAAC,OAAO,EAAE;IACrD,gBAAgB,EAAE,MAAM,CAAA;IACxB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,GAAG,eAAe,CAAC,OAAO,SAAS,CAAC,YAAY,CAAC,CAajD;AAED,wBAAgB,6BAA6B,CAC3C,EAAE,EAAE,YAAY,EAChB,OAAO,EAAE;IAAE,gBAAgB,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,GAC7E,eAAe,CAQjB;AAED,YAAY,EACV,oBAAoB,EACpB,eAAe,EACf,eAAe,EACf,eAAe,EACf,YAAY,EACZ,YAAY,EACZ,UAAU,EACV,YAAY,EACZ,aAAa,GACd,CAAA"}
1
+ {"version":3,"file":"service-catalog-plane.d.ts","sourceRoot":"","sources":["../src/service-catalog-plane.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAGL,KAAK,oBAAoB,EAEzB,KAAK,eAAe,EACpB,KAAK,eAAe,EAEpB,KAAK,eAAe,EACpB,KAAK,YAAY,EACjB,KAAK,YAAY,EACjB,KAAK,UAAU,EACf,KAAK,YAAY,EACjB,KAAK,aAAa,EAEnB,MAAM,mBAAmB,CAAA;AAC1B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAIhD,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAA;AAcjD;;;;GAIG;AACH,wBAAgB,uBAAuB,CACrC,GAAG,EAAE,OAAO,SAAS,CAAC,YAAY,EAClC,OAAO,EAAE;IAAE,gBAAgB,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,GAC7E,WAAW,CAAC,MAAM,EAAE,OAAO,CAAC,CA4C9B;AAED,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,OAAO,SAAS,CAAC,YAAY,EACnC,OAAO,EAAE;IAAE,gBAAgB,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,GAC7E,UAAU,CAMZ;AAED,MAAM,WAAW,sBAAsB;IACrC,gBAAgB,EAAE,MAAM,CAAA;IACxB,KAAK,EAAE,aAAa,CAAA;IACpB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,wBAAsB,uBAAuB,CAC3C,EAAE,EAAE,YAAY,EAChB,EAAE,EAAE,MAAM,EACV,OAAO,EAAE,sBAAsB,GAC9B,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAkB9B;AAED,wBAAsB,qBAAqB,CACzC,EAAE,EAAE,YAAY,EAChB,IAAI,EAAE,aAAa,CAAC,OAAO,SAAS,CAAC,YAAY,CAAC,EAClD,OAAO,EAAE,sBAAsB,GAC9B,OAAO,CAAC,YAAY,EAAE,CAAC,CAoBzB;AAED;;;GAGG;AACH,wBAAsB,0BAA0B,CAC9C,EAAE,EAAE,YAAY,EAChB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,sBAAsB,GAAG;IAAE,YAAY,CAAC,EAAE,YAAY,CAAA;CAAE,GAChE,OAAO,CAAC,IAAI,CAAC,oBAAoB,EAAE,WAAW,CAAC,GAAG,IAAI,CAAC,CAUzD;AAMD,wBAAgB,6BAA6B,CAAC,OAAO,EAAE;IACrD,gBAAgB,EAAE,MAAM,CAAA;IACxB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,GAAG,eAAe,CAAC,OAAO,SAAS,CAAC,YAAY,CAAC,CAajD;AAED,wBAAgB,6BAA6B,CAC3C,EAAE,EAAE,YAAY,EAChB,OAAO,EAAE;IAAE,gBAAgB,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,GAC7E,eAAe,CAmBjB;AA0ED,YAAY,EACV,oBAAoB,EACpB,eAAe,EACf,eAAe,EACf,eAAe,EACf,YAAY,EACZ,YAAY,EACZ,UAAU,EACV,YAAY,EACZ,aAAa,GACd,CAAA"}
@@ -10,9 +10,10 @@
10
10
  * See `docs/architecture/catalog-architecture.md` §9.1.
11
11
  */
12
12
  import { buildIndexerDocument, buildSnapshotInputFromView, createFieldPolicyRegistry, resolveEntityView, } from "@voyantjs/catalog";
13
- import { eq } from "drizzle-orm";
13
+ import { and, eq } from "drizzle-orm";
14
14
  import { hospitalityCatalogPolicy } from "./catalog-policy.js";
15
15
  import { roomTypes } from "./schema-inventory.js";
16
+ import { HOSPITALITY_CONTENT_MARKET_ANY, hospitalitySourcedContentTable, } from "./schema-sourced-content.js";
16
17
  let _registry;
17
18
  function getHospitalityRegistry() {
18
19
  if (!_registry) {
@@ -43,6 +44,7 @@ export function roomTypeRowToProjection(row, context) {
43
44
  ["name", row.name],
44
45
  ["description", row.description],
45
46
  ["accessibilityNotes", row.accessibilityNotes],
47
+ ["thumbnailUrl", pickThumbnailUrl(row.metadata)],
46
48
  // Structural / facets
47
49
  ["inventoryMode", row.inventoryMode],
48
50
  ["roomClass", row.roomClass],
@@ -130,12 +132,72 @@ export function createRoomTypeDocumentEmitter(context) {
130
132
  };
131
133
  }
132
134
  export function createRoomTypeDocumentBuilder(db, context) {
133
- const emitter = createRoomTypeDocumentEmitter(context);
135
+ const registry = getHospitalityRegistry();
134
136
  return async (entityId, slice) => {
135
137
  const rows = await db.select().from(roomTypes).where(eq(roomTypes.id, entityId)).limit(1);
136
138
  const row = rows[0];
137
139
  if (!row)
138
140
  return null;
139
- return emitter.emit(row, slice);
141
+ const projection = new Map(roomTypeRowToProjection(row, {
142
+ sellerOperatorId: context.sellerOperatorId,
143
+ sourceKind: context.sourceKind,
144
+ sourceRef: context.sourceRef,
145
+ }));
146
+ const sourcedThumbnailUrl = await fetchSourcedContentThumbnailUrl(db, entityId, slice);
147
+ if (sourcedThumbnailUrl) {
148
+ projection.set("thumbnailUrl", sourcedThumbnailUrl);
149
+ }
150
+ return buildIndexerDocument(registry, projection, slice, entityId);
140
151
  };
141
152
  }
153
+ async function fetchSourcedContentThumbnailUrl(db, entityId, slice) {
154
+ const rows = await db
155
+ .select({
156
+ market: hospitalitySourcedContentTable.market,
157
+ payload: hospitalitySourcedContentTable.payload,
158
+ })
159
+ .from(hospitalitySourcedContentTable)
160
+ .where(and(eq(hospitalitySourcedContentTable.entity_id, entityId), eq(hospitalitySourcedContentTable.locale, slice.locale)));
161
+ const row = rows.find((candidate) => candidate.market === slice.market) ??
162
+ rows.find((candidate) => candidate.market === HOSPITALITY_CONTENT_MARKET_ANY) ??
163
+ rows[0];
164
+ return pickThumbnailUrl(row?.payload);
165
+ }
166
+ function pickThumbnailUrl(value) {
167
+ const record = asRecord(value);
168
+ if (!record)
169
+ return null;
170
+ return (firstString(record.thumbnailUrl, record.heroImageUrl, record.hero_image_url, record.imageUrl, record.image_url) ??
171
+ firstMediaUrl(record.media) ??
172
+ firstStringFromArray(record.images) ??
173
+ firstStringFromArray(record.galleryUrls));
174
+ }
175
+ function firstMediaUrl(value) {
176
+ if (!Array.isArray(value))
177
+ return null;
178
+ for (const item of value) {
179
+ const media = asRecord(item);
180
+ if (!media)
181
+ continue;
182
+ const type = typeof media.type === "string" ? media.type : null;
183
+ if (type && type !== "image")
184
+ continue;
185
+ const url = firstString(media.url, media.src);
186
+ if (url)
187
+ return url;
188
+ }
189
+ return null;
190
+ }
191
+ function firstStringFromArray(value) {
192
+ if (!Array.isArray(value))
193
+ return null;
194
+ return value.find((item) => typeof item === "string" && item.length > 0) ?? null;
195
+ }
196
+ function firstString(...values) {
197
+ return (values.find((value) => typeof value === "string" && value.length > 0) ?? null);
198
+ }
199
+ function asRecord(value) {
200
+ return value && typeof value === "object" && !Array.isArray(value)
201
+ ? value
202
+ : null;
203
+ }
package/dist/service.d.ts CHANGED
@@ -682,9 +682,9 @@ export declare const hospitalityService: {
682
682
  active: boolean;
683
683
  sortOrder: number;
684
684
  ratePlanId: string;
685
+ roomTypeId: string;
685
686
  productId: string | null;
686
687
  optionId: string | null;
687
- roomTypeId: string;
688
688
  unitId: string | null;
689
689
  } | null>;
690
690
  updateRatePlanRoomType(db: PostgresJsDatabase, id: string, data: UpdateRatePlanRoomTypeInput): Promise<{
@@ -1066,8 +1066,8 @@ export declare const hospitalityService: {
1066
1066
  metadata: Record<string, unknown> | null;
1067
1067
  notes: string | null;
1068
1068
  ratePlanId: string;
1069
- bookingItemId: string;
1070
1069
  roomTypeId: string;
1070
+ bookingItemId: string;
1071
1071
  mealPlanId: string | null;
1072
1072
  roomUnitId: string | null;
1073
1073
  checkInDate: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@voyantjs/hospitality",
3
- "version": "0.32.3",
3
+ "version": "0.34.0",
4
4
  "license": "Apache-2.0",
5
5
  "type": "module",
6
6
  "exports": {
@@ -64,16 +64,16 @@
64
64
  "drizzle-orm": "^0.45.2",
65
65
  "hono": "^4.12.10",
66
66
  "zod": "^4.3.6",
67
- "@voyantjs/bookings": "0.32.3",
68
- "@voyantjs/core": "0.32.3",
69
- "@voyantjs/db": "0.32.3",
70
- "@voyantjs/facilities": "0.32.3",
71
- "@voyantjs/hono": "0.32.3",
72
- "@voyantjs/catalog": "0.32.3"
67
+ "@voyantjs/bookings": "0.34.0",
68
+ "@voyantjs/core": "0.34.0",
69
+ "@voyantjs/db": "0.34.0",
70
+ "@voyantjs/facilities": "0.34.0",
71
+ "@voyantjs/hono": "0.34.0",
72
+ "@voyantjs/catalog": "0.34.0"
73
73
  },
74
74
  "devDependencies": {
75
75
  "typescript": "^6.0.2",
76
- "@voyantjs/pricing": "0.32.3",
76
+ "@voyantjs/pricing": "0.34.0",
77
77
  "@voyantjs/voyant-typescript-config": "0.1.0"
78
78
  },
79
79
  "files": [