@voyantjs/products 0.2.0 → 0.3.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.
Files changed (51) hide show
  1. package/dist/index.d.ts +3 -0
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/index.js +5 -0
  4. package/dist/routes-public.d.ts +337 -0
  5. package/dist/routes-public.d.ts.map +1 -0
  6. package/dist/routes-public.js +32 -0
  7. package/dist/routes.d.ts +4 -4
  8. package/dist/schema-core.d.ts +897 -0
  9. package/dist/schema-core.d.ts.map +1 -0
  10. package/dist/schema-core.js +77 -0
  11. package/dist/schema-itinerary.d.ts +828 -0
  12. package/dist/schema-itinerary.d.ts.map +1 -0
  13. package/dist/schema-itinerary.js +77 -0
  14. package/dist/schema-relations.d.ts +99 -0
  15. package/dist/schema-relations.d.ts.map +1 -0
  16. package/dist/schema-relations.js +155 -0
  17. package/dist/schema-settings.d.ts +1749 -0
  18. package/dist/schema-settings.d.ts.map +1 -0
  19. package/dist/schema-settings.js +175 -0
  20. package/dist/schema-shared.d.ts +15 -0
  21. package/dist/schema-shared.d.ts.map +1 -0
  22. package/dist/schema-shared.js +91 -0
  23. package/dist/schema-taxonomy.d.ts +573 -0
  24. package/dist/schema-taxonomy.d.ts.map +1 -0
  25. package/dist/schema-taxonomy.js +65 -0
  26. package/dist/schema.d.ts +6 -4155
  27. package/dist/schema.d.ts.map +1 -1
  28. package/dist/schema.js +6 -653
  29. package/dist/service-public.d.ts +259 -0
  30. package/dist/service-public.d.ts.map +1 -0
  31. package/dist/service-public.js +479 -0
  32. package/dist/service.d.ts +4 -4
  33. package/dist/validation-config.d.ts +233 -0
  34. package/dist/validation-config.d.ts.map +1 -0
  35. package/dist/validation-config.js +73 -0
  36. package/dist/validation-content.d.ts +358 -0
  37. package/dist/validation-content.d.ts.map +1 -0
  38. package/dist/validation-content.js +177 -0
  39. package/dist/validation-core.d.ts +268 -0
  40. package/dist/validation-core.d.ts.map +1 -0
  41. package/dist/validation-core.js +91 -0
  42. package/dist/validation-public.d.ts +454 -0
  43. package/dist/validation-public.d.ts.map +1 -0
  44. package/dist/validation-public.js +130 -0
  45. package/dist/validation-shared.d.ts +108 -0
  46. package/dist/validation-shared.d.ts.map +1 -0
  47. package/dist/validation-shared.js +87 -0
  48. package/dist/validation.d.ts +5 -854
  49. package/dist/validation.d.ts.map +1 -1
  50. package/dist/validation.js +5 -433
  51. package/package.json +12 -4
