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/types.d.ts
CHANGED
|
@@ -5,6 +5,13 @@ export interface Interval {
|
|
|
5
5
|
start: Date;
|
|
6
6
|
end: Date;
|
|
7
7
|
}
|
|
8
|
+
/** Hours a resource without its own inherits, as the database resolves them (RFC 0004 B2). */
|
|
9
|
+
export interface SlotlockInheritedAvailability {
|
|
10
|
+
source: 'location' | 'tenant';
|
|
11
|
+
/** The location whose hours apply, when `source` is `location`. */
|
|
12
|
+
location?: string;
|
|
13
|
+
rules: WeeklyAvailabilityRule[];
|
|
14
|
+
}
|
|
8
15
|
/** A schedulable resource (vehicle, room, worker, machine, or any other reservable asset). */
|
|
9
16
|
export interface SlotlockResource {
|
|
10
17
|
id: string;
|
|
@@ -22,6 +29,11 @@ export interface SlotlockResource {
|
|
|
22
29
|
* uses the default (`SLOTLOCK_AVAILABILITY`, or the backend's `availabilityRules`).
|
|
23
30
|
*/
|
|
24
31
|
availabilityRules?: WeeklyAvailabilityRule[];
|
|
32
|
+
/**
|
|
33
|
+
* The hours it inherits when it has none of its own (RFC 0004 B2): its location's, the nearest
|
|
34
|
+
* up the chain, else its tenant's. Absent when it has its own, or inherits the server's.
|
|
35
|
+
*/
|
|
36
|
+
inheritedAvailability?: SlotlockInheritedAvailability;
|
|
25
37
|
/**
|
|
26
38
|
* `shared` resources are listed to and booked by agents; `private` ones are invisible to agents.
|
|
27
39
|
* Fixed at creation; absent means shared.
|
|
@@ -89,6 +101,11 @@ export interface SlotlockApprovalPolicy {
|
|
|
89
101
|
/** How long a person has to decide, before the booking's start less `leadMinutes`. */
|
|
90
102
|
approvalTtlMinutes: number;
|
|
91
103
|
leadMinutes: number;
|
|
104
|
+
/**
|
|
105
|
+
* It also holds the tenant's own bookings through the application API (bundles and pool
|
|
106
|
+
* bookings); without it, it holds only agents' (RFC 0004 B7).
|
|
107
|
+
*/
|
|
108
|
+
includeApplication: boolean;
|
|
92
109
|
createdAt: Date;
|
|
93
110
|
updatedAt: Date;
|
|
94
111
|
}
|
|
@@ -148,6 +165,12 @@ export interface SlotlockReservation {
|
|
|
148
165
|
/** Monotonic command revision; legacy, hold, and shadow rows start at 1. */
|
|
149
166
|
revision: number;
|
|
150
167
|
source: string | null;
|
|
168
|
+
/** Whom to tell about it (RFC 0004 P3), when it names someone. */
|
|
169
|
+
contactRef?: string;
|
|
170
|
+
/** Present, and false, when no one should be notified about it. */
|
|
171
|
+
notify?: false;
|
|
172
|
+
/** Minutes before its start it is reminded, latest first, when it is. */
|
|
173
|
+
reminderMinutes?: number[];
|
|
151
174
|
}
|
|
152
175
|
export interface ExternalReservationCommand {
|
|
153
176
|
tenantRef: string;
|
|
@@ -158,6 +181,34 @@ export interface ExternalReservationCommand {
|
|
|
158
181
|
bufferAfterMs: number;
|
|
159
182
|
revision: number;
|
|
160
183
|
source?: string;
|
|
184
|
+
/**
|
|
185
|
+
* An admin's reason for moving the booking past its reschedule cutoff (RFC 0004 B5), kept on the
|
|
186
|
+
* feed. Without it, a move past the cutoff is refused.
|
|
187
|
+
*/
|
|
188
|
+
overrideReason?: string;
|
|
189
|
+
/**
|
|
190
|
+
* The wall time the booking starts at in its resource's zone, `YYYY-MM-DDTHH:MM[:SS]` (RFC 0004
|
|
191
|
+
* B9): it must name `start` now, and if zone rules later move it, maintenance says so or follows
|
|
192
|
+
* it (`followZoneRules`). Left out, the booking keeps its instant only.
|
|
193
|
+
*/
|
|
194
|
+
localStart?: string;
|
|
195
|
+
/**
|
|
196
|
+
* Whom to tell about it (RFC 0004 P3): a contact's reference (`putContact`), never the person.
|
|
197
|
+
* Put on the feed with each of its changes; a sender looks the person up by it.
|
|
198
|
+
*/
|
|
199
|
+
contactRef?: string;
|
|
200
|
+
/** False: no sender should notify anyone about it (default true). On the feed only when false. */
|
|
201
|
+
notify?: boolean;
|
|
202
|
+
/**
|
|
203
|
+
* Minutes before its start to remind whom it names (RFC 0004 P3): up to five, each 0 to a year,
|
|
204
|
+
* said on the feed once each as `reminder.due` by maintenance, and again if the booking moves.
|
|
205
|
+
*/
|
|
206
|
+
reminderMinutes?: number[];
|
|
207
|
+
}
|
|
208
|
+
/** What a cancellation records for the integrator to charge (RFC 0004 B5). Slotlock moves no money. */
|
|
209
|
+
export interface SlotlockRecordedFee {
|
|
210
|
+
amountMinor: number;
|
|
211
|
+
currency: string;
|
|
161
212
|
}
|
|
162
213
|
export type ExternalReservationResult = {
|
|
163
214
|
ok: true;
|
|
@@ -166,6 +217,14 @@ export type ExternalReservationResult = {
|
|
|
166
217
|
} | {
|
|
167
218
|
ok: false;
|
|
168
219
|
code: 'invalid_window';
|
|
220
|
+
}
|
|
221
|
+
/** `localStart` is not a wall time, or does not name `start` in the resource's zone. */
|
|
222
|
+
| {
|
|
223
|
+
ok: false;
|
|
224
|
+
code: 'invalid_local_start';
|
|
225
|
+
} | {
|
|
226
|
+
ok: false;
|
|
227
|
+
code: 'invalid_contact_ref' | 'invalid_notify' | 'invalid_reminders';
|
|
169
228
|
} | {
|
|
170
229
|
ok: false;
|
|
171
230
|
code: 'invalid_buffer';
|
|
@@ -227,6 +286,13 @@ export type CancelExternalReservationResult = {
|
|
|
227
286
|
ok: true;
|
|
228
287
|
cancelled: boolean;
|
|
229
288
|
revision: number;
|
|
289
|
+
cancellationFee?: SlotlockRecordedFee;
|
|
290
|
+
}
|
|
291
|
+
/** The booking's cancel cutoff has passed (RFC 0004 B5): an admin may override with a reason. */
|
|
292
|
+
| {
|
|
293
|
+
ok: false;
|
|
294
|
+
code: 'booking_rule_violated';
|
|
295
|
+
rule: 'cancel_cutoff';
|
|
230
296
|
} | {
|
|
231
297
|
ok: false;
|
|
232
298
|
code: 'invalid_identity';
|
|
@@ -317,6 +383,21 @@ export interface SlotlockHold {
|
|
|
317
383
|
source: string | null;
|
|
318
384
|
/** The alternatives it was held with (`groupId` when acquired); absent when held alone. */
|
|
319
385
|
groupId?: string;
|
|
386
|
+
/** Present when it waits for payment (RFC 0004 C3): it is confirmed only once paid. */
|
|
387
|
+
paymentRequired?: true;
|
|
388
|
+
/** The payment's reference at the integrator's processor, once paid. */
|
|
389
|
+
paymentRef?: string | null;
|
|
390
|
+
paidAt?: Date | null;
|
|
391
|
+
/** What the payment must be, when the hold names it. */
|
|
392
|
+
paymentAmount?: {
|
|
393
|
+
amountMinor: number;
|
|
394
|
+
currency: string;
|
|
395
|
+
} | null;
|
|
396
|
+
/** What was received, once paid and when the payer said. */
|
|
397
|
+
paidAmount?: {
|
|
398
|
+
amountMinor: number;
|
|
399
|
+
currency: string;
|
|
400
|
+
} | null;
|
|
320
401
|
}
|
|
321
402
|
/** One entry of a tenant's agenda (`listAgenda`): what occupies a resource, and from when. */
|
|
322
403
|
export interface SlotlockAgendaEntry {
|
|
@@ -345,6 +426,11 @@ export type AcquireHoldResult =
|
|
|
345
426
|
} | {
|
|
346
427
|
ok: false;
|
|
347
428
|
code: 'invalid_ttl';
|
|
429
|
+
}
|
|
430
|
+
/** `payment` without `paymentRequired`, or not an amount and an ISO 4217 currency. */
|
|
431
|
+
| {
|
|
432
|
+
ok: false;
|
|
433
|
+
code: 'invalid_payment';
|
|
348
434
|
} | {
|
|
349
435
|
ok: false;
|
|
350
436
|
code: 'invalid_buffer';
|
|
@@ -412,6 +498,11 @@ export type ConfirmHoldResult = {
|
|
|
412
498
|
ok: false;
|
|
413
499
|
code: 'hold_expired';
|
|
414
500
|
}
|
|
501
|
+
/** The hold waits for payment (RFC 0004 C3) and none is recorded yet (markHoldPaid). */
|
|
502
|
+
| {
|
|
503
|
+
ok: false;
|
|
504
|
+
code: 'payment_required';
|
|
505
|
+
}
|
|
415
506
|
/** A cancellation of the hold's reference (its id) arrived first and retired it. */
|
|
416
507
|
| {
|
|
417
508
|
ok: false;
|
|
@@ -437,6 +528,71 @@ export type ReleaseHoldResult = {
|
|
|
437
528
|
ok: true;
|
|
438
529
|
released: boolean;
|
|
439
530
|
};
|
|
531
|
+
/**
|
|
532
|
+
* A person a booking may name to be told about it (RFC 0004 P3), by the tenant's own reference: how
|
|
533
|
+
* to reach them, and which channels they agreed to. A sender reads it; Slotlock sends nothing.
|
|
534
|
+
*/
|
|
535
|
+
export interface SlotlockContact {
|
|
536
|
+
ref: string;
|
|
537
|
+
name: string | null;
|
|
538
|
+
email: string | null;
|
|
539
|
+
/** E.164, for SMS. */
|
|
540
|
+
phone: string | null;
|
|
541
|
+
/** E.164, for WhatsApp. */
|
|
542
|
+
whatsapp: string | null;
|
|
543
|
+
/** Each channel the person said yes or no to; a channel left out has no answer recorded. */
|
|
544
|
+
consent: SlotlockContactConsent;
|
|
545
|
+
/** When each answer in `consent` was given (kept while it stands): the proof of it. */
|
|
546
|
+
consentAt: Partial<Record<keyof SlotlockContactConsent, Date>>;
|
|
547
|
+
/** BCP 47, for the language of what is sent. */
|
|
548
|
+
locale: string | null;
|
|
549
|
+
createdAt: Date;
|
|
550
|
+
updatedAt: Date;
|
|
551
|
+
}
|
|
552
|
+
export interface SlotlockContactConsent {
|
|
553
|
+
email?: boolean;
|
|
554
|
+
sms?: boolean;
|
|
555
|
+
whatsapp?: boolean;
|
|
556
|
+
}
|
|
557
|
+
export type PutContactResult = {
|
|
558
|
+
ok: true;
|
|
559
|
+
contact: SlotlockContact;
|
|
560
|
+
created: boolean;
|
|
561
|
+
} | {
|
|
562
|
+
ok: false;
|
|
563
|
+
code: 'invalid_contact_ref' | 'invalid_contact';
|
|
564
|
+
} | {
|
|
565
|
+
ok: false;
|
|
566
|
+
code: 'contact_limit_reached';
|
|
567
|
+
limit: number;
|
|
568
|
+
};
|
|
569
|
+
/** Recording a hold's payment (RFC 0004 C3); `idempotent` when it was recorded already. */
|
|
570
|
+
export type MarkHoldPaidResult = {
|
|
571
|
+
ok: true;
|
|
572
|
+
hold: SlotlockHold;
|
|
573
|
+
idempotent: boolean;
|
|
574
|
+
} | {
|
|
575
|
+
ok: false;
|
|
576
|
+
code: 'invalid_identity' | 'invalid_payment_ref' | 'invalid_payment';
|
|
577
|
+
}
|
|
578
|
+
/** Less than the hold's payment, in another currency, or not said when the hold names one. */
|
|
579
|
+
| {
|
|
580
|
+
ok: false;
|
|
581
|
+
code: 'payment_amount_mismatch';
|
|
582
|
+
} | {
|
|
583
|
+
ok: false;
|
|
584
|
+
code: 'hold_not_found' | 'hold_expired';
|
|
585
|
+
}
|
|
586
|
+
/** The hold does not wait for payment. */
|
|
587
|
+
| {
|
|
588
|
+
ok: false;
|
|
589
|
+
code: 'payment_not_required';
|
|
590
|
+
}
|
|
591
|
+
/** It was already paid by another payment. */
|
|
592
|
+
| {
|
|
593
|
+
ok: false;
|
|
594
|
+
code: 'payment_conflict';
|
|
595
|
+
};
|
|
440
596
|
/** RFC 5545 TRANSP projection. Transparent events remain visible but never occupy a resource. */
|
|
441
597
|
export type CalendarTransparency = 'opaque' | 'transparent';
|
|
442
598
|
export type CalendarEventStatus = 'confirmed' | 'tentative';
|
|
@@ -543,6 +699,11 @@ export interface PutCalendarEventCommand extends CalendarEventContent {
|
|
|
543
699
|
holdId: string;
|
|
544
700
|
holderRef: string;
|
|
545
701
|
};
|
|
702
|
+
/**
|
|
703
|
+
* False: no sender should notify anyone about it (RFC 0004 P3), and its reminders are not put on
|
|
704
|
+
* the feed. Default true; as sent with each revision.
|
|
705
|
+
*/
|
|
706
|
+
notify?: boolean;
|
|
546
707
|
}
|
|
547
708
|
export type PutCalendarEventResult = {
|
|
548
709
|
ok: true;
|
|
@@ -604,6 +765,11 @@ export type PutCalendarEventResult = {
|
|
|
604
765
|
ok: false;
|
|
605
766
|
code: 'hold_expired';
|
|
606
767
|
}
|
|
768
|
+
/** `fromHold`'s hold waits for payment (RFC 0004 C3) and none is recorded yet. */
|
|
769
|
+
| {
|
|
770
|
+
ok: false;
|
|
771
|
+
code: 'payment_required';
|
|
772
|
+
}
|
|
607
773
|
/** `fromHold`'s hold is on another resource, or does not cover the event. */
|
|
608
774
|
| {
|
|
609
775
|
ok: false;
|
|
@@ -644,6 +810,8 @@ export type CancelCalendarEventResult = {
|
|
|
644
810
|
externalRef: string;
|
|
645
811
|
revision: number;
|
|
646
812
|
idempotent: boolean;
|
|
813
|
+
/** What a late cancellation costs, recorded for the integrator to charge (RFC 0004 B5). */
|
|
814
|
+
cancellationFee?: SlotlockRecordedFee;
|
|
647
815
|
} | {
|
|
648
816
|
ok: false;
|
|
649
817
|
code: 'invalid_identity';
|
|
@@ -664,6 +832,12 @@ export type CancelCalendarEventResult = {
|
|
|
664
832
|
ok: false;
|
|
665
833
|
code: 'revision_conflict';
|
|
666
834
|
currentRevision: number;
|
|
835
|
+
}
|
|
836
|
+
/** The event's cancel cutoff has passed (RFC 0004 B5). */
|
|
837
|
+
| {
|
|
838
|
+
ok: false;
|
|
839
|
+
code: 'booking_rule_violated';
|
|
840
|
+
rule: 'cancel_cutoff';
|
|
667
841
|
};
|
|
668
842
|
/** A place in the roll's order of due masters: the last one a batch examined. */
|
|
669
843
|
export interface CalendarHorizonRollCursor {
|
|
@@ -763,6 +937,30 @@ export type CalendarCoverageResult = {
|
|
|
763
937
|
code: 'coverage_limit_reached';
|
|
764
938
|
limit: number;
|
|
765
939
|
};
|
|
940
|
+
/**
|
|
941
|
+
* What a calendar that gives busy time but not its events says (Google freeBusy, Microsoft
|
|
942
|
+
* getSchedule; RFC 0004 C1): its coverage of the window, and the busy time in it, which replaces
|
|
943
|
+
* what the source said of that window before.
|
|
944
|
+
*/
|
|
945
|
+
export interface SourceBusyCommand extends CalendarCoverageCommand {
|
|
946
|
+
/** At most SLOTLOCK_SOURCE_BUSY_MAX intervals; clipped to the window and merged. */
|
|
947
|
+
busy: Interval[];
|
|
948
|
+
}
|
|
949
|
+
export type SourceBusyResult = {
|
|
950
|
+
ok: true;
|
|
951
|
+
revision: number;
|
|
952
|
+
/** A revision already recorded: nothing changed. */
|
|
953
|
+
idempotent: boolean;
|
|
954
|
+
/** How many intervals are kept, merged and clipped. */
|
|
955
|
+
busy: number;
|
|
956
|
+
/** Bookings the source newly reports in the way of, each put on the feed as coverage.conflict. */
|
|
957
|
+
conflicts: number;
|
|
958
|
+
} | Exclude<CalendarCoverageResult, {
|
|
959
|
+
ok: true;
|
|
960
|
+
}> | {
|
|
961
|
+
ok: false;
|
|
962
|
+
code: 'invalid_busy';
|
|
963
|
+
};
|
|
766
964
|
export interface CalendarCoverageAssessment {
|
|
767
965
|
state: 'complete' | 'partial' | 'unknown';
|
|
768
966
|
/** Required sources that are absent, stale, or do not fully cover the requested window. */
|