@voyantjs/pricing 0.26.8 → 0.26.9

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":"service-public.d.ts","sourceRoot":"","sources":["../src/service-public.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AASjE,OAAO,KAAK,EACV,+BAA+B,EAC/B,yBAAyB,EAC1B,MAAM,wBAAwB,CAAA;AAwE/B,eAAO,MAAM,oBAAoB;kCAEzB,kBAAkB,aACX,MAAM,SACV,yBAAyB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;gCA0R5B,kBAAkB,aACX,MAAM,SACV,+BAA+B;;;;;;;;;;;;;;;;;;;;;;;;;;CAgGzC,CAAA"}
1
+ {"version":3,"file":"service-public.d.ts","sourceRoot":"","sources":["../src/service-public.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AAWjE,OAAO,KAAK,EACV,+BAA+B,EAC/B,yBAAyB,EAC1B,MAAM,wBAAwB,CAAA;AA+J/B,eAAO,MAAM,oBAAoB;kCAEzB,kBAAkB,aACX,MAAM,SACV,yBAAyB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;gCA+R5B,kBAAkB,aACX,MAAM,SACV,+BAA+B;;;;;;;;;;;;;;;;;;;;;;;;;;CAgGzC,CAAA"}
@@ -1,7 +1,8 @@
1
1
  import { availabilitySlots, availabilityStartTimes } from "@voyantjs/availability/schema";
2
2
  import { optionUnits, productOptions, products } from "@voyantjs/products/schema";
3
3
  import { and, asc, desc, eq, gte, inArray, lte, ne, or, sql } from "drizzle-orm";
4
- import { optionPriceRules, optionStartTimeRules, optionUnitPriceRules, optionUnitTiers, priceCatalogs, } from "./schema.js";
4
+ import { optionPriceRules, optionStartTimeRules, optionUnitPriceRules, optionUnitTiers, priceCatalogs, priceSchedules, } from "./schema.js";
5
+ import { pickRulesForDate } from "./service-rule-resolver.js";
5
6
  function normalizeDate(value) {
6
7
  if (!value) {
7
8
  return null;
@@ -48,6 +49,68 @@ async function resolvePublicCatalog(db, input) {
48
49
  .limit(1);
49
50
  return catalog ?? null;
50
51
  }
52
+ async function resolveQueryDate(db, query) {
53
+ if (query.date)
54
+ return query.date;
55
+ if (!query.departureId)
56
+ return null;
57
+ const [slot] = await db
58
+ .select({ dateLocal: availabilitySlots.dateLocal })
59
+ .from(availabilitySlots)
60
+ .where(eq(availabilitySlots.id, query.departureId))
61
+ .limit(1);
62
+ return slot?.dateLocal ?? null;
63
+ }
64
+ async function narrowRulesByDate(db, rules, isoDate) {
65
+ if (rules.length === 0)
66
+ return rules;
67
+ const scheduleIds = Array.from(new Set(rules.map((r) => r.priceScheduleId).filter((id) => id !== null)));
68
+ const schedules = scheduleIds.length > 0
69
+ ? await db
70
+ .select({
71
+ id: priceSchedules.id,
72
+ active: priceSchedules.active,
73
+ priority: priceSchedules.priority,
74
+ recurrenceRule: priceSchedules.recurrenceRule,
75
+ validFrom: priceSchedules.validFrom,
76
+ validTo: priceSchedules.validTo,
77
+ weekdays: priceSchedules.weekdays,
78
+ timezone: priceSchedules.timezone,
79
+ })
80
+ .from(priceSchedules)
81
+ .where(inArray(priceSchedules.id, scheduleIds))
82
+ : [];
83
+ const scheduleMap = new Map(schedules.map((s) => [
84
+ s.id,
85
+ {
86
+ id: s.id,
87
+ active: s.active,
88
+ priority: s.priority,
89
+ recurrenceRule: s.recurrenceRule,
90
+ validFrom: s.validFrom,
91
+ validTo: s.validTo,
92
+ weekdays: s.weekdays ?? null,
93
+ timezone: s.timezone,
94
+ },
95
+ ]));
96
+ const rulesByOption = new Map();
97
+ for (const r of rules) {
98
+ const existing = rulesByOption.get(r.optionId) ?? [];
99
+ existing.push(r);
100
+ rulesByOption.set(r.optionId, existing);
101
+ }
102
+ const winners = [];
103
+ for (const [, candidateRules] of rulesByOption) {
104
+ const picked = pickRulesForDate(candidateRules, scheduleMap, isoDate);
105
+ const winnerId = picked[0]?.id;
106
+ if (!winnerId)
107
+ continue;
108
+ const winner = candidateRules.find((r) => r.id === winnerId);
109
+ if (winner)
110
+ winners.push(winner);
111
+ }
112
+ return winners;
113
+ }
51
114
  export const publicPricingService = {
52
115
  async getProductPricingSnapshot(db, productId, query) {
53
116
  const product = await ensurePublicProduct(db, productId);
@@ -87,7 +150,8 @@ export const publicPricingService = {
87
150
  };
88
151
  }
89
152
  const optionIds = options.map((option) => option.id);
90
- const [units, rules] = await Promise.all([
153
+ const resolvedDate = await resolveQueryDate(db, query);
154
+ const [units, allRules] = await Promise.all([
91
155
  db
92
156
  .select({
93
157
  id: optionUnits.id,
@@ -112,11 +176,13 @@ export const publicPricingService = {
112
176
  maxPerBooking: optionPriceRules.maxPerBooking,
113
177
  isDefault: optionPriceRules.isDefault,
114
178
  cancellationPolicyId: optionPriceRules.cancellationPolicyId,
179
+ priceScheduleId: optionPriceRules.priceScheduleId,
115
180
  })
116
181
  .from(optionPriceRules)
117
182
  .where(and(eq(optionPriceRules.productId, productId), inArray(optionPriceRules.optionId, optionIds), eq(optionPriceRules.priceCatalogId, catalog.id), eq(optionPriceRules.active, true)))
118
183
  .orderBy(desc(optionPriceRules.isDefault), asc(optionPriceRules.name)),
119
184
  ]);
185
+ const rules = resolvedDate ? await narrowRulesByDate(db, allRules, resolvedDate) : allRules;
120
186
  const ruleIds = rules.map((rule) => rule.id);
121
187
  const [unitPrices, startTimeAdjustments] = await Promise.all([
122
188
  ruleIds.length > 0
@@ -0,0 +1,44 @@
1
+ import type { PostgresJsDatabase } from "drizzle-orm/postgres-js";
2
+ export interface ResolverRuleInput {
3
+ id: string;
4
+ name: string;
5
+ isDefault: boolean;
6
+ priceScheduleId: string | null;
7
+ }
8
+ export interface ResolverScheduleInput {
9
+ id: string;
10
+ active: boolean;
11
+ priority: number;
12
+ recurrenceRule: string;
13
+ validFrom: string | null;
14
+ validTo: string | null;
15
+ weekdays: string[] | null;
16
+ timezone: string | null;
17
+ }
18
+ /**
19
+ * Pick the option price rule that applies to a given date, given a set of
20
+ * candidate rules and their schedules.
21
+ *
22
+ * - Rules with a matching schedule beat rules without one.
23
+ * - Among scheduled matches, highest `priority` wins. Ties: `isDefault` first,
24
+ * then alphabetic by `name`.
25
+ * - When no schedule matches, a rule with `isDefault=true` and no schedule acts
26
+ * as the fallback. Without one, returns an empty array.
27
+ */
28
+ export declare function pickRulesForDate(rules: ResolverRuleInput[], schedules: Map<string, ResolverScheduleInput>, isoDate: string): ResolverRuleInput[];
29
+ export interface ResolveOptionPriceRulesParams {
30
+ productId: string;
31
+ optionIds: string[];
32
+ catalogId: string;
33
+ date: string;
34
+ }
35
+ /**
36
+ * DB-backed wrapper around `pickRulesForDate`. Fetches active rules for the
37
+ * product/option/catalog plus their schedules, then picks the winning rule
38
+ * per option for the given date.
39
+ *
40
+ * Returns a Map keyed by optionId. Options whose rules don't match the date
41
+ * (and have no default) are absent from the map.
42
+ */
43
+ export declare function resolveOptionPriceRulesForDate(db: PostgresJsDatabase, params: ResolveOptionPriceRulesParams): Promise<Map<string, ResolverRuleInput>>;
44
+ //# sourceMappingURL=service-rule-resolver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service-rule-resolver.d.ts","sourceRoot":"","sources":["../src/service-rule-resolver.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AAMjE,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,EAAE,OAAO,CAAA;IAClB,eAAe,EAAE,MAAM,GAAG,IAAI,CAAA;CAC/B;AAED,MAAM,WAAW,qBAAqB;IACpC,EAAE,EAAE,MAAM,CAAA;IACV,MAAM,EAAE,OAAO,CAAA;IACf,QAAQ,EAAE,MAAM,CAAA;IAChB,cAAc,EAAE,MAAM,CAAA;IACtB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,QAAQ,EAAE,MAAM,EAAE,GAAG,IAAI,CAAA;IACzB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;CACxB;AAoED;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,iBAAiB,EAAE,EAC1B,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,qBAAqB,CAAC,EAC7C,OAAO,EAAE,MAAM,GACd,iBAAiB,EAAE,CAgCrB;AAED,MAAM,WAAW,6BAA6B;IAC5C,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,MAAM,EAAE,CAAA;IACnB,SAAS,EAAE,MAAM,CAAA;IACjB,IAAI,EAAE,MAAM,CAAA;CACb;AAED;;;;;;;GAOG;AACH,wBAAsB,8BAA8B,CAClD,EAAE,EAAE,kBAAkB,EACtB,MAAM,EAAE,6BAA6B,GACpC,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC,CA8EzC"}
@@ -0,0 +1,172 @@
1
+ import { and, eq, inArray } from "drizzle-orm";
2
+ import { rrulestr } from "rrule";
3
+ import { priceSchedules } from "./schema-catalogs.js";
4
+ import { optionPriceRules } from "./schema-option-rules.js";
5
+ const ISO_DATE_RE = /^\d{4}-\d{2}-\d{2}$/;
6
+ const WEEKDAY_CODES = ["SU", "MO", "TU", "WE", "TH", "FR", "SA"];
7
+ function weekdayCode(isoDate) {
8
+ const d = new Date(`${isoDate}T00:00:00Z`);
9
+ return WEEKDAY_CODES[d.getUTCDay()] ?? "MO";
10
+ }
11
+ function dateInWindow(isoDate, from, to) {
12
+ if (from && isoDate < from)
13
+ return false;
14
+ if (to && isoDate > to)
15
+ return false;
16
+ return true;
17
+ }
18
+ function rruleMatchesDate(ruleString, isoDate, anchor) {
19
+ const trimmed = ruleString.trim();
20
+ if (trimmed === "")
21
+ return true;
22
+ const dtstart = `${anchor.replace(/-/g, "")}T000000Z`;
23
+ const hasDtstart = /(?:^|\n)DTSTART[:;]/.test(trimmed);
24
+ const hasRrule = /(?:^|\n)RRULE[:;]/.test(trimmed);
25
+ const body = hasRrule ? trimmed : `RRULE:${trimmed}`;
26
+ const fullRule = hasDtstart ? body : `DTSTART:${dtstart}\n${body}`;
27
+ let parsed;
28
+ try {
29
+ parsed = rrulestr(fullRule);
30
+ }
31
+ catch {
32
+ return false;
33
+ }
34
+ const start = new Date(`${isoDate}T00:00:00Z`);
35
+ const end = new Date(start.getTime() + 24 * 60 * 60 * 1000);
36
+ const occurrences = parsed.between(start, end, true);
37
+ return occurrences.some((occ) => occ.toISOString().slice(0, 10) === isoDate);
38
+ }
39
+ function scheduleMatchesDate(s, isoDate) {
40
+ if (!s.active)
41
+ return false;
42
+ if (!dateInWindow(isoDate, s.validFrom, s.validTo))
43
+ return false;
44
+ if (s.weekdays && s.weekdays.length > 0) {
45
+ if (!s.weekdays.includes(weekdayCode(isoDate)))
46
+ return false;
47
+ }
48
+ const anchor = s.validFrom ?? "2000-01-01";
49
+ if (!rruleMatchesDate(s.recurrenceRule, isoDate, anchor))
50
+ return false;
51
+ return true;
52
+ }
53
+ function compareMatches(a, b) {
54
+ if (b.priority !== a.priority)
55
+ return b.priority - a.priority;
56
+ const aDef = a.rule.isDefault ? 1 : 0;
57
+ const bDef = b.rule.isDefault ? 1 : 0;
58
+ if (aDef !== bDef)
59
+ return bDef - aDef;
60
+ return a.rule.name.localeCompare(b.rule.name);
61
+ }
62
+ /**
63
+ * Pick the option price rule that applies to a given date, given a set of
64
+ * candidate rules and their schedules.
65
+ *
66
+ * - Rules with a matching schedule beat rules without one.
67
+ * - Among scheduled matches, highest `priority` wins. Ties: `isDefault` first,
68
+ * then alphabetic by `name`.
69
+ * - When no schedule matches, a rule with `isDefault=true` and no schedule acts
70
+ * as the fallback. Without one, returns an empty array.
71
+ */
72
+ export function pickRulesForDate(rules, schedules, isoDate) {
73
+ if (!ISO_DATE_RE.test(isoDate)) {
74
+ throw new Error(`pickRulesForDate: expected ISO yyyy-mm-dd, got "${isoDate}"`);
75
+ }
76
+ const matches = [];
77
+ for (const rule of rules) {
78
+ if (rule.priceScheduleId === null) {
79
+ if (rule.isDefault) {
80
+ matches.push({ rule, priority: Number.NEGATIVE_INFINITY, scheduled: false });
81
+ }
82
+ continue;
83
+ }
84
+ const schedule = schedules.get(rule.priceScheduleId);
85
+ if (!schedule)
86
+ continue;
87
+ if (!scheduleMatchesDate(schedule, isoDate))
88
+ continue;
89
+ matches.push({ rule, priority: schedule.priority, scheduled: true });
90
+ }
91
+ if (matches.length === 0)
92
+ return [];
93
+ const scheduled = matches.filter((m) => m.scheduled);
94
+ if (scheduled.length > 0) {
95
+ scheduled.sort(compareMatches);
96
+ const winner = scheduled[0];
97
+ return winner ? [winner.rule] : [];
98
+ }
99
+ matches.sort(compareMatches);
100
+ const winner = matches[0];
101
+ return winner ? [winner.rule] : [];
102
+ }
103
+ /**
104
+ * DB-backed wrapper around `pickRulesForDate`. Fetches active rules for the
105
+ * product/option/catalog plus their schedules, then picks the winning rule
106
+ * per option for the given date.
107
+ *
108
+ * Returns a Map keyed by optionId. Options whose rules don't match the date
109
+ * (and have no default) are absent from the map.
110
+ */
111
+ export async function resolveOptionPriceRulesForDate(db, params) {
112
+ if (params.optionIds.length === 0)
113
+ return new Map();
114
+ const rules = await db
115
+ .select({
116
+ id: optionPriceRules.id,
117
+ optionId: optionPriceRules.optionId,
118
+ name: optionPriceRules.name,
119
+ isDefault: optionPriceRules.isDefault,
120
+ priceScheduleId: optionPriceRules.priceScheduleId,
121
+ })
122
+ .from(optionPriceRules)
123
+ .where(and(eq(optionPriceRules.productId, params.productId), inArray(optionPriceRules.optionId, params.optionIds), eq(optionPriceRules.priceCatalogId, params.catalogId), eq(optionPriceRules.active, true)));
124
+ const scheduleIds = Array.from(new Set(rules.map((r) => r.priceScheduleId).filter((id) => id !== null)));
125
+ const schedules = scheduleIds.length > 0
126
+ ? await db
127
+ .select({
128
+ id: priceSchedules.id,
129
+ active: priceSchedules.active,
130
+ priority: priceSchedules.priority,
131
+ recurrenceRule: priceSchedules.recurrenceRule,
132
+ validFrom: priceSchedules.validFrom,
133
+ validTo: priceSchedules.validTo,
134
+ weekdays: priceSchedules.weekdays,
135
+ timezone: priceSchedules.timezone,
136
+ })
137
+ .from(priceSchedules)
138
+ .where(inArray(priceSchedules.id, scheduleIds))
139
+ : [];
140
+ const scheduleMap = new Map(schedules.map((s) => [
141
+ s.id,
142
+ {
143
+ id: s.id,
144
+ active: s.active,
145
+ priority: s.priority,
146
+ recurrenceRule: s.recurrenceRule,
147
+ validFrom: s.validFrom,
148
+ validTo: s.validTo,
149
+ weekdays: s.weekdays ?? null,
150
+ timezone: s.timezone,
151
+ },
152
+ ]));
153
+ const rulesByOption = new Map();
154
+ for (const r of rules) {
155
+ const existing = rulesByOption.get(r.optionId) ?? [];
156
+ existing.push({
157
+ id: r.id,
158
+ name: r.name,
159
+ isDefault: r.isDefault,
160
+ priceScheduleId: r.priceScheduleId,
161
+ });
162
+ rulesByOption.set(r.optionId, existing);
163
+ }
164
+ const result = new Map();
165
+ for (const [optionId, candidateRules] of rulesByOption) {
166
+ const picked = pickRulesForDate(candidateRules, scheduleMap, params.date);
167
+ const first = picked[0];
168
+ if (first)
169
+ result.set(optionId, first);
170
+ }
171
+ return result;
172
+ }
@@ -2,6 +2,8 @@ import { z } from "zod";
2
2
  export declare const publicProductPricingQuerySchema: z.ZodObject<{
3
3
  catalogId: z.ZodOptional<z.ZodString>;
4
4
  optionId: z.ZodOptional<z.ZodString>;
5
+ date: z.ZodOptional<z.ZodString>;
6
+ departureId: z.ZodOptional<z.ZodString>;
5
7
  }, z.core.$strip>;
6
8
  export declare const publicAvailabilitySnapshotQuerySchema: z.ZodObject<{
7
9
  optionId: z.ZodOptional<z.ZodString>;
@@ -1 +1 @@
1
- {"version":3,"file":"validation-public.d.ts","sourceRoot":"","sources":["../src/validation-public.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAWvB,eAAO,MAAM,+BAA+B;;;iBAG1C,CAAA;AAEF,eAAO,MAAM,qCAAqC;;;;;;;;;;;;iBAOhD,CAAA;AAEF,eAAO,MAAM,wBAAwB;;;;;iBAKnC,CAAA;AAEF,eAAO,MAAM,uBAAuB;;;;;;iBAMlC,CAAA;AAEF,eAAO,MAAM,2BAA2B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAYtC,CAAA;AAEF,eAAO,MAAM,+BAA+B;;;;;;;;;;;;;;;;;iBAS1C,CAAA;AAEF,eAAO,MAAM,6BAA6B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAYxC,CAAA;AAEF,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBASnC,CAAA;AAEF,eAAO,MAAM,kCAAkC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAI7C,CAAA;AAEF,eAAO,MAAM,iCAAiC;;;;;iBAK5C,CAAA;AAEF,eAAO,MAAM,4BAA4B;;;;;;;;;;;;;;;;;;;;;;;;iBAcvC,CAAA;AAEF,eAAO,MAAM,gCAAgC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAM3C,CAAA;AAEF,MAAM,MAAM,yBAAyB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,+BAA+B,CAAC,CAAA;AACvF,MAAM,MAAM,+BAA+B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qCAAqC,CAAC,CAAA"}
1
+ {"version":3,"file":"validation-public.d.ts","sourceRoot":"","sources":["../src/validation-public.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAWvB,eAAO,MAAM,+BAA+B;;;;;iBAK1C,CAAA;AAEF,eAAO,MAAM,qCAAqC;;;;;;;;;;;;iBAOhD,CAAA;AAEF,eAAO,MAAM,wBAAwB;;;;;iBAKnC,CAAA;AAEF,eAAO,MAAM,uBAAuB;;;;;;iBAMlC,CAAA;AAEF,eAAO,MAAM,2BAA2B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAYtC,CAAA;AAEF,eAAO,MAAM,+BAA+B;;;;;;;;;;;;;;;;;iBAS1C,CAAA;AAEF,eAAO,MAAM,6BAA6B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAYxC,CAAA;AAEF,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBASnC,CAAA;AAEF,eAAO,MAAM,kCAAkC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAI7C,CAAA;AAEF,eAAO,MAAM,iCAAiC;;;;;iBAK5C,CAAA;AAEF,eAAO,MAAM,4BAA4B;;;;;;;;;;;;;;;;;;;;;;;;iBAcvC,CAAA;AAEF,eAAO,MAAM,gCAAgC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAM3C,CAAA;AAEF,MAAM,MAAM,yBAAyB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,+BAA+B,CAAC,CAAA;AACvF,MAAM,MAAM,+BAA+B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qCAAqC,CAAC,CAAA"}
@@ -6,6 +6,8 @@ const isoDateSchema = z.string().date();
6
6
  export const publicProductPricingQuerySchema = z.object({
7
7
  catalogId: z.string().optional(),
8
8
  optionId: z.string().optional(),
9
+ date: isoDateSchema.optional(),
10
+ departureId: z.string().optional(),
9
11
  });
10
12
  export const publicAvailabilitySnapshotQuerySchema = z.object({
11
13
  optionId: z.string().optional(),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@voyantjs/pricing",
3
- "version": "0.26.8",
3
+ "version": "0.26.9",
4
4
  "license": "Apache-2.0",
5
5
  "type": "module",
6
6
  "exports": {
@@ -38,17 +38,18 @@
38
38
  "dependencies": {
39
39
  "drizzle-orm": "^0.45.2",
40
40
  "hono": "^4.12.10",
41
+ "rrule": "^2.8.1",
41
42
  "zod": "^4.3.6",
42
- "@voyantjs/availability": "0.26.8",
43
- "@voyantjs/core": "0.26.8",
44
- "@voyantjs/db": "0.26.8",
45
- "@voyantjs/hono": "0.26.8",
46
- "@voyantjs/products": "0.26.8"
43
+ "@voyantjs/availability": "0.26.9",
44
+ "@voyantjs/core": "0.26.9",
45
+ "@voyantjs/db": "0.26.9",
46
+ "@voyantjs/hono": "0.26.9",
47
+ "@voyantjs/products": "0.26.9"
47
48
  },
48
49
  "devDependencies": {
49
50
  "typescript": "^6.0.2",
50
- "@voyantjs/extras": "0.26.8",
51
- "@voyantjs/facilities": "0.26.8",
51
+ "@voyantjs/extras": "0.26.9",
52
+ "@voyantjs/facilities": "0.26.9",
52
53
  "@voyantjs/voyant-typescript-config": "0.1.0"
53
54
  },
54
55
  "files": [