@@ -0,0 +1,479 @@
1
+ import { and, asc, desc, eq, ilike, inArray, notInArray, or, sql } from "drizzle-orm";
2
+ import { productCapabilities, productCategories, productCategoryProducts, productFaqs, productFeatures, productLocations, productMedia, products, productTagProducts, productTags, productTranslations, productTypes, productVisibilitySettings, } from "./schema.js";
3
+ function impossibleCondition() {
4
+ return sql `1 = 0`;
5
+ }
6
+ function normalizeDate(value) {
7
+ if (!value) {
8
+ return null;
9
+ }
10
+ return value instanceof Date ? value.toISOString() : value;
11
+ }
12
+ function normalizeLanguageTag(value) {
13
+ const normalized = value?.trim().toLowerCase();
14
+ return normalized || null;
15
+ }
16
+ async function listProductIdsForCategory(db, categoryId) {
17
+ const rows = await db
18
+ .select({ productId: productCategoryProducts.productId })
19
+ .from(productCategoryProducts)
20
+ .innerJoin(productCategories, eq(productCategories.id, productCategoryProducts.categoryId))
21
+ .where(and(eq(productCategoryProducts.categoryId, categoryId), eq(productCategories.active, true)));
22
+ return rows.map((row) => row.productId);
23
+ }
24
+ async function listProductIdsForTag(db, tagId) {
25
+ const rows = await db
26
+ .select({ productId: productTagProducts.productId })
27
+ .from(productTagProducts)
28
+ .where(eq(productTagProducts.tagId, tagId));
29
+ return rows.map((row) => row.productId);
30
+ }
31
+ async function listFeaturedProductIds(db) {
32
+ const rows = await db
33
+ .select({ productId: productVisibilitySettings.productId })
34
+ .from(productVisibilitySettings)
35
+ .where(eq(productVisibilitySettings.isFeatured, true));
36
+ return rows.map((row) => row.productId);
37
+ }
38
+ async function hydrateCatalogProducts(db, productRows, options) {
39
+ if (productRows.length === 0) {
40
+ return [];
41
+ }
42
+ const productIds = productRows.map((product) => product.id);
43
+ const productTypeIds = Array.from(new Set(productRows
44
+ .map((product) => product.productTypeId)
45
+ .filter((value) => Boolean(value))));
46
+ const [categoryRows, tagRows, translationRows, typeRows, capabilityRows, mediaRows, featuredRows, featureRows, faqRows, locationRows,] = await Promise.all([
47
+ db
48
+ .select({
49
+ productId: productCategoryProducts.productId,
50
+ id: productCategories.id,
51
+ parentId: productCategories.parentId,
52
+ name: productCategories.name,
53
+ slug: productCategories.slug,
54
+ description: productCategories.description,
55
+ sortOrder: productCategories.sortOrder,
56
+ })
57
+ .from(productCategoryProducts)
58
+ .innerJoin(productCategories, eq(productCategories.id, productCategoryProducts.categoryId))
59
+ .where(and(inArray(productCategoryProducts.productId, productIds), eq(productCategories.active, true)))
60
+ .orderBy(asc(productCategoryProducts.sortOrder), asc(productCategories.sortOrder), asc(productCategories.name)),
61
+ db
62
+ .select({
63
+ productId: productTagProducts.productId,
64
+ id: productTags.id,
65
+ name: productTags.name,
66
+ })
67
+ .from(productTagProducts)
68
+ .innerJoin(productTags, eq(productTags.id, productTagProducts.tagId))
69
+ .where(inArray(productTagProducts.productId, productIds))
70
+ .orderBy(asc(productTags.name)),
71
+ options?.languageTag
72
+ ? db
73
+ .select({
74
+ productId: productTranslations.productId,
75
+ languageTag: productTranslations.languageTag,
76
+ slug: productTranslations.slug,
77
+ name: productTranslations.name,
78
+ shortDescription: productTranslations.shortDescription,
79
+ description: productTranslations.description,
80
+ seoTitle: productTranslations.seoTitle,
81
+ seoDescription: productTranslations.seoDescription,
82
+ })
83
+ .from(productTranslations)
84
+ .where(and(inArray(productTranslations.productId, productIds), eq(productTranslations.languageTag, options.languageTag)))
85
+ : Promise.resolve([]),
86
+ productTypeIds.length > 0
87
+ ? db
88
+ .select({
89
+ id: productTypes.id,
90
+ code: productTypes.code,
91
+ name: productTypes.name,
92
+ description: productTypes.description,
93
+ })
94
+ .from(productTypes)
95
+ .where(and(inArray(productTypes.id, productTypeIds), eq(productTypes.active, true)))
96
+ : Promise.resolve([]),
97
+ db
98
+ .select({
99
+ productId: productCapabilities.productId,
100
+ capability: productCapabilities.capability,
101
+ })
102
+ .from(productCapabilities)
103
+ .where(and(inArray(productCapabilities.productId, productIds), eq(productCapabilities.enabled, true)))
104
+ .orderBy(asc(productCapabilities.capability)),
105
+ db
106
+ .select({
107
+ productId: productMedia.productId,
108
+ id: productMedia.id,
109
+ mediaType: productMedia.mediaType,
110
+ name: productMedia.name,
111
+ url: productMedia.url,
112
+ mimeType: productMedia.mimeType,
113
+ altText: productMedia.altText,
114
+ sortOrder: productMedia.sortOrder,
115
+ isCover: productMedia.isCover,
116
+ })
117
+ .from(productMedia)
118
+ .where(inArray(productMedia.productId, productIds))
119
+ .orderBy(desc(productMedia.isCover), asc(productMedia.sortOrder), asc(productMedia.createdAt)),
120
+ db
121
+ .select({ productId: productVisibilitySettings.productId })
122
+ .from(productVisibilitySettings)
123
+ .where(and(inArray(productVisibilitySettings.productId, productIds), eq(productVisibilitySettings.isFeatured, true))),
124
+ options?.includeContent
125
+ ? db
126
+ .select({
127
+ productId: productFeatures.productId,
128
+ id: productFeatures.id,
129
+ featureType: productFeatures.featureType,
130
+ title: productFeatures.title,
131
+ description: productFeatures.description,
132
+ sortOrder: productFeatures.sortOrder,
133
+ })
134
+ .from(productFeatures)
135
+ .where(inArray(productFeatures.productId, productIds))
136
+ .orderBy(asc(productFeatures.sortOrder), asc(productFeatures.createdAt))
137
+ : Promise.resolve([]),
138
+ options?.includeContent
139
+ ? db
140
+ .select({
141
+ productId: productFaqs.productId,
142
+ id: productFaqs.id,
143
+ question: productFaqs.question,
144
+ answer: productFaqs.answer,
145
+ sortOrder: productFaqs.sortOrder,
146
+ })
147
+ .from(productFaqs)
148
+ .where(inArray(productFaqs.productId, productIds))
149
+ .orderBy(asc(productFaqs.sortOrder), asc(productFaqs.createdAt))
150
+ : Promise.resolve([]),
151
+ options?.includeContent
152
+ ? db
153
+ .select({
154
+ productId: productLocations.productId,
155
+ id: productLocations.id,
156
+ locationType: productLocations.locationType,
157
+ title: productLocations.title,
158
+ address: productLocations.address,
159
+ city: productLocations.city,
160
+ countryCode: productLocations.countryCode,
161
+ latitude: productLocations.latitude,
162
+ longitude: productLocations.longitude,
163
+ sortOrder: productLocations.sortOrder,
164
+ })
165
+ .from(productLocations)
166
+ .where(inArray(productLocations.productId, productIds))
167
+ .orderBy(asc(productLocations.sortOrder), asc(productLocations.createdAt))
168
+ : Promise.resolve([]),
169
+ ]);
170
+ const categoriesByProduct = new Map();
171
+ for (const row of categoryRows) {
172
+ const existing = categoriesByProduct.get(row.productId) ?? [];
173
+ existing.push(row);
174
+ categoriesByProduct.set(row.productId, existing);
175
+ }
176
+ const tagsByProduct = new Map();
177
+ for (const row of tagRows) {
178
+ const existing = tagsByProduct.get(row.productId) ?? [];
179
+ existing.push(row);
180
+ tagsByProduct.set(row.productId, existing);
181
+ }
182
+ const translationByProduct = new Map(translationRows.map((row) => [row.productId, row]));
183
+ const capabilitiesByProduct = new Map();
184
+ for (const row of capabilityRows) {
185
+ const existing = capabilitiesByProduct.get(row.productId) ?? [];
186
+ existing.push(row.capability);
187
+ capabilitiesByProduct.set(row.productId, existing);
188
+ }
189
+ const mediaByProduct = new Map();
190
+ for (const row of mediaRows) {
191
+ const existing = mediaByProduct.get(row.productId) ?? [];
192
+ existing.push(row);
193
+ mediaByProduct.set(row.productId, existing);
194
+ }
195
+ const featuresByProduct = new Map();
196
+ for (const row of featureRows) {
197
+ const existing = featuresByProduct.get(row.productId) ?? [];
198
+ existing.push(row);
199
+ featuresByProduct.set(row.productId, existing);
200
+ }
201
+ const faqsByProduct = new Map();
202
+ for (const row of faqRows) {
203
+ const existing = faqsByProduct.get(row.productId) ?? [];
204
+ existing.push(row);
205
+ faqsByProduct.set(row.productId, existing);
206
+ }
207
+ const locationsByProduct = new Map();
208
+ for (const row of locationRows) {
209
+ const existing = locationsByProduct.get(row.productId) ?? [];
210
+ existing.push(row);
211
+ locationsByProduct.set(row.productId, existing);
212
+ }
213
+ const typeById = new Map(typeRows.map((row) => [row.id, row]));
214
+ const featuredIds = new Set(featuredRows.map((row) => row.productId));
215
+ return productRows.map((product) => {
216
+ const translation = translationByProduct.get(product.id) ?? null;
217
+ const media = (mediaByProduct.get(product.id) ?? []).map((row) => ({
218
+ id: row.id,
219
+ mediaType: row.mediaType,
220
+ name: row.name,
221
+ url: row.url,
222
+ mimeType: row.mimeType ?? null,
223
+ altText: row.altText ?? null,
224
+ sortOrder: row.sortOrder,
225
+ isCover: row.isCover,
226
+ }));
227
+ const base = {
228
+ id: product.id,
229
+ name: translation?.name ?? product.name,
230
+ description: translation?.description ?? product.description ?? null,
231
+ contentLanguageTag: translation?.languageTag ?? null,
232
+ slug: translation?.slug ?? null,
233
+ shortDescription: translation?.shortDescription ?? null,
234
+ seoTitle: translation?.seoTitle ?? null,
235
+ seoDescription: translation?.seoDescription ?? null,
236
+ bookingMode: product.bookingMode,
237
+ capacityMode: product.capacityMode,
238
+ visibility: product.visibility,
239
+ sellCurrency: product.sellCurrency,
240
+ sellAmountCents: product.sellAmountCents ?? null,
241
+ startDate: normalizeDate(product.startDate),
242
+ endDate: normalizeDate(product.endDate),
243
+ pax: product.pax ?? null,
244
+ productType: product.productTypeId ? (typeById.get(product.productTypeId) ?? null) : null,
245
+ categories: (categoriesByProduct.get(product.id) ?? []).map((row) => ({
246
+ id: row.id,
247
+ parentId: row.parentId ?? null,
248
+ name: row.name,
249
+ slug: row.slug,
250
+ description: row.description ?? null,
251
+ sortOrder: row.sortOrder,
252
+ })),
253
+ tags: (tagsByProduct.get(product.id) ?? []).map((row) => ({
254
+ id: row.id,
255
+ name: row.name,
256
+ })),
257
+ capabilities: capabilitiesByProduct.get(product.id) ?? [],
258
+ coverMedia: media.find((item) => item.isCover) ?? media[0] ?? null,
259
+ isFeatured: featuredIds.has(product.id),
260
+ };
261
+ if (!options?.includeContent) {
262
+ return base;
263
+ }
264
+ return {
265
+ ...base,
266
+ media,
267
+ features: (featuresByProduct.get(product.id) ?? []).map((row) => ({
268
+ id: row.id,
269
+ featureType: row.featureType,
270
+ title: row.title,
271
+ description: row.description ?? null,
272
+ sortOrder: row.sortOrder,
273
+ })),
274
+ faqs: (faqsByProduct.get(product.id) ?? []).map((row) => ({
275
+ id: row.id,
276
+ question: row.question,
277
+ answer: row.answer,
278
+ sortOrder: row.sortOrder,
279
+ })),
280
+ locations: (locationsByProduct.get(product.id) ?? []).map((row) => ({
281
+ id: row.id,
282
+ locationType: row.locationType,
283
+ title: row.title,
284
+ address: row.address ?? null,
285
+ city: row.city ?? null,
286
+ countryCode: row.countryCode ?? null,
287
+ latitude: row.latitude ?? null,
288
+ longitude: row.longitude ?? null,
289
+ sortOrder: row.sortOrder,
290
+ })),
291
+ };
292
+ });
293
+ }
294
+ function orderProducts(query) {
295
+ const direction = query.direction === "desc" ? desc : asc;
296
+ switch (query.sort) {
297
+ case "createdAt":
298
+ return direction(products.createdAt);
299
+ case "startDate":
300
+ return direction(products.startDate);
301
+ case "price":
302
+ return direction(products.sellAmountCents);
303
+ default:
304
+ return direction(products.name);
305
+ }
306
+ }
307
+ export const publicProductsService = {
308
+ async listCatalogProducts(db, query) {
309
+ const conditions = [
310
+ eq(products.status, "active"),
311
+ eq(products.activated, true),
312
+ eq(products.visibility, "public"),
313
+ ];
314
+ if (query.search) {
315
+ const term = `%${query.search}%`;
316
+ const searchCondition = or(ilike(products.name, term), ilike(products.description, term));
317
+ if (searchCondition) {
318
+ conditions.push(searchCondition);
319
+ }
320
+ }
321
+ if (query.bookingMode) {
322
+ conditions.push(eq(products.bookingMode, query.bookingMode));
323
+ }
324
+ if (query.capacityMode) {
325
+ conditions.push(eq(products.capacityMode, query.capacityMode));
326
+ }
327
+ if (query.productTypeId) {
328
+ conditions.push(eq(products.productTypeId, query.productTypeId));
329
+ }
330
+ if (query.categoryId) {
331
+ const productIds = await listProductIdsForCategory(db, query.categoryId);
332
+ conditions.push(productIds.length > 0 ? inArray(products.id, productIds) : impossibleCondition());
333
+ }
334
+ if (query.tagId) {
335
+ const productIds = await listProductIdsForTag(db, query.tagId);
336
+ conditions.push(productIds.length > 0 ? inArray(products.id, productIds) : impossibleCondition());
337
+ }
338
+ if (query.featured !== undefined) {
339
+ const productIds = await listFeaturedProductIds(db);
340
+ conditions.push(query.featured
341
+ ? productIds.length > 0
342
+ ? inArray(products.id, productIds)
343
+ : impossibleCondition()
344
+ : productIds.length > 0
345
+ ? notInArray(products.id, productIds)
346
+ : sql `1 = 1`);
347
+ }
348
+ const where = and(...conditions);
349
+ const [rows, countResult] = await Promise.all([
350
+ db
351
+ .select()
352
+ .from(products)
353
+ .where(where)
354
+ .orderBy(orderProducts(query), asc(products.id))
355
+ .limit(query.limit)
356
+ .offset(query.offset),
357
+ db.select({ count: sql `count(*)::int` }).from(products).where(where),
358
+ ]);
359
+ return {
360
+ data: await hydrateCatalogProducts(db, rows, {
361
+ languageTag: normalizeLanguageTag(query.languageTag),
362
+ }),
363
+ total: countResult[0]?.count ?? 0,
364
+ limit: query.limit,
365
+ offset: query.offset,
366
+ };
367
+ },
368
+ async getCatalogProductById(db, id, query = {}) {
369
+ const [row] = await db
370
+ .select()
371
+ .from(products)
372
+ .where(and(eq(products.id, id), eq(products.status, "active"), eq(products.activated, true), eq(products.visibility, "public")))
373
+ .limit(1);
374
+ if (!row) {
375
+ return null;
376
+ }
377
+ const [product] = await hydrateCatalogProducts(db, [row], {
378
+ includeContent: true,
379
+ languageTag: normalizeLanguageTag(query.languageTag),
380
+ });
381
+ return product ?? null;
382
+ },
383
+ async getCatalogProductBySlug(db, slug, query = {}) {
384
+ const normalizedSlug = slug.trim().toLowerCase();
385
+ const normalizedLanguageTag = normalizeLanguageTag(query.languageTag);
386
+ const conditions = [
387
+ sql `lower(${productTranslations.slug}) = ${normalizedSlug}`,
388
+ eq(products.status, "active"),
389
+ eq(products.activated, true),
390
+ eq(products.visibility, "public"),
391
+ ];
392
+ if (normalizedLanguageTag) {
393
+ conditions.push(eq(productTranslations.languageTag, normalizedLanguageTag));
394
+ }
395
+ const [row] = await db
396
+ .select({
397
+ productId: products.id,
398
+ languageTag: productTranslations.languageTag,
399
+ })
400
+ .from(productTranslations)
401
+ .innerJoin(products, eq(products.id, productTranslations.productId))
402
+ .where(and(...conditions))
403
+ .orderBy(desc(productTranslations.updatedAt))
404
+ .limit(1);
405
+ if (!row) {
406
+ return null;
407
+ }
408
+ return this.getCatalogProductById(db, row.productId, {
409
+ languageTag: normalizedLanguageTag ?? row.languageTag,
410
+ });
411
+ },
412
+ async listCatalogCategories(db, query) {
413
+ const conditions = [eq(productCategories.active, true)];
414
+ if (query.parentId) {
415
+ conditions.push(eq(productCategories.parentId, query.parentId));
416
+ }
417
+ if (query.search) {
418
+ const term = `%${query.search}%`;
419
+ const searchCondition = or(ilike(productCategories.name, term), ilike(productCategories.slug, term));
420
+ if (searchCondition) {
421
+ conditions.push(searchCondition);
422
+ }
423
+ }
424
+ const where = and(...conditions);
425
+ const [rows, countResult] = await Promise.all([
426
+ db
427
+ .select({
428
+ id: productCategories.id,
429
+ parentId: productCategories.parentId,
430
+ name: productCategories.name,
431
+ slug: productCategories.slug,
432
+ description: productCategories.description,
433
+ sortOrder: productCategories.sortOrder,
434
+ })
435
+ .from(productCategories)
436
+ .where(where)
437
+ .orderBy(asc(productCategories.sortOrder), asc(productCategories.name))
438
+ .limit(query.limit)
439
+ .offset(query.offset),
440
+ db.select({ count: sql `count(*)::int` }).from(productCategories).where(where),
441
+ ]);
442
+ return {
443
+ data: rows.map((row) => ({
444
+ ...row,
445
+ parentId: row.parentId ?? null,
446
+ description: row.description ?? null,
447
+ })),
448
+ total: countResult[0]?.count ?? 0,
449
+ limit: query.limit,
450
+ offset: query.offset,
451
+ };
452
+ },
453
+ async listCatalogTags(db, query) {
454
+ const conditions = [];
455
+ if (query.search) {
456
+ conditions.push(ilike(productTags.name, `%${query.search}%`));
457
+ }
458
+ const where = conditions.length > 0 ? and(...conditions) : undefined;
459
+ const [rows, countResult] = await Promise.all([
460
+ db
461
+ .select({
462
+ id: productTags.id,
463
+ name: productTags.name,
464
+ })
465
+ .from(productTags)
466
+ .where(where)
467
+ .orderBy(asc(productTags.name))
468
+ .limit(query.limit)
469
+ .offset(query.offset),
470
+ db.select({ count: sql `count(*)::int` }).from(productTags).where(where),
471
+ ]);
472
+ return {
473
+ data: rows,
474
+ total: countResult[0]?.count ?? 0,
475
+ limit: query.limit,
476
+ offset: query.offset,
477
+ };
478
+ },
479
+ };
package/dist/service.d.ts CHANGED
@@ -352,8 +352,8 @@ export declare const productsService: {
352
352
  createdAt: Date;
353
353
  updatedAt: Date;
354
354
  id: string;
355
- capability: "on_request" | "private" | "instant_confirmation" | "pickup_available" | "dropoff_available" | "guided" | "shared" | "digital_ticket" | "voucher_required" | "external_inventory" | "multi_day" | "accommodation" | "transport";
356
355
  notes: string | null;
356
+ capability: "on_request" | "private" | "instant_confirmation" | "pickup_available" | "dropoff_available" | "guided" | "shared" | "digital_ticket" | "voucher_required" | "external_inventory" | "multi_day" | "accommodation" | "transport";
357
357
  } | null>;
