@voyantjs/availability 0.51.1 → 0.52.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.
@@ -1 +1 @@
1
- {"version":3,"file":"service-allocation-automation.d.ts","sourceRoot":"","sources":["../src/service-allocation-automation.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AACjE,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAQ5B,OAAO,EACL,KAAK,kBAAkB,EAIxB,MAAM,aAAa,CAAA;AACpB,OAAO,EACL,KAAK,yBAAyB,EAK/B,MAAM,yBAAyB,CAAA;AAChC,OAAO,KAAK,EAAE,0BAA0B,EAAE,4BAA4B,EAAE,MAAM,iBAAiB,CAAA;AAE/F,MAAM,MAAM,2BAA2B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,4BAA4B,CAAC,CAAA;AACtF,MAAM,MAAM,yBAAyB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,0BAA0B,CAAC,CAAA;AAMlF,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAA;IACV,eAAe,EAAE,MAAM,CAAA;IACvB,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,QAAQ,EAAE,MAAM,CAAA;IAChB,WAAW,EAAE,MAAM,CAAA;IACnB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC9B,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;CAClB;AAED,MAAM,WAAW,8BAA8B;IAC7C,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;IACnB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,MAAM,EAAE,MAAM,CAAA;IACd,SAAS,EAAE,OAAO,CAAA;IAClB,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,gBAAgB,EAAE,CAAA;CAC9B;AAED,MAAM,WAAW,0BAA0B;IACzC,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,SAAS,CAAC,EAAE,kBAAkB,EAAE,CAAA;CACjC;AAED,wBAAsB,kCAAkC,CACtD,EAAE,EAAE,kBAAkB,EACtB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,8BAA8B,EAAE,CAAC,CAyC3C;AAED,wBAAsB,mCAAmC,CACvD,EAAE,EAAE,kBAAkB,EACtB,SAAS,EAAE,MAAM,EACjB,eAAe,EAAE,MAAM,EACvB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,2BAA2B,GACjC,OAAO,CAAC,gBAAgB,CAAC,CA8C3B;AAED,wBAAsB,mCAAmC,CACvD,EAAE,EAAE,kBAAkB,EACtB,SAAS,EAAE,MAAM,EACjB,eAAe,EAAE,MAAM,EACvB,IAAI,EAAE,MAAM;;;UAeb;AAqBD,wBAAsB,kCAAkC,CACtD,EAAE,EAAE,kBAAkB,EACtB,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,yBAAyB,EAChC,OAAO,GAAE,yBAA8B,GACtC,OAAO,CAAC,0BAA0B,CAAC,CA+GrC;AAED,wBAAsB,yBAAyB,CAC7C,EAAE,EAAE,kBAAkB,EACtB,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,yBAAyB,EAChC,OAAO,GAAE,yBAA8B,GACtC,OAAO,CAAC,0BAA0B,CAAC,CAkDrC;AAED,MAAM,WAAW,4CAA4C;IAC3D;;;;OAIG;IACH,IAAI,CAAC,EAAE,MAAM,CAAA;IACb;;;;OAIG;IACH,YAAY,CAAC,EAAE,OAAO,CAAA;CACvB;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,4CAA4C,CAChE,EAAE,EAAE,kBAAkB,EACtB,MAAM,EAAE,MAAM,EACd,IAAI,GAAE,4CAAiD,GACtD,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,kBAAkB,EAAE,CAAA;CAAE,CAAC,CA6D/D"}
1
+ {"version":3,"file":"service-allocation-automation.d.ts","sourceRoot":"","sources":["../src/service-allocation-automation.ts"],"names":[],"mappings":"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"}
@@ -2,6 +2,16 @@ import { and, eq, sql } from "drizzle-orm";
2
2
  import { planRoomAllocation, planVehicleSeatAllocation, } from "./auto-allocator.js";
3
3
  import { allocationResources, availabilitySlots, productOptionResourceTemplates, } from "./schema.js";
4
4
  import { AllocationServiceError, getSlotAllocationManifest, recordAllocationAudit, } from "./service-allocation.js";
5
+ /**
6
+ * Emit `ARRAY[$1, $2, …]::text[]` so Postgres doesn't try to cast a
7
+ * tuple to `text[]`. See `sqlTextArray` in service-allocation.ts and
8
+ * issue #952.
9
+ */
10
+ function sqlTextArray(values) {
11
+ if (values.length === 0)
12
+ return sql `ARRAY[]::text[]`;
13
+ return sql `ARRAY[${sql.join(values.map((value) => sql `${value}`), sql.raw(", "))}]::text[]`;
14
+ }
5
15
  export async function listProductOptionResourceTemplates(db, productId) {
6
16
  const optionRows = await executeRows(db, sql `
7
17
  SELECT id, name, code, description, status, is_default, sort_order
@@ -15,7 +25,7 @@ export async function listProductOptionResourceTemplates(db, productId) {
15
25
  const templateRows = await executeRows(db, sql `
16
26
  SELECT id, product_option_id, kind, ref_type, ref_id, capacity, name_pattern, layout, default_count, flags, created_at, updated_at
17
27
  FROM product_option_resource_templates
18
- WHERE product_option_id = ANY(${optionIds}::text[])
28
+ WHERE product_option_id = ANY(${sqlTextArray(optionIds)})
19
29
  ORDER BY kind, created_at
20
30
  `);
21
31
  const byOption = new Map();
@@ -231,7 +241,7 @@ export async function autoAllocateSlotResources(db, slotId, input, options = {})
231
241
  SELECT
232
242
  row.traveler_id,
233
243
  jsonb_build_object(${kind}::text, row.resource_id::text)
234
- FROM unnest(${travelerIds}::text[], ${resourceIds}::text[]) AS row(traveler_id, resource_id)
244
+ FROM unnest(${sqlTextArray(travelerIds)}, ${sqlTextArray(resourceIds)}) AS row(traveler_id, resource_id)
235
245
  ON CONFLICT (traveler_id) DO UPDATE SET
236
246
  allocations =
237
247
  COALESCE(booking_traveler_travel_details.allocations, '{}'::jsonb)
@@ -143,7 +143,7 @@ export async function getSlotsResourceAvailability(db, slotIds) {
143
143
  AND b.status IN ('draft', 'on_hold', 'confirmed', 'in_progress', 'completed')
144
144
  AND ba.status IN ('held', 'confirmed', 'fulfilled')
145
145
  ) usage ON true
146
- WHERE ar.slot_id = ANY(${uniqueIds}::text[])
146
+ WHERE ar.slot_id = ANY(${sqlTextArray(uniqueIds)})
147
147
  ORDER BY ar.slot_id, ar.kind, ar.sort_order, ar.created_at
148
148
  `);
149
149
  const out = new Map();
@@ -206,7 +206,7 @@ export async function validateSlotAllocationCapacity(db, slotId, planned) {
206
206
  const resources = await executeRows(db, sql `
207
207
  SELECT id, kind, capacity, slot_id
208
208
  FROM allocation_resources
209
- WHERE slot_id = ${slotId} AND id = ANY(${resourceIds}::text[])
209
+ WHERE slot_id = ${slotId} AND id = ANY(${sqlTextArray(resourceIds)})
210
210
  FOR UPDATE
211
211
  `);
212
212
  const resourceById = new Map(resources.map((r) => [r.id, r]));
@@ -246,7 +246,7 @@ export async function validateSlotAllocationCapacity(db, slotId, planned) {
246
246
  AND ba.availability_slot_id = ${slotId}
247
247
  AND b.status IN ('draft', 'on_hold', 'confirmed', 'in_progress', 'completed')
248
248
  AND ba.status IN ('held', 'confirmed', 'fulfilled')
249
- AND btd.traveler_id <> ALL(${travelerIdsArr}::text[])
249
+ AND btd.traveler_id <> ALL(${sqlTextArray(travelerIdsArr)})
250
250
  `);
251
251
  const existingAssigned = existingRows[0]?.count ?? 0;
252
252
  const total = existingAssigned + plan.travelerIds.size;
@@ -462,7 +462,7 @@ export async function pairSharingGroup(db, slotId, input, options = {}) {
462
462
  await db.execute(sql `
463
463
  INSERT INTO booking_traveler_travel_details (traveler_id, sharing_group_id)
464
464
  SELECT id, ${sharingGroupId}
465
- FROM unnest(${input.travelerIds}::text[]) AS u(id)
465
+ FROM unnest(${sqlTextArray(input.travelerIds)}) AS u(id)
466
466
  ON CONFLICT (traveler_id) DO UPDATE SET
467
467
  sharing_group_id = EXCLUDED.sharing_group_id,
468
468
  updated_at = now()
@@ -642,13 +642,25 @@ async function loadSharingGroupLabelMap(db, groupIds) {
642
642
  label: sharingGroupLabels.label,
643
643
  })
644
644
  .from(sharingGroupLabels)
645
- .where(sql `${sharingGroupLabels.groupId} = ANY(${uniqueIds}::text[])`);
645
+ .where(sql `${sharingGroupLabels.groupId} = ANY(${sqlTextArray(uniqueIds)})`);
646
646
  return Object.fromEntries(rows.map((row) => [row.groupId, row.label]));
647
647
  }
648
648
  async function executeRows(db, query) {
649
649
  const rows = await db.execute(query);
650
650
  return Array.isArray(rows) ? rows : [];
651
651
  }
652
+ /**
653
+ * Emit a Postgres `ARRAY[$1, $2, …]::text[]` literal instead of the
654
+ * naive `${jsArray}::text[]` form. drizzle's `sql` template spreads
655
+ * JS arrays into a row constructor (`($1, $2)`) which Postgres
656
+ * refuses to cast to `text[]` — see issue #952. Empty input returns
657
+ * `ARRAY[]::text[]` which Postgres accepts.
658
+ */
659
+ function sqlTextArray(values) {
660
+ if (values.length === 0)
661
+ return sql `ARRAY[]::text[]`;
662
+ return sql `ARRAY[${sql.join(values.map((value) => sql `${value}`), sql.raw(", "))}]::text[]`;
663
+ }
652
664
  function serializeSlot(slot) {
653
665
  return {
654
666
  id: slot.id,
@@ -698,7 +710,7 @@ async function loadSlotTravelerRows(db, bookingIds) {
698
710
  (btd.dietary_encrypted IS NOT NULL) AS has_dietary_requirements
699
711
  FROM booking_travelers bt
700
712
  LEFT JOIN booking_traveler_travel_details btd ON btd.traveler_id = bt.id
701
- WHERE bt.booking_id = ANY(${bookingIds}::text[])
713
+ WHERE bt.booking_id = ANY(${sqlTextArray(bookingIds)})
702
714
  ORDER BY bt.booking_id, bt.is_primary DESC, bt.created_at
703
715
  `);
704
716
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@voyantjs/availability",
3
- "version": "0.51.1",
3
+ "version": "0.52.1",
4
4
  "license": "Apache-2.0",
5
5
  "type": "module",
6
6
  "exports": {
@@ -44,13 +44,13 @@
44
44
  "drizzle-orm": "^0.45.2",
45
45
  "hono": "^4.12.10",
46
46
  "zod": "^4.3.6",
47
- "@voyantjs/core": "0.51.1",
48
- "@voyantjs/db": "0.51.1",
49
- "@voyantjs/hono": "0.51.1"
47
+ "@voyantjs/core": "0.52.1",
48
+ "@voyantjs/db": "0.52.1",
49
+ "@voyantjs/hono": "0.52.1"
50
50
  },
51
51
  "devDependencies": {
52
52
  "typescript": "^6.0.2",
53
- "@voyantjs/products": "0.51.1",
53
+ "@voyantjs/products": "0.52.1",
54
54
  "@voyantjs/voyant-typescript-config": "0.1.0"
55
55
  },
56
56
  "files": [