slotlock 0.7.0 → 0.9.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.
- package/CHANGELOG.md +281 -0
- package/agent-server.d.ts +25 -5
- package/agent-server.js +152 -7
- package/agent-store-backend.d.ts +6 -1
- package/agent-store-backend.js +861 -55
- package/application-api.d.ts +19 -1
- package/application-api.js +578 -21
- package/approvals.d.ts +2 -0
- package/approvals.js +12 -5
- package/assistant.d.ts +64 -9
- package/assistant.js +450 -82
- package/availability-store.d.ts +193 -0
- package/availability-store.js +558 -0
- package/booking-rules.d.ts +92 -5
- package/booking-rules.js +243 -15
- package/dashboard-assistant-ui.d.ts +21 -0
- package/dashboard-assistant-ui.js +539 -0
- package/dashboard-markdown.d.ts +2 -0
- package/dashboard-markdown.js +157 -0
- package/dashboard-settings-ui.d.ts +1 -0
- package/dashboard-settings-ui.js +78 -0
- package/dashboard.d.ts +84 -11
- package/dashboard.js +1654 -384
- package/ddl.d.ts +5 -1
- package/ddl.js +760 -9
- package/event-feed.d.ts +1 -1
- package/event-feed.js +18 -0
- package/holiday-import.d.ts +38 -0
- package/holiday-import.js +57 -0
- package/holidays.d.ts +38 -0
- package/holidays.js +150 -0
- package/hours.d.ts +125 -0
- package/hours.js +224 -0
- package/index.d.ts +14 -3
- package/index.js +10 -2
- package/interop.d.ts +25 -7
- package/interop.js +145 -17
- package/lifecycle.d.ts +31 -0
- package/lifecycle.js +115 -0
- package/maintenance.d.ts +19 -0
- package/maintenance.js +55 -1
- package/metrics.js +3 -0
- package/openapi.json +16237 -7795
- package/package.json +1 -1
- package/ranges.d.ts +28 -0
- package/ranges.js +135 -0
- package/resource-search.d.ts +19 -0
- package/resource-search.js +153 -0
- package/rest-api.js +7 -0
- package/rules.d.ts +2 -0
- package/rules.js +2 -0
- package/self-host.d.ts +1 -1
- package/self-host.js +221 -21
- package/slotlock.manifest.json +1 -1
- package/store.d.ts +367 -24
- package/store.js +1567 -97
- package/types.d.ts +198 -0
package/store.d.ts
CHANGED
|
@@ -3,10 +3,13 @@ import { type SlotlockUsageRow } from './usage.js';
|
|
|
3
3
|
import { type SlotlockChangeOrigin, type SlotlockEventFeed } from './event-feed.js';
|
|
4
4
|
import { type SlotlockBookingRules } from './booking-rules.js';
|
|
5
5
|
import type { Sql, TransactionSql } from 'postgres';
|
|
6
|
-
import { SLOTLOCK_CALENDAR_HORIZON_DAYS } from './rules.js';
|
|
7
|
-
import type { AcquireHoldResult, CalendarCoverageCommand, CalendarCoverageResult, CalendarEventContent, CalendarEventRetentionResult, BookingRetentionResult, SlotlockTenantErasure, SlotlockBookingRuleDefaults, CalendarFreeBusy, CalendarHorizonRollCursor, CalendarHorizonRollResult, CancelCalendarEventResult, CancelExternalReservationResult, ConfirmHoldResult, CreateReservationResult, DeleteResourceResult, ExternalReservationCommand, ExternalReservationResult, Interval, SlotlockCalendarEvent, SlotlockAgendaEntry, SlotlockHold, SlotlockBookingDescription, SlotlockApproval, SlotlockApprovalPolicy, SlotlockReservation, SlotlockResource, PutCalendarEventCommand, PutCalendarEventResult, ReleaseHoldResult, WeeklyAvailabilityRule } from './types.js';
|
|
6
|
+
import { SLOTLOCK_CALENDAR_HORIZON_DAYS, SLOTLOCK_SOURCE_BUSY_MAX } from './rules.js';
|
|
7
|
+
import type { AcquireHoldResult, MarkHoldPaidResult, PutContactResult, SlotlockContact, SlotlockContactConsent, CalendarCoverageCommand, CalendarCoverageResult, SourceBusyCommand, SourceBusyResult, CalendarEventContent, CalendarEventRetentionResult, BookingRetentionResult, SlotlockTenantErasure, SlotlockBookingRuleDefaults, CalendarFreeBusy, CalendarHorizonRollCursor, CalendarHorizonRollResult, CancelCalendarEventResult, CancelExternalReservationResult, ConfirmHoldResult, CreateReservationResult, DeleteResourceResult, ExternalReservationCommand, ExternalReservationResult, Interval, SlotlockCalendarEvent, SlotlockAgendaEntry, SlotlockHold, SlotlockBookingDescription, SlotlockApproval, SlotlockApprovalPolicy, SlotlockReservation, SlotlockResource, PutCalendarEventCommand, PutCalendarEventResult, ReleaseHoldResult, WeeklyAvailabilityRule } from './types.js';
|
|
8
|
+
import { type SlotlockAvailabilityDefaults, type SlotlockAvailabilityDefaultsResult, type SlotlockAvailabilityExceptionInput, type SlotlockOverrideResources, type SlotlockHolidayCalendar, type SlotlockHolidayImport } from './availability-store.js';
|
|
9
|
+
import type { SlotlockAvailabilityException, SlotlockRankedException } from './hours.js';
|
|
10
|
+
import type { SlotlockHoliday } from './holidays.js';
|
|
8
11
|
import { type PutApprovalPolicyParams } from './approvals.js';
|
|
9
|
-
export { SLOTLOCK_CALENDAR_HORIZON_DAYS };
|
|
12
|
+
export { SLOTLOCK_CALENDAR_HORIZON_DAYS, SLOTLOCK_SOURCE_BUSY_MAX };
|
|
10
13
|
/**
|
|
11
14
|
* Longest one-off event (ten years and some leap days); a recurring series is bounded by its
|
|
12
15
|
* materialization window instead.
|
|
@@ -69,6 +72,10 @@ export declare function readSlotlockSchemaVersion(sql: SlotlockSql): Promise<num
|
|
|
69
72
|
* migrate`) or `schema_newer`. Both carry `installed` and `expected`.
|
|
70
73
|
*/
|
|
71
74
|
export declare function assertSlotlockSchemaCurrent(sql: SlotlockSql): Promise<void>;
|
|
75
|
+
/** The most contacts a tenant keeps (RFC 0004 P3). */
|
|
76
|
+
export declare const SLOTLOCK_MAX_CONTACTS_PER_TENANT = 100000;
|
|
77
|
+
/** The longest a hold that waits for payment may live (RFC 0004 C3): 30 minutes. */
|
|
78
|
+
export declare const SLOTLOCK_PAYMENT_HOLD_MAX_TTL_MS: number;
|
|
72
79
|
/**
|
|
73
80
|
* A put's identity and the event it asks for, not its storage window: a series' window moves with
|
|
74
81
|
* the UTC day, so a retry after midnight must still match.
|
|
@@ -405,11 +412,132 @@ export interface SlotlockStore extends SlotlockEventFeed {
|
|
|
405
412
|
pool: string;
|
|
406
413
|
resourceId: string;
|
|
407
414
|
}): Promise<void>;
|
|
408
|
-
/**
|
|
415
|
+
/**
|
|
416
|
+
* Store (or clear, with `null`) the tenant's weekly hours (RFC 0004 B2): every resource without its
|
|
417
|
+
* own and with no location hours above it uses them, new ones too. Nothing is copied: a resource
|
|
418
|
+
* keeps hours of its own unless `overrideResources` clears them (`all`), or clears those that are
|
|
419
|
+
* the same as the tenant's were or as these (`matching`). Refuses `invalid_availability`.
|
|
420
|
+
*/
|
|
421
|
+
storeTenantAvailability(params: {
|
|
422
|
+
tenantRef: string;
|
|
423
|
+
rules: readonly WeeklyAvailabilityRule[] | null;
|
|
424
|
+
overrideResources?: SlotlockOverrideResources;
|
|
425
|
+
}): Promise<SlotlockAvailabilityDefaultsResult>;
|
|
426
|
+
/**
|
|
427
|
+
* Every resource the tenant has uses these weekly hours (or the server's, with `null`): as in 0.8.0,
|
|
428
|
+
* whatever hours of their own they had are gone. Now done by storing them as the tenant's, which
|
|
429
|
+
* resources added later inherit too. Returns how many resources in use they now apply to.
|
|
430
|
+
*
|
|
431
|
+
* @deprecated Use storeTenantAvailability, which can keep the hours resources have of their own
|
|
432
|
+
* and says how many do.
|
|
433
|
+
*/
|
|
409
434
|
setTenantAvailability(params: {
|
|
410
435
|
tenantRef: string;
|
|
411
436
|
rules: readonly WeeklyAvailabilityRule[] | null;
|
|
412
437
|
}): Promise<number>;
|
|
438
|
+
/**
|
|
439
|
+
* Store (or clear) a location's weekly hours: resources at it or inside it without their own use
|
|
440
|
+
* them, unless a nearer location has its own. Null for a location the tenant does not have.
|
|
441
|
+
*/
|
|
442
|
+
setLocationAvailability(params: {
|
|
443
|
+
tenantRef: string;
|
|
444
|
+
location: string;
|
|
445
|
+
rules: readonly WeeklyAvailabilityRule[] | null;
|
|
446
|
+
}): Promise<SlotlockAvailabilityDefaultsResult | null>;
|
|
447
|
+
/** The tenant's stored hours, and each location's that has them. */
|
|
448
|
+
getAvailabilityDefaults(params: {
|
|
449
|
+
tenantRef: string;
|
|
450
|
+
}): Promise<SlotlockAvailabilityDefaults>;
|
|
451
|
+
/**
|
|
452
|
+
* Add a closure or a day of special hours (RFC 0004 B1) for the tenant, a location or a resource;
|
|
453
|
+
* an import's `sourceUid` already stored at that scope is updated instead. Refuses
|
|
454
|
+
* `invalid_availability_exception`, `location_not_found`, `resource_not_found` and
|
|
455
|
+
* `availability_exceptions_limit_reached`.
|
|
456
|
+
*/
|
|
457
|
+
createAvailabilityException(params: SlotlockAvailabilityExceptionInput): Promise<SlotlockAvailabilityException>;
|
|
458
|
+
/**
|
|
459
|
+
* The tenant's exceptions by first day: those that apply to `resourceId`, or a `location`'s own,
|
|
460
|
+
* or all; only those reaching `from` to `to` when given.
|
|
461
|
+
*/
|
|
462
|
+
listAvailabilityExceptions(params: {
|
|
463
|
+
tenantRef: string;
|
|
464
|
+
resourceId?: string;
|
|
465
|
+
location?: string;
|
|
466
|
+
from?: string;
|
|
467
|
+
to?: string;
|
|
468
|
+
limit?: number;
|
|
469
|
+
after?: string;
|
|
470
|
+
}): Promise<SlotlockAvailabilityException[]>;
|
|
471
|
+
deleteAvailabilityException(params: {
|
|
472
|
+
tenantRef: string;
|
|
473
|
+
id: string;
|
|
474
|
+
}): Promise<boolean>;
|
|
475
|
+
/**
|
|
476
|
+
* Replace the exceptions an import of one resource's VAVAILABILITY made (source `vavailability`)
|
|
477
|
+
* with `ranges`; returns how many it keeps.
|
|
478
|
+
*/
|
|
479
|
+
replaceImportedExceptions(params: {
|
|
480
|
+
tenantRef: string;
|
|
481
|
+
resourceId: string;
|
|
482
|
+
ranges: readonly {
|
|
483
|
+
startsOn: string;
|
|
484
|
+
endsOn: string;
|
|
485
|
+
outcome: 'closed' | 'open';
|
|
486
|
+
hours?: {
|
|
487
|
+
startMinutes: number;
|
|
488
|
+
durationMinutes: number;
|
|
489
|
+
}[];
|
|
490
|
+
}[];
|
|
491
|
+
}): Promise<number>;
|
|
492
|
+
/**
|
|
493
|
+
* Import a holiday calendar's days off as closures at its scope, as the calendar named `name`
|
|
494
|
+
* there (RFC 0004 B1): holidays added or updated, and those it made before and no longer names
|
|
495
|
+
* in `span` deleted. With `url`, a subscription maintenance imports again. See
|
|
496
|
+
* availability-store.ts importHolidayCalendar for its refusals.
|
|
497
|
+
*/
|
|
498
|
+
importHolidayCalendar(params: {
|
|
499
|
+
tenantRef: string;
|
|
500
|
+
location?: string;
|
|
501
|
+
resourceId?: string;
|
|
502
|
+
name: string;
|
|
503
|
+
url?: string;
|
|
504
|
+
holidays: readonly SlotlockHoliday[];
|
|
505
|
+
span: {
|
|
506
|
+
from: string;
|
|
507
|
+
to: string;
|
|
508
|
+
};
|
|
509
|
+
}): Promise<SlotlockHolidayImport>;
|
|
510
|
+
/** The tenant's holiday calendars. */
|
|
511
|
+
listHolidayCalendars(params: {
|
|
512
|
+
tenantRef: string;
|
|
513
|
+
}): Promise<SlotlockHolidayCalendar[]>;
|
|
514
|
+
/** Delete a holiday calendar and its closures; null for one the tenant does not have. */
|
|
515
|
+
deleteHolidayCalendar(params: {
|
|
516
|
+
tenantRef: string;
|
|
517
|
+
id: string;
|
|
518
|
+
}): Promise<{
|
|
519
|
+
closures: number;
|
|
520
|
+
} | null>;
|
|
521
|
+
/** Subscriptions due to be imported again, the longest waiting first. */
|
|
522
|
+
dueHolidayCalendars(params: {
|
|
523
|
+
tenantRef: string;
|
|
524
|
+
limit: number;
|
|
525
|
+
}): Promise<SlotlockHolidayCalendar[]>;
|
|
526
|
+
/** Note why a subscription's import failed; it is tried again a day later. */
|
|
527
|
+
noteHolidayCalendarFailure(params: {
|
|
528
|
+
tenantRef: string;
|
|
529
|
+
id: string;
|
|
530
|
+
error: string;
|
|
531
|
+
}): Promise<void>;
|
|
532
|
+
/**
|
|
533
|
+
* Each resource's exceptions that reach `window`, in the order the evaluator applies them, by
|
|
534
|
+
* resource id.
|
|
535
|
+
*/
|
|
536
|
+
availabilityExceptionsFor(params: {
|
|
537
|
+
tenantRef: string;
|
|
538
|
+
resourceIds: readonly string[];
|
|
539
|
+
window: Interval;
|
|
540
|
+
}): Promise<Map<string, SlotlockRankedException[]>>;
|
|
413
541
|
/** Bounded tenant resource discovery, ordered and keyset-paginated by immutable UUID. */
|
|
414
542
|
listResources(params: {
|
|
415
543
|
tenantRef: string;
|
|
@@ -483,6 +611,12 @@ export interface SlotlockStore extends SlotlockEventFeed {
|
|
|
483
611
|
tenantRef: string;
|
|
484
612
|
externalRef: string;
|
|
485
613
|
revision: number;
|
|
614
|
+
/**
|
|
615
|
+
* An admin's reason for cancelling past the booking's cancel cutoff (RFC 0004 B5), 1-500
|
|
616
|
+
* characters, kept on its tombstone and the feed. Without it, a cancellation past the cutoff is
|
|
617
|
+
* refused.
|
|
618
|
+
*/
|
|
619
|
+
overrideReason?: string;
|
|
486
620
|
}): Promise<CancelExternalReservationResult>;
|
|
487
621
|
/**
|
|
488
622
|
* Occupy a window without committing: the hold blocks rivals under the same EXCLUDE arbiter until
|
|
@@ -526,7 +660,77 @@ export interface SlotlockStore extends SlotlockEventFeed {
|
|
|
526
660
|
* `fromHold` releases the rest, and releasing one with a holder releases them all.
|
|
527
661
|
*/
|
|
528
662
|
groupId?: string;
|
|
663
|
+
/**
|
|
664
|
+
* The hold waits for payment (RFC 0004 C3): it cannot be confirmed until `markHoldPaid`
|
|
665
|
+
* records the payment's reference, and lives at most SLOTLOCK_PAYMENT_HOLD_MAX_TTL_MS
|
|
666
|
+
* (`invalid_ttl` beyond). Slotlock records payment state; it never moves money.
|
|
667
|
+
*/
|
|
668
|
+
paymentRequired?: boolean;
|
|
669
|
+
/**
|
|
670
|
+
* What the payment must be (with `paymentRequired`): markHoldPaid refuses one for less, or in
|
|
671
|
+
* another currency (`payment_amount_mismatch`). Without it, any recorded payment counts.
|
|
672
|
+
*/
|
|
673
|
+
payment?: {
|
|
674
|
+
amountMinor: number;
|
|
675
|
+
currency: string;
|
|
676
|
+
};
|
|
529
677
|
}): Promise<AcquireHoldResult>;
|
|
678
|
+
/**
|
|
679
|
+
* Record that a hold waiting for payment is paid (RFC 0004 C3), by the payment's reference at the
|
|
680
|
+
* integrator's processor: the integrator says so, or an adapter that verified it. Once paid it
|
|
681
|
+
* may be confirmed. The same reference again answers the same hold, whatever became of it since
|
|
682
|
+
* (confirmed, booked, expired: the payment is kept apart); another is `payment_conflict`. The feed says so (`hold.paid`). A hold that does not wait for payment is
|
|
683
|
+
* `payment_not_required`; an expired one `hold_expired`; one confirmed, released or unknown
|
|
684
|
+
* `hold_not_found`.
|
|
685
|
+
*/
|
|
686
|
+
markHoldPaid(params: {
|
|
687
|
+
tenantRef: string;
|
|
688
|
+
holdId: string;
|
|
689
|
+
paymentRef: string;
|
|
690
|
+
/** What was received, as the processor says: needed when the hold names its payment. */
|
|
691
|
+
received?: {
|
|
692
|
+
amountMinor: number;
|
|
693
|
+
currency: string;
|
|
694
|
+
};
|
|
695
|
+
}): Promise<MarkHoldPaidResult>;
|
|
696
|
+
/**
|
|
697
|
+
* Keep a person a booking may name (`contactRef`) to be told about it (RFC 0004 P3): how to reach
|
|
698
|
+
* them and which channels they agreed to. Replaces what was kept under the reference. A sender
|
|
699
|
+
* reads it to send; Slotlock sends nothing. At most SLOTLOCK_MAX_CONTACTS_PER_TENANT.
|
|
700
|
+
*/
|
|
701
|
+
putContact(params: {
|
|
702
|
+
tenantRef: string;
|
|
703
|
+
ref: string;
|
|
704
|
+
name?: string | null;
|
|
705
|
+
email?: string | null;
|
|
706
|
+
phone?: string | null;
|
|
707
|
+
whatsapp?: string | null;
|
|
708
|
+
consent?: SlotlockContactConsent;
|
|
709
|
+
locale?: string | null;
|
|
710
|
+
}): Promise<PutContactResult>;
|
|
711
|
+
/** The tenant's contact with this reference, or null. */
|
|
712
|
+
getContact(params: {
|
|
713
|
+
tenantRef: string;
|
|
714
|
+
ref: string;
|
|
715
|
+
}): Promise<SlotlockContact | null>;
|
|
716
|
+
/** The tenant's contacts by reference, after `after`, up to `limit` (1-100, default 50). */
|
|
717
|
+
listContacts(params: {
|
|
718
|
+
tenantRef: string;
|
|
719
|
+
limit?: number;
|
|
720
|
+
after?: string;
|
|
721
|
+
}): Promise<SlotlockContact[]>;
|
|
722
|
+
/**
|
|
723
|
+
* Forget a person (RFC 0004 P3): their contact, and their reference on every booking that named
|
|
724
|
+
* it, in one transaction. `deleted` is false when there was no contact; `bookings` counts the
|
|
725
|
+
* bookings that no longer name them.
|
|
726
|
+
*/
|
|
727
|
+
deleteContact(params: {
|
|
728
|
+
tenantRef: string;
|
|
729
|
+
ref: string;
|
|
730
|
+
}): Promise<{
|
|
731
|
+
deleted: boolean;
|
|
732
|
+
bookings: number;
|
|
733
|
+
}>;
|
|
530
734
|
/** One of the tenant's live holds, or null (none, expired, confirmed, or another tenant's). */
|
|
531
735
|
getHold(params: {
|
|
532
736
|
tenantRef: string;
|
|
@@ -814,6 +1018,8 @@ export interface SlotlockStore extends SlotlockEventFeed {
|
|
|
814
1018
|
* another, checked under the event's lock.
|
|
815
1019
|
*/
|
|
816
1020
|
expectedResourceId?: string;
|
|
1021
|
+
/** Hold a one-off event to its resource's cancel cutoff (RFC 0004 B5), as agents' cancels are. */
|
|
1022
|
+
enforceBookingRules?: boolean;
|
|
817
1023
|
}): Promise<CancelCalendarEventResult>;
|
|
818
1024
|
/**
|
|
819
1025
|
* The tenant's cancellation of one of its events by id, whichever owner wrote it: an agent key's
|
|
@@ -829,6 +1035,11 @@ export interface SlotlockStore extends SlotlockEventFeed {
|
|
|
829
1035
|
expectedRevision: number;
|
|
830
1036
|
/** As for cancelCalendarEvent: `event_not_found` when the event is on another resource. */
|
|
831
1037
|
expectedResourceId?: string;
|
|
1038
|
+
/**
|
|
1039
|
+
* An admin's reason for cancelling a one-off event past its cancel cutoff (RFC 0004 B5), kept on
|
|
1040
|
+
* the feed; without it, that cancellation is refused.
|
|
1041
|
+
*/
|
|
1042
|
+
overrideReason?: string;
|
|
832
1043
|
}): Promise<CancelCalendarEventResult>;
|
|
833
1044
|
/**
|
|
834
1045
|
* Rematerialize due recurring masters into one rolling window without changing their revision. A
|
|
@@ -921,6 +1132,17 @@ export interface SlotlockStore extends SlotlockEventFeed {
|
|
|
921
1132
|
maxAgeMs?: number;
|
|
922
1133
|
limit?: number;
|
|
923
1134
|
}): Promise<number>;
|
|
1135
|
+
/**
|
|
1136
|
+
* Put each event reminder that has come due on the feed once (RFC 0004 P3), as `reminder.due`:
|
|
1137
|
+
* an occurrence's reminder, its minutes before the start, of an event that may be notified about
|
|
1138
|
+
* (`notify`), due within the last day and not started yet. Each is recorded in
|
|
1139
|
+
* `reminder_dispatches` in the same transaction, so no later pass says it again. The change's id
|
|
1140
|
+
* is the key a sender sends it once by. Up to `limit` (default 500); how many.
|
|
1141
|
+
*/
|
|
1142
|
+
dueReminders(params: {
|
|
1143
|
+
tenantRef: string;
|
|
1144
|
+
limit?: number;
|
|
1145
|
+
}): Promise<number>;
|
|
924
1146
|
/**
|
|
925
1147
|
* Claim a booking by its reference (check-in), so a resource whose booking rules ask for check-in
|
|
926
1148
|
* (`checkInMinutes`) does not release it. Check-in opens `SLOTLOCK_CHECK_IN_OPENS_MINUTES` before
|
|
@@ -932,6 +1154,15 @@ export interface SlotlockStore extends SlotlockEventFeed {
|
|
|
932
1154
|
tenantRef: string;
|
|
933
1155
|
externalRef: string;
|
|
934
1156
|
}): Promise<CheckInReservationResult>;
|
|
1157
|
+
/**
|
|
1158
|
+
* Say on the feed that bookings have ended (RFC 0004 B4): each confirmed booking whose end passed
|
|
1159
|
+
* within the last week and was not said yet gets one `reservation.completed`, its row unchanged
|
|
1160
|
+
* but for when it was said. Up to `limit` (default 500); returns how many.
|
|
1161
|
+
*/
|
|
1162
|
+
completeEndedBookings(params: {
|
|
1163
|
+
tenantRef: string;
|
|
1164
|
+
limit?: number;
|
|
1165
|
+
}): Promise<number>;
|
|
935
1166
|
/**
|
|
936
1167
|
* Release up to `limit` (default 100) bookings left unclaimed: on a resource whose booking rules
|
|
937
1168
|
* ask for check-in, made since they did, not checked in `checkInMinutes` after the start, and not
|
|
@@ -956,12 +1187,44 @@ export interface SlotlockStore extends SlotlockEventFeed {
|
|
|
956
1187
|
end: Date;
|
|
957
1188
|
holderRef: string;
|
|
958
1189
|
offerTtlMs?: number;
|
|
1190
|
+
/**
|
|
1191
|
+
* Wait for any slot of this many milliseconds within the window (RFC 0004 B6), a whole minute
|
|
1192
|
+
* from one minute to the window's length; left out, the whole window.
|
|
1193
|
+
*/
|
|
1194
|
+
durationMs?: number;
|
|
959
1195
|
/**
|
|
960
1196
|
* A retry identity, kept as long as the entry: the same key and request answer the entry the
|
|
961
1197
|
* first made (`replayed`), another request `idempotency_conflict`.
|
|
962
1198
|
*/
|
|
963
1199
|
idempotencyKey?: string;
|
|
964
1200
|
}): Promise<JoinWaitlistResult>;
|
|
1201
|
+
/**
|
|
1202
|
+
* One holder's live holds in a group, by resource id (RFC 0004 B7). With `alignExpiry`, every one
|
|
1203
|
+
* expires when the earliest does, so the set has one time to live.
|
|
1204
|
+
*/
|
|
1205
|
+
holdGroup(params: {
|
|
1206
|
+
tenantRef: string;
|
|
1207
|
+
holderRef: string;
|
|
1208
|
+
groupId: string;
|
|
1209
|
+
alignExpiry?: boolean;
|
|
1210
|
+
}): Promise<{
|
|
1211
|
+
holdId: string;
|
|
1212
|
+
resourceId: string;
|
|
1213
|
+
start: Date;
|
|
1214
|
+
end: Date;
|
|
1215
|
+
expiresAt: Date;
|
|
1216
|
+
source: string | null;
|
|
1217
|
+
}[]>;
|
|
1218
|
+
/**
|
|
1219
|
+
* Decline an entry's offer (RFC 0004 B6): its hold is let go and the entry is `declined`, so the
|
|
1220
|
+
* time is offered to the next. With `holderRef`, only that holder's. Null when there is no such
|
|
1221
|
+
* offer.
|
|
1222
|
+
*/
|
|
1223
|
+
declineWaitlistOffer(params: {
|
|
1224
|
+
tenantRef: string;
|
|
1225
|
+
id: string;
|
|
1226
|
+
holderRef?: string;
|
|
1227
|
+
}): Promise<SlotlockWaitlistEntry | null>;
|
|
965
1228
|
/** The tenant's waitlist entries, oldest first, optionally of one resource, pool or holder. */
|
|
966
1229
|
listWaitlist(params: {
|
|
967
1230
|
tenantRef: string;
|
|
@@ -1018,42 +1281,72 @@ export interface SlotlockStore extends SlotlockEventFeed {
|
|
|
1018
1281
|
from: string;
|
|
1019
1282
|
to: string;
|
|
1020
1283
|
}): Promise<boolean>;
|
|
1021
|
-
/**
|
|
1022
|
-
|
|
1284
|
+
/**
|
|
1285
|
+
* A member's conversations with the assistant, the most recent first (at most `limit`, default
|
|
1286
|
+
* 100): what the Chats list shows. Expired ones are left out.
|
|
1287
|
+
*/
|
|
1288
|
+
listAssistantChats(params: {
|
|
1023
1289
|
tenantRef: string;
|
|
1024
1290
|
memberRef: string;
|
|
1025
|
-
|
|
1291
|
+
limit?: number;
|
|
1292
|
+
}): Promise<SlotlockAssistantChatSummary[]>;
|
|
1293
|
+
/** One of a member's conversations, or null when there is none by that id (or it expired). */
|
|
1294
|
+
getAssistantChat(params: {
|
|
1295
|
+
tenantRef: string;
|
|
1296
|
+
memberRef: string;
|
|
1297
|
+
chatId: string;
|
|
1298
|
+
}): Promise<SlotlockAssistantChatRecord | null>;
|
|
1026
1299
|
/**
|
|
1027
|
-
* Store a member's
|
|
1300
|
+
* Store one of a member's conversations, creating it (titled `title`) or replacing its messages.
|
|
1028
1301
|
* Its actions become those stored already that `keep` names, in their stored state
|
|
1029
1302
|
* (settleAssistantAction changes it), and the `added` ones not stored already: an action is never
|
|
1030
|
-
* put back into a conversation that no longer has it.
|
|
1031
|
-
*
|
|
1303
|
+
* put back into a conversation that no longer has it. It is kept until deleted, or for `ttlMs`
|
|
1304
|
+
* (1 second to 3,650 days) from now when given, and then the tenant is listed for
|
|
1305
|
+
* sweepAssistantConversations. The member keeps at most SLOTLOCK_ASSISTANT_MAX_CHATS: past it,
|
|
1306
|
+
* the least recently used go (the member's writes take turns, so two at once keep the bound).
|
|
1307
|
+
* True when it was written; false when `create` is false and it was not there. Run it in a
|
|
1308
|
+
* transaction (withTenant does) so its lock lasts until the trim commits.
|
|
1032
1309
|
*/
|
|
1033
|
-
|
|
1310
|
+
putAssistantChat(params: {
|
|
1034
1311
|
tenantRef: string;
|
|
1035
1312
|
memberRef: string;
|
|
1313
|
+
chatId: string;
|
|
1314
|
+
title: string;
|
|
1036
1315
|
messages: unknown[];
|
|
1037
1316
|
added: Record<string, Record<string, unknown>>;
|
|
1038
1317
|
keep: readonly string[];
|
|
1039
|
-
ttlMs: number;
|
|
1040
|
-
|
|
1318
|
+
ttlMs: number | null;
|
|
1319
|
+
/**
|
|
1320
|
+
* False to only change a conversation that is still there: one the member deleted while a turn
|
|
1321
|
+
* on it ran is not written back. True (the default) creates it when it is not.
|
|
1322
|
+
*/
|
|
1323
|
+
create?: boolean;
|
|
1324
|
+
}): Promise<boolean>;
|
|
1325
|
+
/** Give one of a member's conversations a new title (1-120 characters). False when there is none. */
|
|
1326
|
+
renameAssistantChat(params: {
|
|
1327
|
+
tenantRef: string;
|
|
1328
|
+
memberRef: string;
|
|
1329
|
+
chatId: string;
|
|
1330
|
+
title: string;
|
|
1331
|
+
}): Promise<boolean>;
|
|
1041
1332
|
/**
|
|
1042
|
-
* Change one proposed action, only while its `status` is `from`: its fields are
|
|
1043
|
-
* `patch`. The action as changed, or null when it is not in that state (or not
|
|
1044
|
-
* racing approvals, one wins.
|
|
1333
|
+
* Change one proposed action of a conversation, only while its `status` is `from`: its fields are
|
|
1334
|
+
* merged with `patch`. The action as changed, or null when it is not in that state (or not
|
|
1335
|
+
* there): of two racing approvals, one wins.
|
|
1045
1336
|
*/
|
|
1046
1337
|
settleAssistantAction(params: {
|
|
1047
1338
|
tenantRef: string;
|
|
1048
1339
|
memberRef: string;
|
|
1340
|
+
chatId: string;
|
|
1049
1341
|
actionId: string;
|
|
1050
1342
|
from: string;
|
|
1051
1343
|
patch: Record<string, unknown>;
|
|
1052
1344
|
}): Promise<Record<string, unknown> | null>;
|
|
1053
|
-
/**
|
|
1054
|
-
|
|
1345
|
+
/** Delete one of a member's conversations. False when there was none. */
|
|
1346
|
+
deleteAssistantChat(params: {
|
|
1055
1347
|
tenantRef: string;
|
|
1056
1348
|
memberRef: string;
|
|
1349
|
+
chatId: string;
|
|
1057
1350
|
}): Promise<boolean>;
|
|
1058
1351
|
/** Delete up to `limit` (default 1,000) of the tenant's expired assistant conversations: how many. */
|
|
1059
1352
|
pruneAssistantConversations(params: {
|
|
@@ -1132,6 +1425,39 @@ export interface SlotlockStore extends SlotlockEventFeed {
|
|
|
1132
1425
|
}): Promise<SlotlockTenantErasure>;
|
|
1133
1426
|
/** Record the bounded, complete source window represented by a provider cursor/revision. */
|
|
1134
1427
|
recordCalendarCoverage(params: CalendarCoverageCommand): Promise<CalendarCoverageResult>;
|
|
1428
|
+
/**
|
|
1429
|
+
* A calendar that gives busy time but not its events (RFC 0004 C1): records its coverage of the
|
|
1430
|
+
* window at the revision, as recordCalendarCoverage does, and in the same transaction replaces
|
|
1431
|
+
* the busy time it reported for that window (what it said outside the window stays). Busy time
|
|
1432
|
+
* counts in free/busy and is refused to every booking Slotlock makes, as an event's would be;
|
|
1433
|
+
* a confirmed booking the source newly reports busy time over is put on the feed as
|
|
1434
|
+
* coverage.conflict, once, and left as it is. A revision already recorded changes nothing.
|
|
1435
|
+
*/
|
|
1436
|
+
replaceSourceBusy(params: SourceBusyCommand): Promise<SourceBusyResult>;
|
|
1437
|
+
/**
|
|
1438
|
+
* A source says a booking it was given (a sync's write-back) was changed or removed in its
|
|
1439
|
+
* calendar (RFC 0004 C4): put on the feed as `coverage.conflict`, named by the source's
|
|
1440
|
+
* `source_id`, with the booking and what the calendar now says. The booking is left as it is:
|
|
1441
|
+
* Slotlock stays the source of truth, and someone decides.
|
|
1442
|
+
*/
|
|
1443
|
+
reportCoverageConflict(params: {
|
|
1444
|
+
tenantRef: string;
|
|
1445
|
+
resourceId: string;
|
|
1446
|
+
source: string;
|
|
1447
|
+
booking: {
|
|
1448
|
+
reservationRef: string;
|
|
1449
|
+
} | {
|
|
1450
|
+
eventId: string;
|
|
1451
|
+
};
|
|
1452
|
+
reason: 'changed_in_calendar' | 'removed_from_calendar';
|
|
1453
|
+
/** Where the calendar now has it, when it was moved. */
|
|
1454
|
+
calendar?: Interval;
|
|
1455
|
+
}): Promise<{
|
|
1456
|
+
ok: true;
|
|
1457
|
+
} | {
|
|
1458
|
+
ok: false;
|
|
1459
|
+
code: 'invalid_identity' | 'invalid_window' | 'coverage_not_found' | 'reservation_not_found' | 'event_not_found';
|
|
1460
|
+
}>;
|
|
1135
1461
|
/** Return merged busy intervals plus explicit completeness for caller-required provider sources. */
|
|
1136
1462
|
getFreeBusy(params: {
|
|
1137
1463
|
tenantRef: string;
|
|
@@ -1178,12 +1504,21 @@ export interface SlotlockAssistantSettingsRecord {
|
|
|
1178
1504
|
updatedAt: Date;
|
|
1179
1505
|
}
|
|
1180
1506
|
/** One member's live conversation with the dashboard assistant, as assistant.ts keeps it. */
|
|
1181
|
-
|
|
1507
|
+
/** One of a member's conversations with the assistant, as the Chats list shows it. */
|
|
1508
|
+
export interface SlotlockAssistantChatSummary {
|
|
1509
|
+
/** 16 URL-safe characters. */
|
|
1510
|
+
id: string;
|
|
1511
|
+
title: string;
|
|
1512
|
+
updatedAt: Date;
|
|
1513
|
+
}
|
|
1514
|
+
/** One of a member's conversations with the assistant, whole. */
|
|
1515
|
+
export interface SlotlockAssistantChatRecord extends SlotlockAssistantChatSummary {
|
|
1182
1516
|
messages: unknown[];
|
|
1183
1517
|
/** The writes it proposed, by id. */
|
|
1184
1518
|
actions: Record<string, Record<string, unknown>>;
|
|
1185
|
-
|
|
1186
|
-
|
|
1519
|
+
createdAt: Date;
|
|
1520
|
+
/** When it is deleted unless used again; null when it is kept until the member deletes it. */
|
|
1521
|
+
expiresAt: Date | null;
|
|
1187
1522
|
}
|
|
1188
1523
|
/** One entry of a tenant's waitlist (joinWaitlist). */
|
|
1189
1524
|
export interface SlotlockWaitlistEntry {
|
|
@@ -1195,12 +1530,20 @@ export interface SlotlockWaitlistEntry {
|
|
|
1195
1530
|
end: Date;
|
|
1196
1531
|
holderRef: string;
|
|
1197
1532
|
offerTtlMs: number;
|
|
1198
|
-
/**
|
|
1199
|
-
|
|
1533
|
+
/**
|
|
1534
|
+
* `waiting`; `offered` (a hold was made: `holdId` on `offeredResourceId`); then `accepted` (the
|
|
1535
|
+
* hold was confirmed), `declined` (let go) or `lapsed` (it expired); or `expired` (no slot could
|
|
1536
|
+
* be offered before the window closed).
|
|
1537
|
+
*/
|
|
1538
|
+
status: 'waiting' | 'offered' | 'accepted' | 'declined' | 'lapsed' | 'expired';
|
|
1200
1539
|
holdId: string | null;
|
|
1201
1540
|
offeredResourceId: string | null;
|
|
1202
1541
|
offeredAt: Date | null;
|
|
1203
1542
|
createdAt: Date;
|
|
1543
|
+
/** The length it waits for, any slot of it within the window (RFC 0004 B6); null: the whole window. */
|
|
1544
|
+
durationMs: number | null;
|
|
1545
|
+
/** When its offer was accepted, declined or lapsed. */
|
|
1546
|
+
decidedAt: Date | null;
|
|
1204
1547
|
}
|
|
1205
1548
|
export type JoinWaitlistResult = {
|
|
1206
1549
|
ok: true;
|
|
@@ -1323,4 +1666,4 @@ export declare function createSlotlockStore(sql: StoreSql, options?: SlotlockSto
|
|
|
1323
1666
|
* Every store method that writes for a tenant: what a suspended tenant's withTenant store refuses.
|
|
1324
1667
|
* Maintenance (rolling series, pruning, purging) and erasure are not among them.
|
|
1325
1668
|
*/
|
|
1326
|
-
export declare const SLOTLOCK_TENANT_WRITE_METHODS: readonly ["createResource", "updateResourceProfile", "putLocation", "updateLocation", "deleteLocation", "putGroup", "deleteGroup", "addGroupMember", "removeGroupMember", "archiveResource", "restoreResource", "deleteResource", "setResourceAvailability", "setResourceBookingRules", "setBookingRuleDefaults", "setResourcePool", "setResourceParent", "setPoolOrder", "notePoolBooking", "putApprovalPolicy", "deleteApprovalPolicy", "requestApproval", "beginApprovalGrant", "finishApprovalGrant", "declineApproval", "resetTestTenant", "fastForwardTestTenant", "setTenantAvailability", "createReservation", "createExternalReservation", "rescheduleExternalReservation", "cancelExternalReservation", "acquireHold", "confirmHold", "releaseHold", "putCalendarEvent", "cancelCalendarEvent", "cancelCalendarEventById", "recordCalendarCoverage", "createWebhookEndpoint", "deleteWebhookEndpoint", "enableWebhookEndpoint", "recordCoverageFailure", "deleteCoverage", "checkInReservation", "joinWaitlist", "leaveWaitlist", "putAssistantSettings", "deleteAssistantSettings", "resealAssistantKey", "
|
|
1669
|
+
export declare const SLOTLOCK_TENANT_WRITE_METHODS: readonly ["createResource", "updateResourceProfile", "putLocation", "updateLocation", "deleteLocation", "putGroup", "deleteGroup", "addGroupMember", "removeGroupMember", "archiveResource", "restoreResource", "deleteResource", "setResourceAvailability", "setResourceBookingRules", "setBookingRuleDefaults", "setResourcePool", "setResourceParent", "setPoolOrder", "notePoolBooking", "putApprovalPolicy", "deleteApprovalPolicy", "requestApproval", "beginApprovalGrant", "finishApprovalGrant", "declineApproval", "resetTestTenant", "fastForwardTestTenant", "storeTenantAvailability", "setTenantAvailability", "setLocationAvailability", "createAvailabilityException", "deleteAvailabilityException", "replaceImportedExceptions", "importHolidayCalendar", "deleteHolidayCalendar", "noteHolidayCalendarFailure", "createReservation", "createExternalReservation", "rescheduleExternalReservation", "cancelExternalReservation", "acquireHold", "markHoldPaid", "putContact", "deleteContact", "confirmHold", "releaseHold", "putCalendarEvent", "cancelCalendarEvent", "cancelCalendarEventById", "recordCalendarCoverage", "replaceSourceBusy", "reportCoverageConflict", "createWebhookEndpoint", "deleteWebhookEndpoint", "enableWebhookEndpoint", "recordCoverageFailure", "deleteCoverage", "checkInReservation", "joinWaitlist", "leaveWaitlist", "declineWaitlistOffer", "putAssistantSettings", "deleteAssistantSettings", "resealAssistantKey", "putAssistantChat", "renameAssistantChat", "settleAssistantAction", "deleteAssistantChat"];
|