358
358
  updateCapability(db: PostgresJsDatabase, id: string, data: UpdateProductCapabilityInput): Promise<{
359
359
  id: string;
@@ -439,8 +439,8 @@ export declare const productsService: {
439
439
  description: string | null;
440
440
  id: string;
441
441
  sortOrder: number;
442
- featureType: "other" | "inclusion" | "exclusion" | "highlight" | "important_information";
443
442
  title: string;
443
+ featureType: "other" | "inclusion" | "exclusion" | "highlight" | "important_information";
444
444
  } | null>;
445
445
  updateFeature(db: PostgresJsDatabase, id: string, data: UpdateProductFeatureInput): Promise<{
446
446
  id: string;
@@ -1169,8 +1169,8 @@ export declare const productsService: {
1169
1169
  updatedAt: Date;
1170
1170
  description: string | null;
1171
1171
  id: string;
1172
- title: string | null;
1173
1172
  dayNumber: number;
1173
+ title: string | null;
1174
1174
  location: string | null;
1175
1175
  } | null | undefined>;
1176
1176
  updateDay(db: PostgresJsDatabase, dayId: string, data: UpdateDayInput): Promise<{
@@ -1618,11 +1618,11 @@ export declare const productsService: {
1618
1618
  id: string;
1619
1619
  costAmountCents: number;
1620
1620
  sortOrder: number | null;
1621
- notes: string | null;
1622
1621
  dayId: string;
1623
1622
  serviceType: "other" | "transfer" | "accommodation" | "experience" | "guide" | "meal";
1624
1623
  costCurrency: string;
1625
1624
  quantity: number;
1625
+ notes: string | null;
1626
1626
  } | null | undefined>;
1627
1627
  updateDayService(db: PostgresJsDatabase, productId: string, serviceId: string, data: UpdateDayServiceInput): Promise<{
1628
1628
  id: string;