@aglyn/plugins-bookings 1.0.0-beta.221 → 1.0.0-beta.222

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 (52) hide show
  1. package/README.md +3 -2
  2. package/package.json +11 -11
  3. package/src/lib/components/book-meeting-action.js +5 -3
  4. package/src/lib/components/book-meeting-action.js.map +1 -1
  5. package/src/lib/components/booking.d.ts +33 -0
  6. package/src/lib/components/booking.js +260 -54
  7. package/src/lib/components/booking.js.map +1 -1
  8. package/src/lib/components/bookings-console-page.js +139 -15
  9. package/src/lib/components/bookings-console-page.js.map +1 -1
  10. package/src/lib/declarations.console-server.d.ts +34 -0
  11. package/src/lib/declarations.console-server.js +84 -0
  12. package/src/lib/declarations.console-server.js.map +1 -0
  13. package/src/lib/model/booking-contact-fields.d.ts +88 -0
  14. package/src/lib/model/booking-contact-fields.js +130 -0
  15. package/src/lib/model/booking-contact-fields.js.map +1 -0
  16. package/src/lib/model/booking-price.d.ts +51 -0
  17. package/src/lib/model/booking-price.js +61 -0
  18. package/src/lib/model/booking-price.js.map +1 -0
  19. package/src/lib/model/booking-record.d.ts +7 -0
  20. package/src/lib/model/booking-record.js +11 -2
  21. package/src/lib/model/booking-record.js.map +1 -1
  22. package/src/lib/model/bookings-record-counts.d.ts +25 -0
  23. package/src/lib/model/bookings-record-counts.js +34 -0
  24. package/src/lib/model/bookings-record-counts.js.map +1 -0
  25. package/src/lib/model/bookings.d.ts +61 -4
  26. package/src/lib/model/bookings.js +81 -15
  27. package/src/lib/model/bookings.js.map +1 -1
  28. package/src/lib/model/index.d.ts +2 -0
  29. package/src/lib/model/index.js +2 -0
  30. package/src/lib/model/index.js.map +1 -1
  31. package/src/lib/plugin.js +14 -0
  32. package/src/lib/plugin.js.map +1 -1
  33. package/src/lib/server/billing-webhook.js +33 -15
  34. package/src/lib/server/billing-webhook.js.map +1 -1
  35. package/src/lib/server/booking-crm.js +4 -1
  36. package/src/lib/server/booking-crm.js.map +1 -1
  37. package/src/lib/server/person-eraser.d.ts +36 -0
  38. package/src/lib/server/person-eraser.js +48 -0
  39. package/src/lib/server/person-eraser.js.map +1 -0
  40. package/src/lib/server/refund.js +2 -2
  41. package/src/lib/server/refund.js.map +1 -1
  42. package/src/lib/server.js +97 -36
  43. package/src/lib/server.js.map +1 -1
  44. package/src/lib/transfer/bookings-transfer-common.d.ts +68 -0
  45. package/src/lib/transfer/bookings-transfer-common.js +130 -0
  46. package/src/lib/transfer/bookings-transfer-common.js.map +1 -0
  47. package/src/lib/transfer/bookings-transfer.d.ts +86 -0
  48. package/src/lib/transfer/bookings-transfer.js +613 -0
  49. package/src/lib/transfer/bookings-transfer.js.map +1 -0
  50. package/src/lib/transfer/bookings-transfer.server.d.ts +26 -0
  51. package/src/lib/transfer/bookings-transfer.server.js +31 -0
  52. package/src/lib/transfer/bookings-transfer.server.js.map +1 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/bookings/src/lib/transfer/bookings-transfer.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n TRANSFER_ID_FIELD,\n buildMatchLookup,\n type TransferCatalogInput,\n type TransferField,\n} from '@aglyn/aglyn/data-transfer'\nimport type {\n PluginTransferResource,\n TransferReadOptions,\n TransferReadPage,\n TransferResourceContext,\n} from '@aglyn/aglyn/plugin-manager/plugin-transfer-resources'\nimport { zonedDateTime } from '@aglyn/shared-util-timestamp/zoned-time'\nimport { FieldPath } from 'firebase-admin/firestore'\nimport { bookingTimeZone, storedBookingTimeZone } from '../model/booking-time'\nimport {\n BOOKINGS_TRANSFER_MATCH_KEYS,\n type BookingsTransferFilter,\n parseBookingsTransferFilter,\n} from './bookings-transfer-common'\n\n/**\n * BOOKINGS, EXPORTED (the server half of the `bookings` transfer resource).\n *\n * Every booking of one site, `hosts/{hostId}/bookings/{id}`, as rows of the\n * fields a person picks: the service and the slot, the customer, what was\n * paid, and when the platform did what to it.\n *\n * ## Exported, never imported\n *\n * The resource declares `exportOnly`, so it registers no `apply` or\n * `revert` (its `lookup` answers the Aglyn ID only) and the upload route\n * refuses it. There is no safe\n * write path to give it: the only thing that creates a booking is the\n * booking route, which holds the slot, may start a Stripe charge, emails the\n * customer and files the meeting in the CRM — and the hourly reminder job\n * would email any confirmed booking it found a day out. A booking written\n * from a file would be an appointment nobody booked.\n *\n * ## Which bookings a page reads\n *\n * - `ids`: the selection, read by id in the order given; ids that name no\n * booking are skipped. The cursor is the offset into the list.\n * - `filter`: one of the list's filters (`bookings-transfer-common.ts`), as\n * one Firestore query:\n * - none: every booking, by start, `startsAtMs` ascending — the\n * single-field index;\n * - upcoming: `endsAtMs >= asOf`, by end ascending — the single-field\n * index on `endsAtMs` (the range field has to lead the order);\n * - one service: `serviceId ==`, by start — the declared composite\n * `serviceId ASC, startsAtMs ASC`;\n * - one booker: `email ==`, by start — the composite\n * `email ASC, startsAtMs ASC`, which `bookings-export-indexes.spec.ts`\n * holds the index file to.\n * Every order breaks ties by document id, and the cursor is the last row's\n * order value and id, so a page never repeats or skips a row.\n * - `scopeTokens` narrows nothing here. Bookings are a SITE's records and\n * carry no `visibleTo`; the export route admits a reader only with\n * `data.manage` on the site named, so a collaborator who reaches this read\n * reaches every booking of that site, the way the Bookings page shows them.\n *\n * Times go out as ISO instants in UTC, beside the booking's own zone and\n * the start and end as a wall clock in it. Amounts are dollars (every\n * booking is charged in USD), from the stored cents.\n */\n\ntype Firestore = FirebaseFirestore.Firestore\ntype Query = FirebaseFirestore.Query\ntype DocumentData = FirebaseFirestore.DocumentData\n\nexport interface BookingsTransferDeps {\n firestore(): Firestore\n /** The clock the upcoming filter reads when it names no moment. */\n now?: () => number\n}\n\n/** The most rows one page answers when the engine does not say. */\nconst DEFAULT_PAGE_ROWS = 500\nconst MAX_PAGE_ROWS = 1000\n/** Firestore's bound on an `in` list. */\nconst IN_LIMIT = 30\n\n/*==========================================\n * THE FIELDS\n *=========================================*/\n\nexport const BOOKINGS_TRANSFER_GROUPS = [\n { id: 'booking', label: 'Booking' },\n { id: 'customer', label: 'Customer' },\n { id: 'payment', label: 'Payment' },\n { id: 'system', label: 'System' },\n] as const\n\nconst readOnly = (field: TransferField): TransferField => ({\n ...field,\n readOnly: true,\n})\n\n/** The booking's own stored fields. */\nconst STANDARD: readonly TransferField[] = (\n [\n {\n id: 'serviceId',\n label: 'Service ID',\n group: 'booking',\n type: 'text',\n description: 'The service that was booked.',\n },\n {\n id: 'serviceName',\n label: 'Service',\n group: 'booking',\n type: 'text',\n aliases: ['service name'],\n description: 'The service’s name when it was booked.',\n },\n {\n id: 'startsAt',\n label: 'Starts (UTC)',\n group: 'booking',\n type: 'datetime',\n aliases: ['start', 'starts at', 'start time'],\n },\n {\n id: 'endsAt',\n label: 'Ends (UTC)',\n group: 'booking',\n type: 'datetime',\n aliases: ['end', 'ends at', 'end time'],\n },\n {\n id: 'timeZone',\n label: 'Time zone',\n group: 'booking',\n type: 'text',\n aliases: ['timezone'],\n description:\n 'The zone the slot was offered in. Bookings made before it was stored read it from the service, then the site.',\n },\n {\n id: 'status',\n label: 'Status',\n group: 'booking',\n type: 'text',\n description: 'Awaiting payment, Confirmed or Canceled.',\n },\n {\n id: 'name',\n label: 'Name',\n group: 'customer',\n type: 'text',\n aliases: ['customer', 'customer name'],\n },\n {\n id: 'email',\n label: 'Email',\n group: 'customer',\n type: 'email',\n aliases: ['customer email'],\n },\n { id: 'phone', label: 'Phone', group: 'customer', type: 'phone' },\n {\n id: 'address',\n label: 'Address',\n group: 'customer',\n type: 'longText',\n description:\n 'Where the job is, as the customer typed it, when the service asked.',\n },\n {\n id: 'crmRef',\n label: 'CRM record',\n group: 'customer',\n type: 'text',\n description: 'The CRM record the booking link carried, as kind:id.',\n },\n {\n id: 'paidAmount',\n label: 'Amount paid',\n group: 'payment',\n type: 'currency',\n description: 'In US dollars, tax included.',\n },\n {\n id: 'tax',\n label: 'Tax',\n group: 'payment',\n type: 'currency',\n description: 'In US dollars.',\n },\n {\n id: 'fee',\n label: 'Platform fee',\n group: 'payment',\n type: 'currency',\n description: 'The platform’s fee on the charge, in US dollars.',\n },\n {\n id: 'refunded',\n label: 'Refunded',\n group: 'payment',\n type: 'currency',\n description: 'In US dollars.',\n },\n {\n id: 'taxMode',\n label: 'Tax mode',\n group: 'payment',\n type: 'text',\n description: 'How tax was charged on the booking.',\n },\n ] satisfies TransferField[]\n).map(readOnly)\n\n/** Computed from the booking and its service when read. */\nconst DERIVED: readonly TransferField[] = (\n [\n {\n id: 'serviceCurrentName',\n label: 'Service (current name)',\n group: 'booking',\n type: 'text',\n description:\n 'The service’s name today; blank when the service no longer exists.',\n },\n {\n id: 'startsLocal',\n label: 'Starts (local time)',\n group: 'booking',\n type: 'text',\n description: 'The start as a clock in the booking’s time zone read it.',\n },\n {\n id: 'endsLocal',\n label: 'Ends (local time)',\n group: 'booking',\n type: 'text',\n description: 'The end as a clock in the booking’s time zone read it.',\n },\n {\n id: 'durationMinutes',\n label: 'Duration (minutes)',\n group: 'booking',\n type: 'integer',\n },\n ] satisfies TransferField[]\n).map(readOnly)\n\n/** Written by the platform: Stripe's handles and the booking's history. */\nconst SYSTEM: readonly TransferField[] = (\n [\n {\n id: 'paymentIntentId',\n label: 'Stripe payment ID',\n group: 'payment',\n type: 'text',\n },\n {\n id: 'checkoutSessionId',\n label: 'Stripe checkout session ID',\n group: 'payment',\n type: 'text',\n },\n {\n id: 'holdExpiresAt',\n label: 'Payment hold expires',\n group: 'payment',\n type: 'datetime',\n description: 'When an unpaid booking’s slot is released.',\n },\n { id: 'createdAt', label: 'Booked', group: 'system', type: 'datetime' },\n {\n id: 'confirmedAt',\n label: 'Payment confirmed',\n group: 'system',\n type: 'datetime',\n },\n {\n id: 'reminderSentAt',\n label: 'Reminder sent',\n group: 'system',\n type: 'datetime',\n },\n {\n id: 'customerErasedAt',\n label: 'Customer erased',\n group: 'system',\n type: 'datetime',\n description: 'When the customer’s details were erased from the booking.',\n },\n ] satisfies TransferField[]\n).map(readOnly)\n\n/** The catalog, the same for every site. */\nexport function bookingsTransferCatalog(): TransferCatalogInput {\n return {\n standard: STANDARD,\n derived: DERIVED,\n system: SYSTEM,\n groups: BOOKINGS_TRANSFER_GROUPS,\n }\n}\n\nconst STATUS_LABELS: Readonly<Record<string, string>> = {\n pendingPayment: 'Awaiting payment',\n confirmed: 'Confirmed',\n canceled: 'Canceled',\n}\n\n/*==========================================\n * READING A BOOKING\n *=========================================*/\n\n/** Epoch milliseconds from a stored moment: a number, a Timestamp, a Date or a string. */\nfunction millisOf(value: unknown): number | null {\n if (value === null || value === undefined || value === '') return null\n if (typeof value === 'number') return Number.isFinite(value) ? value : null\n if (value instanceof Date)\n return Number.isFinite(value.getTime()) ? value.getTime() : null\n if (typeof value === 'string') {\n const parsed = Date.parse(value)\n return Number.isFinite(parsed) ? parsed : null\n }\n if (typeof value === 'object') {\n const stamp = value as {\n toMillis?: () => number\n seconds?: number\n _seconds?: number\n nanoseconds?: number\n _nanoseconds?: number\n }\n if (typeof stamp.toMillis === 'function') return stamp.toMillis()\n const seconds = stamp.seconds ?? stamp._seconds\n if (typeof seconds === 'number')\n return (\n seconds * 1000 +\n Math.floor((stamp.nanoseconds ?? stamp._nanoseconds ?? 0) / 1e6)\n )\n }\n return null\n}\n\nfunction isoOf(value: unknown): string | null {\n const ms = millisOf(value)\n return ms === null ? null : new Date(ms).toISOString()\n}\n\n/** Dollars from stored cents; blank when the booking holds none. */\nfunction dollarsOf(cents: unknown): number | null {\n if (cents === null || cents === undefined || cents === '') return null\n const value = Number(cents)\n return Number.isFinite(value) ? Math.round(value) / 100 : null\n}\n\nfunction textOf(value: unknown): string | null {\n if (value === null || value === undefined) return null\n const text = String(value)\n return text === '' ? null : text\n}\n\nconst pad = (value: number) => String(value).padStart(2, '0')\n\n/** `2026-04-24 15:00` — the wall clock in `timeZone` at `atMs`. */\nfunction localTextOf(atMs: number | null, timeZone: string): string | null {\n if (atMs === null) return null\n try {\n const at = zonedDateTime(atMs, timeZone)\n return `${at.year}-${pad(at.month)}-${pad(at.day)} ${pad(at.hour)}:${pad(at.minute)}`\n } catch {\n return null\n }\n}\n\n/** What a page reads besides the bookings, loaded only when a chosen field needs it. */\ninterface PageContext {\n serviceOf(serviceId: string): Promise<DocumentData | null>\n zoneOf(booking: DocumentData): Promise<string>\n}\n\nfunction pageContext(\n db: Firestore,\n ctx: TransferResourceContext,\n hostId: string,\n): PageContext {\n let services: Promise<Map<string, DocumentData>> | null = null\n let site: Promise<{\n host: DocumentData | null\n org: DocumentData | null\n }> | null = null\n const servicesOfSite = () =>\n (services ??= db\n .collection('hosts')\n .doc(hostId)\n .collection('services')\n .get()\n .then(\n (snapshot) => new Map(snapshot.docs.map((doc) => [doc.id, doc.data()])),\n ))\n const siteZones = () =>\n (site ??= Promise.all([\n db.collection('hosts').doc(hostId).get(),\n db.collection('orgs').doc(ctx.orgId).get(),\n ]).then(([host, org]) => ({\n host: host.data() ?? null,\n org: org.data() ?? null,\n })))\n return {\n serviceOf: async (serviceId) =>\n (await servicesOfSite()).get(serviceId) ?? null,\n async zoneOf(booking) {\n const stored = storedBookingTimeZone(booking)\n if (stored) return stored\n // Written before the zone was stored: the booking route's own chain.\n const [service, zones] = await Promise.all([\n servicesOfSite().then(\n (all) => all.get(String(booking['serviceId'] ?? '')) ?? null,\n ),\n siteZones(),\n ])\n return bookingTimeZone({\n service: service as { timezone?: unknown } | null,\n host: zones.host as { timeZone?: string } | null,\n org: zones.org as { timeZone?: string } | null,\n })\n },\n }\n}\n\nconst ZONE_FIELDS = new Set(['timeZone', 'startsLocal', 'endsLocal'])\n\n/** One booking as a row holding only `fieldIds`. */\nasync function bookingRow(\n id: string,\n booking: DocumentData,\n fieldIds: readonly string[],\n page: PageContext,\n): Promise<Record<string, unknown>> {\n const startsAtMs = millisOf(booking['startsAtMs'])\n const endsAtMs = millisOf(booking['endsAtMs'])\n const zone = fieldIds.some((fieldId) => ZONE_FIELDS.has(fieldId))\n ? await page.zoneOf(booking)\n : 'UTC'\n const row: Record<string, unknown> = {}\n for (const fieldId of fieldIds) {\n switch (fieldId) {\n case 'id':\n row[fieldId] = id\n break\n case 'serviceId':\n case 'serviceName':\n case 'name':\n case 'phone':\n case 'address':\n case 'crmRef':\n case 'taxMode':\n case 'paymentIntentId':\n case 'checkoutSessionId':\n row[fieldId] = textOf(booking[fieldId])\n break\n case 'email':\n // `null` once the customer was erased.\n row[fieldId] = textOf(booking['email'])\n break\n case 'serviceCurrentName': {\n const service = await page.serviceOf(String(booking['serviceId'] ?? ''))\n row[fieldId] =\n service && !service['deletedAt'] ? textOf(service['name']) : null\n break\n }\n case 'startsAt':\n row[fieldId] = isoOf(startsAtMs)\n break\n case 'endsAt':\n row[fieldId] = isoOf(endsAtMs)\n break\n case 'timeZone':\n row[fieldId] = zone\n break\n case 'startsLocal':\n row[fieldId] = localTextOf(startsAtMs, zone)\n break\n case 'endsLocal':\n row[fieldId] = localTextOf(endsAtMs, zone)\n break\n case 'durationMinutes':\n row[fieldId] =\n startsAtMs !== null && endsAtMs !== null\n ? Math.round((endsAtMs - startsAtMs) / 60_000)\n : null\n break\n case 'status': {\n const status = textOf(booking['status'])\n row[fieldId] = status ? (STATUS_LABELS[status] ?? status) : null\n break\n }\n case 'paidAmount':\n row[fieldId] = dollarsOf(booking['paidAmountCents'])\n break\n case 'tax':\n row[fieldId] = dollarsOf(booking['taxCents'])\n break\n case 'fee':\n row[fieldId] = dollarsOf(booking['feeCents'])\n break\n case 'refunded':\n row[fieldId] = dollarsOf(booking['refundedCents'])\n break\n case 'holdExpiresAt':\n // Only an unpaid booking holds its slot; the stamp is cleared on payment.\n row[fieldId] = isoOf(booking['expiresAtMs'])\n break\n case 'createdAt':\n case 'confirmedAt':\n case 'reminderSentAt':\n row[fieldId] = isoOf(booking[fieldId])\n break\n case 'customerErasedAt':\n row[fieldId] = isoOf(booking['customerErasedAtMs'])\n break\n default:\n row[fieldId] = null\n }\n }\n return row\n}\n\n/*==========================================\n * THE QUERIES\n *=========================================*/\n\n/** The query a filter makes, and the field it is ordered by (then by id, the same way). */\ninterface OrderedQuery {\n query: Query\n orderField: 'startsAtMs' | 'endsAtMs'\n}\n\nfunction filteredQuery(\n bookings: FirebaseFirestore.CollectionReference,\n filter: BookingsTransferFilter | null,\n nowMs: number,\n): OrderedQuery {\n if (!filter) return { query: bookings, orderField: 'startsAtMs' }\n switch (filter.kind) {\n case 'upcoming':\n return {\n query: bookings.where('endsAtMs', '>=', filter.asOfMs ?? nowMs),\n orderField: 'endsAtMs',\n }\n case 'email':\n return {\n query: bookings.where('email', '==', filter.email),\n orderField: 'startsAtMs',\n }\n case 'service':\n return {\n query: bookings.where('serviceId', '==', filter.serviceId),\n orderField: 'startsAtMs',\n }\n }\n}\n\ninterface QueryCursor {\n at: number\n id: string\n}\n\nfunction readQueryCursor(cursor: string | null): QueryCursor | null {\n if (cursor === null) return null\n try {\n const parsed = JSON.parse(cursor) as Partial<QueryCursor>\n if (\n typeof parsed.at === 'number' &&\n typeof parsed.id === 'string' &&\n parsed.id\n ) {\n return { at: parsed.at, id: parsed.id }\n }\n } catch {\n // Falls through to the refusal.\n }\n throw new Error('bookings export: the page cursor could not be read')\n}\n\nfunction hostIdOf(ctx: TransferResourceContext): string {\n const hostId = String(ctx.hostId ?? '').trim()\n if (!hostId || hostId.includes('/'))\n throw new Error('bookings export: a site is required')\n return hostId\n}\n\nfunction pageSizeOf(options: TransferReadOptions | undefined): number {\n const size = Math.floor(Number(options?.pageSize ?? DEFAULT_PAGE_ROWS))\n return Math.max(\n 1,\n Math.min(MAX_PAGE_ROWS, Number.isFinite(size) ? size : DEFAULT_PAGE_ROWS),\n )\n}\n\nfunction chunks<T>(items: readonly T[], size: number): T[][] {\n const out: T[][] = []\n for (let index = 0; index < items.length; index += size)\n out.push(items.slice(index, index + size))\n return out\n}\n\n/*==========================================\n * THE RESOURCE\n *=========================================*/\n\n/** The `bookings` resource over `deps.firestore()`. Export only: a lookup by id, and no apply or revert. */\nexport function createBookingsTransferResource(\n deps: BookingsTransferDeps,\n): PluginTransferResource {\n const now = deps.now ?? Date.now\n const bookingsOf = (hostId: string) =>\n deps.firestore().collection('hosts').doc(hostId).collection('bookings')\n\n return {\n fields: () => bookingsTransferCatalog(),\n matchKeys: BOOKINGS_TRANSFER_MATCH_KEYS,\n\n async count(ctx, options) {\n const hostId = hostIdOf(ctx)\n const bookings = bookingsOf(hostId)\n if (options.ids) {\n // Only the ids that name a booking, so the count is the rows the file holds.\n const ids = [...new Set(options.ids)].filter(\n (id) => id && !id.includes('/'),\n )\n let total = 0\n for (const part of chunks(ids, IN_LIMIT)) {\n const snapshot = await bookings\n .where(FieldPath.documentId(), 'in', part)\n .count()\n .get()\n total += snapshot.data().count\n }\n return total\n }\n const { query } = filteredQuery(\n bookings,\n parseBookingsTransferFilter(options.filter),\n now(),\n )\n return (await query.count().get()).data().count\n },\n\n async readPage(ctx, cursor, fieldIds, options): Promise<TransferReadPage> {\n const hostId = hostIdOf(ctx)\n const db = deps.firestore()\n const bookings = bookingsOf(hostId)\n const size = pageSizeOf(options)\n const page = pageContext(db, ctx, hostId)\n\n if (options?.ids) {\n const ids = [...new Set(options.ids)].filter(\n (id) => id && !id.includes('/'),\n )\n const offset = cursor === null ? 0 : Number(cursor)\n if (!Number.isInteger(offset) || offset < 0) {\n throw new Error('bookings export: the page cursor could not be read')\n }\n const slice = ids.slice(offset, offset + size)\n const snapshots = slice.length\n ? await db.getAll(...slice.map((id) => bookings.doc(id)))\n : []\n const rows: Array<Record<string, unknown>> = []\n for (const snapshot of snapshots) {\n if (snapshot.exists)\n rows.push(\n await bookingRow(\n snapshot.id,\n snapshot.data() ?? {},\n fieldIds,\n page,\n ),\n )\n }\n const next = offset + slice.length\n return { rows, next: next < ids.length ? String(next) : null }\n }\n\n const { query, orderField } = filteredQuery(\n bookings,\n parseBookingsTransferFilter(options?.filter),\n now(),\n )\n let ordered = query\n .orderBy(orderField, 'asc')\n .orderBy(FieldPath.documentId(), 'asc')\n const after = readQueryCursor(cursor)\n if (after) ordered = ordered.startAfter(after.at, after.id)\n // One more than the page, to know without a second read whether another follows.\n const snapshot = await ordered.limit(size + 1).get()\n const docs = snapshot.docs.slice(0, size)\n const rows: Array<Record<string, unknown>> = []\n for (const doc of docs)\n rows.push(await bookingRow(doc.id, doc.data(), fieldIds, page))\n const last = docs[docs.length - 1]\n const next =\n snapshot.docs.length > size && last\n ? JSON.stringify({\n at: Number(last.get(orderField) ?? 0),\n id: last.id,\n } satisfies QueryCursor)\n : null\n return { rows, next }\n },\n\n /** What a booking holds now, by its Aglyn ID — the one key a resource nothing imports into answers. */\n async lookup(ctx, requests) {\n const hostId = hostIdOf(ctx)\n const db = deps.firestore()\n const bookings = bookingsOf(hostId)\n const byId = requests.filter((request) => request.fieldId === TRANSFER_ID_FIELD)\n const ids = [...new Set(byId.flatMap((request) => request.values))].filter(\n (id) => id && !id.includes('/'),\n )\n const catalog = bookingsTransferCatalog()\n const fieldIds = [\n TRANSFER_ID_FIELD,\n ...[...(catalog.standard ?? []), ...(catalog.system ?? [])].map((field) => field.id),\n ]\n const page = pageContext(db, ctx, hostId)\n const records = new Map<string, Record<string, unknown>>()\n for (const part of chunks(ids, MAX_PAGE_ROWS)) {\n const snapshots = part.length ? await db.getAll(...part.map((id) => bookings.doc(id))) : []\n for (const snapshot of snapshots) {\n if (snapshot.exists) records.set(snapshot.id, await bookingRow(snapshot.id, snapshot.data() ?? {}, fieldIds, page))\n }\n }\n const lookup = buildMatchLookup(\n [...records].map(([id, values]) => ({ id, values })),\n byId,\n )\n return { lookup, records }\n },\n }\n}\n"],"names":["TRANSFER_ID_FIELD","buildMatchLookup","zonedDateTime","FieldPath","bookingTimeZone","storedBookingTimeZone","BOOKINGS_TRANSFER_MATCH_KEYS","parseBookingsTransferFilter","DEFAULT_PAGE_ROWS","MAX_PAGE_ROWS","IN_LIMIT","BOOKINGS_TRANSFER_GROUPS","id","label","readOnly","field","STANDARD","group","type","description","aliases","map","DERIVED","SYSTEM","bookingsTransferCatalog","standard","derived","system","groups","STATUS_LABELS","pendingPayment","confirmed","canceled","millisOf","value","undefined","Number","isFinite","Date","getTime","parsed","parse","stamp","toMillis","seconds","_seconds","Math","floor","nanoseconds","_nanoseconds","isoOf","ms","toISOString","dollarsOf","cents","round","textOf","text","String","pad","padStart","localTextOf","atMs","timeZone","at","year","month","day","hour","minute","pageContext","db","ctx","hostId","services","site","servicesOfSite","collection","doc","get","then","snapshot","Map","docs","data","siteZones","Promise","all","orgId","host","org","serviceOf","serviceId","zoneOf","booking","stored","service","zones","ZONE_FIELDS","Set","bookingRow","fieldIds","page","startsAtMs","endsAtMs","zone","some","fieldId","has","row","status","filteredQuery","bookings","filter","nowMs","query","orderField","kind","where","asOfMs","email","readQueryCursor","cursor","JSON","Error","hostIdOf","trim","includes","pageSizeOf","options","size","pageSize","max","min","chunks","items","out","index","length","push","slice","createBookingsTransferResource","deps","now","bookingsOf","firestore","fields","matchKeys","count","ids","total","part","documentId","readPage","last","offset","isInteger","snapshots","getAll","rows","exists","next","ordered","orderBy","after","startAfter","limit","stringify","lookup","requests","catalog","byId","request","flatMap","values","records","set"],"mappings":";AAAA;;;;;;;;;;;;;;;CAeC,GAED,SACEA,iBAAiB,EACjBC,gBAAgB,QAGX,6BAA4B;AAOnC,SAASC,aAAa,QAAQ,0CAAyC;AACvE,SAASC,SAAS,QAAQ,2BAA0B;AACpD,SAASC,eAAe,EAAEC,qBAAqB,QAAQ,2BAAuB;AAC9E,SACEC,4BAA4B,EAE5BC,2BAA2B,QACtB,gCAA4B;AAyDnC,iEAAiE,GACjE,MAAMC,oBAAoB;AAC1B,MAAMC,gBAAgB;AACtB,uCAAuC,GACvC,MAAMC,WAAW;AAEjB;;2CAE2C,GAE3C,OAAO,MAAMC,2BAA2B;IACtC;QAAEC,IAAI;QAAWC,OAAO;IAAU;IAClC;QAAED,IAAI;QAAYC,OAAO;IAAW;IACpC;QAAED,IAAI;QAAWC,OAAO;IAAU;IAClC;QAAED,IAAI;QAAUC,OAAO;IAAS;CACjC,CAAS;AAEV,MAAMC,WAAW,CAACC,QAAyC,aACtDA;QACHD,UAAU;;AAGZ,qCAAqC,GACrC,MAAME,WAAqC,AACzC;IACE;QACEJ,IAAI;QACJC,OAAO;QACPI,OAAO;QACPC,MAAM;QACNC,aAAa;IACf;IACA;QACEP,IAAI;QACJC,OAAO;QACPI,OAAO;QACPC,MAAM;QACNE,SAAS;YAAC;SAAe;QACzBD,aAAa;IACf;IACA;QACEP,IAAI;QACJC,OAAO;QACPI,OAAO;QACPC,MAAM;QACNE,SAAS;YAAC;YAAS;YAAa;SAAa;IAC/C;IACA;QACER,IAAI;QACJC,OAAO;QACPI,OAAO;QACPC,MAAM;QACNE,SAAS;YAAC;YAAO;YAAW;SAAW;IACzC;IACA;QACER,IAAI;QACJC,OAAO;QACPI,OAAO;QACPC,MAAM;QACNE,SAAS;YAAC;SAAW;QACrBD,aACE;IACJ;IACA;QACEP,IAAI;QACJC,OAAO;QACPI,OAAO;QACPC,MAAM;QACNC,aAAa;IACf;IACA;QACEP,IAAI;QACJC,OAAO;QACPI,OAAO;QACPC,MAAM;QACNE,SAAS;YAAC;YAAY;SAAgB;IACxC;IACA;QACER,IAAI;QACJC,OAAO;QACPI,OAAO;QACPC,MAAM;QACNE,SAAS;YAAC;SAAiB;IAC7B;IACA;QAAER,IAAI;QAASC,OAAO;QAASI,OAAO;QAAYC,MAAM;IAAQ;IAChE;QACEN,IAAI;QACJC,OAAO;QACPI,OAAO;QACPC,MAAM;QACNC,aACE;IACJ;IACA;QACEP,IAAI;QACJC,OAAO;QACPI,OAAO;QACPC,MAAM;QACNC,aAAa;IACf;IACA;QACEP,IAAI;QACJC,OAAO;QACPI,OAAO;QACPC,MAAM;QACNC,aAAa;IACf;IACA;QACEP,IAAI;QACJC,OAAO;QACPI,OAAO;QACPC,MAAM;QACNC,aAAa;IACf;IACA;QACEP,IAAI;QACJC,OAAO;QACPI,OAAO;QACPC,MAAM;QACNC,aAAa;IACf;IACA;QACEP,IAAI;QACJC,OAAO;QACPI,OAAO;QACPC,MAAM;QACNC,aAAa;IACf;IACA;QACEP,IAAI;QACJC,OAAO;QACPI,OAAO;QACPC,MAAM;QACNC,aAAa;IACf;CACD,CACDE,GAAG,CAACP;AAEN,yDAAyD,GACzD,MAAMQ,UAAoC,AACxC;IACE;QACEV,IAAI;QACJC,OAAO;QACPI,OAAO;QACPC,MAAM;QACNC,aACE;IACJ;IACA;QACEP,IAAI;QACJC,OAAO;QACPI,OAAO;QACPC,MAAM;QACNC,aAAa;IACf;IACA;QACEP,IAAI;QACJC,OAAO;QACPI,OAAO;QACPC,MAAM;QACNC,aAAa;IACf;IACA;QACEP,IAAI;QACJC,OAAO;QACPI,OAAO;QACPC,MAAM;IACR;CACD,CACDG,GAAG,CAACP;AAEN,yEAAyE,GACzE,MAAMS,SAAmC,AACvC;IACE;QACEX,IAAI;QACJC,OAAO;QACPI,OAAO;QACPC,MAAM;IACR;IACA;QACEN,IAAI;QACJC,OAAO;QACPI,OAAO;QACPC,MAAM;IACR;IACA;QACEN,IAAI;QACJC,OAAO;QACPI,OAAO;QACPC,MAAM;QACNC,aAAa;IACf;IACA;QAAEP,IAAI;QAAaC,OAAO;QAAUI,OAAO;QAAUC,MAAM;IAAW;IACtE;QACEN,IAAI;QACJC,OAAO;QACPI,OAAO;QACPC,MAAM;IACR;IACA;QACEN,IAAI;QACJC,OAAO;QACPI,OAAO;QACPC,MAA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"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Aglyn LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+ import type { PluginTransferResource } from '@aglyn/aglyn/plugin-manager/plugin-transfer-resources';
18
+ /**
19
+ * The `bookings` transfer resource over the platform's Firestore. Loaded by
20
+ * the console-server declarations with the first export, never at boot: this
21
+ * module is what brings the Admin SDK, so the declarations import it lazily
22
+ * and import no other library lazily — a lazy import of a library would make
23
+ * every static import of it, across the plugin and the apps, a module
24
+ * boundary error.
25
+ */
26
+ export declare function adminBookingsTransferResource(): PluginTransferResource;
@@ -0,0 +1,31 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Aglyn LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */ import { firebaseAdmin } from "@aglyn/tenant-data-admin/server/firebase-admin";
17
+ import { createBookingsTransferResource } from "./bookings-transfer.js";
18
+ /**
19
+ * The `bookings` transfer resource over the platform's Firestore. Loaded by
20
+ * the console-server declarations with the first export, never at boot: this
21
+ * module is what brings the Admin SDK, so the declarations import it lazily
22
+ * and import no other library lazily — a lazy import of a library would make
23
+ * every static import of it, across the plugin and the apps, a module
24
+ * boundary error.
25
+ */ export function adminBookingsTransferResource() {
26
+ return createBookingsTransferResource({
27
+ firestore: ()=>firebaseAdmin.app().firestore()
28
+ });
29
+ }
30
+
31
+ //# sourceMappingURL=bookings-transfer.server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/bookings/src/lib/transfer/bookings-transfer.server.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { firebaseAdmin } from '@aglyn/tenant-data-admin/server/firebase-admin'\nimport type { PluginTransferResource } from '@aglyn/aglyn/plugin-manager/plugin-transfer-resources'\nimport { createBookingsTransferResource } from './bookings-transfer'\n\n/**\n * The `bookings` transfer resource over the platform's Firestore. Loaded by\n * the console-server declarations with the first export, never at boot: this\n * module is what brings the Admin SDK, so the declarations import it lazily\n * and import no other library lazily — a lazy import of a library would make\n * every static import of it, across the plugin and the apps, a module\n * boundary error.\n */\nexport function adminBookingsTransferResource(): PluginTransferResource {\n return createBookingsTransferResource({\n firestore: () => firebaseAdmin.app().firestore(),\n })\n}\n"],"names":["firebaseAdmin","createBookingsTransferResource","adminBookingsTransferResource","firestore","app"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GAED,SAASA,aAAa,QAAQ,iDAAgD;AAE9E,SAASC,8BAA8B,QAAQ,yBAAqB;AAEpE;;;;;;;CAOC,GACD,OAAO,SAASC;IACd,OAAOD,+BAA+B;QACpCE,WAAW,IAAMH,cAAcI,GAAG,GAAGD,SAAS;IAChD;AACF"}