@proveanything/smartlinks 2.0.69 → 2.0.71
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/dist/api/asset.d.ts +5 -0
- package/dist/api/asset.js +11 -0
- package/dist/api/authKit.d.ts +28 -4
- package/dist/api/authKit.js +35 -1
- package/dist/api/bookings.d.ts +89 -0
- package/dist/api/bookings.js +179 -0
- package/dist/api/index.d.ts +1 -0
- package/dist/api/index.js +1 -0
- package/dist/docs/API_SUMMARY.md +503 -11
- package/dist/docs/app-objects.md +4 -0
- package/dist/docs/assets.md +63 -2
- package/dist/docs/auth-kit.md +46 -5
- package/dist/docs/bookings.md +324 -0
- package/dist/docs/members.md +182 -0
- package/dist/docs/overview.md +477 -475
- package/dist/docs/server-functions.md +4 -1
- package/dist/http.js +3 -0
- package/dist/openapi.yaml +5254 -4037
- package/dist/testing/index.js +1 -1
- package/dist/types/appManifest.d.ts +16 -4
- package/dist/types/asset.d.ts +25 -1
- package/dist/types/authKit.d.ts +58 -7
- package/dist/types/bookings.d.ts +301 -0
- package/dist/types/bookings.js +3 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.js +1 -0
- package/dist/utils/freeTimes.d.ts +57 -0
- package/dist/utils/freeTimes.js +206 -0
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.js +1 -0
- package/docs/API_SUMMARY.md +503 -11
- package/docs/app-objects.md +4 -0
- package/docs/assets.md +63 -2
- package/docs/auth-kit.md +46 -5
- package/docs/bookings.md +324 -0
- package/docs/members.md +182 -0
- package/docs/overview.md +477 -475
- package/docs/server-functions.md +4 -1
- package/openapi.yaml +5254 -4037
- package/package.json +1 -1
package/dist/api/asset.d.ts
CHANGED
|
@@ -101,6 +101,11 @@ export declare namespace asset {
|
|
|
101
101
|
* Restore a soft-deleted asset (clears `deletedAt`).
|
|
102
102
|
*/
|
|
103
103
|
function restoreAdmin(collectionId: string, assetId: string): Promise<Asset>;
|
|
104
|
+
/**
|
|
105
|
+
* Give an existing asset its own address (`assetUrl`). New and replaced assets get one automatically;
|
|
106
|
+
* this is for assets made before asset addresses existed. Safe to call again. → the asset, with `assetUrl`.
|
|
107
|
+
*/
|
|
108
|
+
function ensureAssetUrl(collectionId: string, assetId: string): Promise<Asset>;
|
|
104
109
|
/**
|
|
105
110
|
* Soft-delete multiple assets in one request.
|
|
106
111
|
*/
|
package/dist/api/asset.js
CHANGED
|
@@ -424,6 +424,15 @@ export var asset;
|
|
|
424
424
|
return post(path, {});
|
|
425
425
|
}
|
|
426
426
|
asset.restoreAdmin = restoreAdmin;
|
|
427
|
+
/**
|
|
428
|
+
* Give an existing asset its own address (`assetUrl`). New and replaced assets get one automatically;
|
|
429
|
+
* this is for assets made before asset addresses existed. Safe to call again. → the asset, with `assetUrl`.
|
|
430
|
+
*/
|
|
431
|
+
async function ensureAssetUrl(collectionId, assetId) {
|
|
432
|
+
const path = `/admin/collection/${encodeURIComponent(collectionId)}/asset/${encodeURIComponent(assetId)}/asset-url`;
|
|
433
|
+
return post(path, {});
|
|
434
|
+
}
|
|
435
|
+
asset.ensureAssetUrl = ensureAssetUrl;
|
|
427
436
|
/**
|
|
428
437
|
* Soft-delete multiple assets in one request.
|
|
429
438
|
*/
|
|
@@ -673,6 +682,8 @@ export var asset;
|
|
|
673
682
|
startBody.productId = scope.productId;
|
|
674
683
|
if (scope.type === 'proof')
|
|
675
684
|
startBody.proofId = scope.proofId;
|
|
685
|
+
if (options.replaceAssetId)
|
|
686
|
+
startBody.replaceAssetId = options.replaceAssetId;
|
|
676
687
|
const started = await post(base, startBody, token ? { 'X-Upload-Token': token } : undefined);
|
|
677
688
|
const finalizePath = `${base}/${encodeURIComponent(started.uploadId)}/complete`;
|
|
678
689
|
const finalizeBody = {};
|
package/dist/api/authKit.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AuthLoginResponse, AppleLoginOptions, RefreshResponse, LogoutResponse, PhoneSendCodeResponse, PhoneVerifyResponse, PasswordResetRequestResponse, VerifyResetTokenResponse, PasswordResetCompleteResponse, EmailVerificationActionResponse, EmailVerifyTokenResponse, AuthKitConfig, AuthKitConfigInput, AuthKitSetIdentityResponse, MagicLinkSendResponse, MagicLinkVerifyResponse, UserProfile, UpdateProfileResponse, ProfileUpdateData, SuccessResponse, SendWhatsAppRequest, SendWhatsAppResponse, ExchangeWhatsAppSessionResponse, VerifyWhatsAppResponse, WhatsAppStatusResponse, SendSmsVerifyRequest, SendSmsVerifyResponse, VerifySmsResponse, UpsertContactRequest, UpsertContactResponse, MfaChallengeSendResponse, MfaFinalizeResponse, MfaEnrollSendResponse, MfaEnrolledResponse, MfaFactorsResponse, TrustedDevice } from "../types/authKit.js";
|
|
1
|
+
import type { AuthLoginResponse, AppleLoginOptions, RefreshResponse, LogoutResponse, PhoneSendCodeResponse, PhoneVerifyResponse, PasswordResetRequestResponse, VerifyResetTokenResponse, PasswordResetCompleteResponse, EmailVerificationActionResponse, EmailVerifyTokenResponse, AuthKitConfig, AuthKitConfigInput, AuthKitSetIdentityResponse, AuthKitInviteRequest, AuthKitInviteResponse, MagicLinkSendResponse, MagicLinkVerifyResponse, UserProfile, UpdateProfileResponse, ProfileUpdateData, SuccessResponse, SendWhatsAppRequest, SendWhatsAppResponse, ExchangeWhatsAppSessionResponse, VerifyWhatsAppResponse, WhatsAppStatusResponse, SendSmsVerifyRequest, SendSmsVerifyResponse, VerifySmsResponse, UpsertContactRequest, UpsertContactResponse, MfaChallengeSendResponse, MfaFinalizeResponse, MfaEnrollSendResponse, MfaTotpEnrollResponse, MfaEnrolledResponse, MfaFactor, MfaFactorsResponse, TrustedDevice } from "../types/authKit.js";
|
|
2
2
|
/**
|
|
3
3
|
* Namespace containing helper functions for the new AuthKit API.
|
|
4
4
|
* Legacy collection-based authKit helpers retained (marked as *Legacy*).
|
|
@@ -208,8 +208,11 @@ export declare namespace authKit {
|
|
|
208
208
|
function verifyEmailChange(clientId: string, token: string): Promise<SuccessResponse>;
|
|
209
209
|
function updatePhone(clientId: string, phoneNumber: string, verificationCode: string): Promise<SuccessResponse>;
|
|
210
210
|
function deleteAccount(clientId: string, password: string, confirmText: string): Promise<SuccessResponse>;
|
|
211
|
-
/**
|
|
212
|
-
|
|
211
|
+
/**
|
|
212
|
+
* Send (or resend) an MFA challenge code to the given factor (public). For `totp` nothing is sent —
|
|
213
|
+
* it tells the server the code will come from their authenticator app; then {@link mfaChallengeVerify}.
|
|
214
|
+
*/
|
|
215
|
+
function mfaChallengeSend(clientId: string, mfaSessionToken: string, factor: MfaFactor): Promise<MfaChallengeSendResponse>;
|
|
213
216
|
/**
|
|
214
217
|
* Verify an MFA challenge code and finalize the login (public). On success this behaves
|
|
215
218
|
* like {@link login} — the bearer token is adopted and the cache invalidated.
|
|
@@ -233,6 +236,15 @@ export declare namespace authKit {
|
|
|
233
236
|
function enrollSmsMfa(clientId: string, phoneNumber: string): Promise<MfaEnrollSendResponse>;
|
|
234
237
|
/** Confirm SMS-factor enrollment with the code sent by {@link enrollSmsMfa} (authenticated). */
|
|
235
238
|
function confirmSmsMfa(clientId: string, mfaSessionToken: string, code: string): Promise<MfaEnrolledResponse>;
|
|
239
|
+
/**
|
|
240
|
+
* Begin authenticator-app enrollment (authenticated): a new secret for Google Authenticator,
|
|
241
|
+
* Microsoft Authenticator, 1Password and the like. Show `otpauthUri` as a QR code (and `secret` for
|
|
242
|
+
* typing in), then {@link confirmTotpMfa} with the code the app shows. Nothing is kept until then;
|
|
243
|
+
* setting up again replaces the previous app once confirmed.
|
|
244
|
+
*/
|
|
245
|
+
function enrollTotpMfa(clientId: string): Promise<MfaTotpEnrollResponse>;
|
|
246
|
+
/** Confirm authenticator-app enrollment with the 6-digit code the app shows (authenticated). */
|
|
247
|
+
function confirmTotpMfa(clientId: string, mfaSessionToken: string, code: string): Promise<MfaEnrolledResponse>;
|
|
236
248
|
/**
|
|
237
249
|
* Generate a fresh set of recovery codes, invalidating any previous set (authenticated).
|
|
238
250
|
* Returned **in plaintext, exactly once** — nothing else in the API ever returns them
|
|
@@ -242,7 +254,7 @@ export declare namespace authKit {
|
|
|
242
254
|
recoveryCodes: string[];
|
|
243
255
|
}>;
|
|
244
256
|
/** Remove an enrolled MFA factor (authenticated). Server route is DELETE with a body. */
|
|
245
|
-
function removeMfaFactor(clientId: string, factor:
|
|
257
|
+
function removeMfaFactor(clientId: string, factor: MfaFactor, password: string): Promise<SuccessResponse>;
|
|
246
258
|
/** List devices trusted to skip MFA challenges for the current user (authenticated). */
|
|
247
259
|
function listTrustedDevices(clientId: string): Promise<{
|
|
248
260
|
devices: TrustedDevice[];
|
|
@@ -281,5 +293,17 @@ export declare namespace authKit {
|
|
|
281
293
|
function setIdentity(collectionId: string, authKitId: string, body: {
|
|
282
294
|
mode: 'own';
|
|
283
295
|
}): Promise<AuthKitSetIdentityResponse>;
|
|
296
|
+
/**
|
|
297
|
+
* Invite someone to be a member of a site with its own logins (admin). Makes their account if they have
|
|
298
|
+
* none (the only way in when the site is invitation only — `signUp: 'invite'`), finds or creates their
|
|
299
|
+
* contact in this collection with the `customFields` you pass (their level), links the two, and emails
|
|
300
|
+
* them a sign-in link to the site (`redirectUrl`, default the kit's) that works once for 7 days. The page
|
|
301
|
+
* it opens handles it like any magic link: `mode=magicLink&token=…` → {@link verifyMagicLink}.
|
|
302
|
+
* Inviting someone again sends a fresh link.
|
|
303
|
+
*
|
|
304
|
+
* Errors: `OWN_LOGINS_REQUIRED` (409), `INVALID_EMAIL` (400), `INVALID_REDIRECT_URL` (400, not one of
|
|
305
|
+
* this site's addresses), `TOO_MANY_INVITES` (429, 5 an hour per address).
|
|
306
|
+
*/
|
|
307
|
+
function invite(collectionId: string, authKitId: string, body: AuthKitInviteRequest): Promise<AuthKitInviteResponse>;
|
|
284
308
|
function remove(collectionId: string, authKitId: string): Promise<void>;
|
|
285
309
|
}
|
package/dist/api/authKit.js
CHANGED
|
@@ -380,7 +380,10 @@ export var authKit;
|
|
|
380
380
|
* challenge/send can be called again on the same token (while unexpired/unburned) to
|
|
381
381
|
* switch factors or resend.
|
|
382
382
|
* =================================== */
|
|
383
|
-
/**
|
|
383
|
+
/**
|
|
384
|
+
* Send (or resend) an MFA challenge code to the given factor (public). For `totp` nothing is sent —
|
|
385
|
+
* it tells the server the code will come from their authenticator app; then {@link mfaChallengeVerify}.
|
|
386
|
+
*/
|
|
384
387
|
async function mfaChallengeSend(clientId, mfaSessionToken, factor) {
|
|
385
388
|
return post(`/authkit/${encodeURIComponent(clientId)}/mfa/challenge/send`, { mfaSessionToken, factor });
|
|
386
389
|
}
|
|
@@ -442,6 +445,21 @@ export var authKit;
|
|
|
442
445
|
return post(`/authkit/${encodeURIComponent(clientId)}/mfa/factors/sms/confirm`, { mfaSessionToken, code });
|
|
443
446
|
}
|
|
444
447
|
authKit.confirmSmsMfa = confirmSmsMfa;
|
|
448
|
+
/**
|
|
449
|
+
* Begin authenticator-app enrollment (authenticated): a new secret for Google Authenticator,
|
|
450
|
+
* Microsoft Authenticator, 1Password and the like. Show `otpauthUri` as a QR code (and `secret` for
|
|
451
|
+
* typing in), then {@link confirmTotpMfa} with the code the app shows. Nothing is kept until then;
|
|
452
|
+
* setting up again replaces the previous app once confirmed.
|
|
453
|
+
*/
|
|
454
|
+
async function enrollTotpMfa(clientId) {
|
|
455
|
+
return post(`/authkit/${encodeURIComponent(clientId)}/mfa/factors/totp/enroll`, {});
|
|
456
|
+
}
|
|
457
|
+
authKit.enrollTotpMfa = enrollTotpMfa;
|
|
458
|
+
/** Confirm authenticator-app enrollment with the 6-digit code the app shows (authenticated). */
|
|
459
|
+
async function confirmTotpMfa(clientId, mfaSessionToken, code) {
|
|
460
|
+
return post(`/authkit/${encodeURIComponent(clientId)}/mfa/factors/totp/confirm`, { mfaSessionToken, code });
|
|
461
|
+
}
|
|
462
|
+
authKit.confirmTotpMfa = confirmTotpMfa;
|
|
445
463
|
/**
|
|
446
464
|
* Generate a fresh set of recovery codes, invalidating any previous set (authenticated).
|
|
447
465
|
* Returned **in plaintext, exactly once** — nothing else in the API ever returns them
|
|
@@ -525,6 +543,22 @@ export var authKit;
|
|
|
525
543
|
return post(path, body);
|
|
526
544
|
}
|
|
527
545
|
authKit.setIdentity = setIdentity;
|
|
546
|
+
/**
|
|
547
|
+
* Invite someone to be a member of a site with its own logins (admin). Makes their account if they have
|
|
548
|
+
* none (the only way in when the site is invitation only — `signUp: 'invite'`), finds or creates their
|
|
549
|
+
* contact in this collection with the `customFields` you pass (their level), links the two, and emails
|
|
550
|
+
* them a sign-in link to the site (`redirectUrl`, default the kit's) that works once for 7 days. The page
|
|
551
|
+
* it opens handles it like any magic link: `mode=magicLink&token=…` → {@link verifyMagicLink}.
|
|
552
|
+
* Inviting someone again sends a fresh link.
|
|
553
|
+
*
|
|
554
|
+
* Errors: `OWN_LOGINS_REQUIRED` (409), `INVALID_EMAIL` (400), `INVALID_REDIRECT_URL` (400, not one of
|
|
555
|
+
* this site's addresses), `TOO_MANY_INVITES` (429, 5 an hour per address).
|
|
556
|
+
*/
|
|
557
|
+
async function invite(collectionId, authKitId, body) {
|
|
558
|
+
const path = `/admin/collection/${encodeURIComponent(collectionId)}/authKit/${encodeURIComponent(authKitId)}/invite`;
|
|
559
|
+
return post(path, body);
|
|
560
|
+
}
|
|
561
|
+
authKit.invite = invite;
|
|
528
562
|
async function remove(collectionId, authKitId) {
|
|
529
563
|
const path = `/admin/collection/${encodeURIComponent(collectionId)}/authKit/${encodeURIComponent(authKitId)}`;
|
|
530
564
|
return del(path);
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import type { Booking, BookingSlot, BookingAllocation, CreateBookingInput, UpdateBookingInput, MoveBookingInput, BookingListQueryParams, CreateSlotInput, UpdateSlotInput, SlotListQueryParams, CreateBlockInput, BlockListQueryParams, FreeBusyQuery, FreeBusyResponse, BookingAccessOptions } from '../types/bookings.js';
|
|
2
|
+
import type { PaginatedResponse } from '../types/appObjects.js';
|
|
3
|
+
export declare namespace bookings {
|
|
4
|
+
/**
|
|
5
|
+
* Book. All claims succeed together or nothing is written; a clash fails with 409
|
|
6
|
+
* (`SLOT_FULL`, `RESOURCE_TAKEN`, `PER_CONTACT_LIMIT`, …). Pass `idempotencyKey` so a retry never
|
|
7
|
+
* books twice.
|
|
8
|
+
*
|
|
9
|
+
* Public (admin = false): the app's `publicCreate.bookings` rules decide the status and limits; an
|
|
10
|
+
* anonymous guest may get `editToken` back (once) to manage the booking later.
|
|
11
|
+
*
|
|
12
|
+
* POST /bookings
|
|
13
|
+
*/
|
|
14
|
+
function create(collectionId: string, appId: string, input: CreateBookingInput, admin?: boolean): Promise<Booking>;
|
|
15
|
+
/** List bookings (admin). GET /bookings */
|
|
16
|
+
function list(collectionId: string, appId: string, params?: BookingListQueryParams, admin?: boolean): Promise<PaginatedResponse<Booking>>;
|
|
17
|
+
/** The signed-in caller's own bookings (public). GET /bookings/mine */
|
|
18
|
+
function mine(collectionId: string, appId: string, params?: BookingListQueryParams): Promise<PaginatedResponse<Booking>>;
|
|
19
|
+
/**
|
|
20
|
+
* Get one booking. Public: the signed-in booker, or a guest passing `{ editToken }`.
|
|
21
|
+
* GET /bookings/:bookingId
|
|
22
|
+
*/
|
|
23
|
+
function get(collectionId: string, appId: string, bookingId: string, admin?: boolean, opts?: BookingAccessOptions): Promise<Booking>;
|
|
24
|
+
/** Update zones and descriptive fields (admin). PATCH /bookings/:bookingId */
|
|
25
|
+
function update(collectionId: string, appId: string, bookingId: string, input: UpdateBookingInput, admin?: boolean): Promise<Booking>;
|
|
26
|
+
/**
|
|
27
|
+
* held / pending / waitlisted → confirmed (idempotent). A held booking whose hold has run out fails
|
|
28
|
+
* with HOLD_EXPIRED. Public: only the booker's own hold, when `ownerActions.bookings.confirm` allows.
|
|
29
|
+
* POST /bookings/:bookingId/confirm
|
|
30
|
+
*/
|
|
31
|
+
function confirm(collectionId: string, appId: string, bookingId: string, admin?: boolean, opts?: BookingAccessOptions): Promise<Booking>;
|
|
32
|
+
/**
|
|
33
|
+
* Cancel and give the places back (idempotent). Public: per `ownerActions.bookings.cancel` and its
|
|
34
|
+
* cutoff. `reason` is admin-only (public cancels record 'owner').
|
|
35
|
+
* POST /bookings/:bookingId/cancel
|
|
36
|
+
*/
|
|
37
|
+
function cancel(collectionId: string, appId: string, bookingId: string, admin?: boolean, opts?: BookingAccessOptions & {
|
|
38
|
+
reason?: string;
|
|
39
|
+
}): Promise<Booking>;
|
|
40
|
+
/**
|
|
41
|
+
* Move to a new slot / time, all-or-nothing (a failed move leaves the booking as it was).
|
|
42
|
+
* Public: per `ownerActions.bookings.move`; the create rules are re-checked for the new time.
|
|
43
|
+
* POST /bookings/:bookingId/move
|
|
44
|
+
*/
|
|
45
|
+
function move(collectionId: string, appId: string, bookingId: string, input: MoveBookingInput, admin?: boolean, opts?: BookingAccessOptions): Promise<Booking>;
|
|
46
|
+
/** Extend a hold by `holdMinutes` from now (admin; capped at 24h after the booking was made). */
|
|
47
|
+
function extendHold(collectionId: string, appId: string, bookingId: string, holdMinutes: number): Promise<Booking>;
|
|
48
|
+
/** confirmed → completed (admin). */
|
|
49
|
+
function complete(collectionId: string, appId: string, bookingId: string): Promise<Booking>;
|
|
50
|
+
/** confirmed → no_show (admin). */
|
|
51
|
+
function noShow(collectionId: string, appId: string, bookingId: string): Promise<Booking>;
|
|
52
|
+
/**
|
|
53
|
+
* Busy intervals per resource (bookings, blocks, slots' own blocks) — never booking details.
|
|
54
|
+
* Public only when the app sets `publicRead.bookings.freebusy: true`.
|
|
55
|
+
* GET /bookings/freebusy
|
|
56
|
+
*/
|
|
57
|
+
function freebusy(collectionId: string, appId: string, q: FreeBusyQuery, admin?: boolean): Promise<FreeBusyResponse>;
|
|
58
|
+
namespace slots {
|
|
59
|
+
/** Create a slot (admin). POST /bookings/slots */
|
|
60
|
+
function create(collectionId: string, appId: string, input: CreateSlotInput): Promise<BookingSlot>;
|
|
61
|
+
/** Create many slots at once — a series — all-or-nothing (admin, max 500). POST /bookings/slots/batch */
|
|
62
|
+
function createMany(collectionId: string, appId: string, slots: CreateSlotInput[], opts?: {
|
|
63
|
+
seriesId?: string;
|
|
64
|
+
}): Promise<{
|
|
65
|
+
data: BookingSlot[];
|
|
66
|
+
}>;
|
|
67
|
+
/** List slots. Public: open, public slots only, each with `remaining`. GET /bookings/slots */
|
|
68
|
+
function list(collectionId: string, appId: string, params?: SlotListQueryParams, admin?: boolean): Promise<PaginatedResponse<BookingSlot>>;
|
|
69
|
+
/** GET /bookings/slots/:slotId */
|
|
70
|
+
function get(collectionId: string, appId: string, slotId: string, admin?: boolean): Promise<BookingSlot>;
|
|
71
|
+
/**
|
|
72
|
+
* Update a slot (admin). Capacity can't drop below what's booked (SLOT_OVERBOOKED); times can't
|
|
73
|
+
* change once anything is booked (SLOT_HAS_BOOKINGS).
|
|
74
|
+
*/
|
|
75
|
+
function update(collectionId: string, appId: string, slotId: string, input: UpdateSlotInput): Promise<BookingSlot>;
|
|
76
|
+
/** Delete a slot (admin; refused while places are booked). */
|
|
77
|
+
function remove(collectionId: string, appId: string, slotId: string): Promise<{
|
|
78
|
+
success: boolean;
|
|
79
|
+
}>;
|
|
80
|
+
}
|
|
81
|
+
/** Blocked time on a resource with no booking — time off, a closure, maintenance (admin). */
|
|
82
|
+
namespace blocks {
|
|
83
|
+
function create(collectionId: string, appId: string, input: CreateBlockInput): Promise<BookingAllocation>;
|
|
84
|
+
function list(collectionId: string, appId: string, params?: BlockListQueryParams): Promise<PaginatedResponse<BookingAllocation>>;
|
|
85
|
+
function remove(collectionId: string, appId: string, blockId: string): Promise<{
|
|
86
|
+
success: boolean;
|
|
87
|
+
}>;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
// src/api/bookings.ts
|
|
2
|
+
// Generic booking objects — see docs/bookings.md.
|
|
3
|
+
//
|
|
4
|
+
// Every function takes `admin` last (default false), like app.cases / app.records:
|
|
5
|
+
// admin = true → /admin/... — unconditional (Studio users, your app's own server functions)
|
|
6
|
+
// admin = false → /public/... — governed by the app's config: publicCreate.bookings (who may book,
|
|
7
|
+
// as what status, limits, time rules), ownerActions.bookings (cancel / move /
|
|
8
|
+
// confirm afterwards) and publicRead.bookings.freebusy.
|
|
9
|
+
import { request, post, patch, del, requestWithOptions } from '../http.js';
|
|
10
|
+
function basePath(collectionId, appId, admin) {
|
|
11
|
+
const zone = admin ? 'admin' : 'public';
|
|
12
|
+
return `/${zone}/collection/${encodeURIComponent(collectionId)}/app/${encodeURIComponent(appId)}/bookings`;
|
|
13
|
+
}
|
|
14
|
+
function query(params) {
|
|
15
|
+
if (!params)
|
|
16
|
+
return '';
|
|
17
|
+
const parts = [];
|
|
18
|
+
for (const [key, value] of Object.entries(params)) {
|
|
19
|
+
if (value === undefined || value === null)
|
|
20
|
+
continue;
|
|
21
|
+
const v = value instanceof Date ? value.toISOString() : Array.isArray(value) ? value.join(',') : String(value);
|
|
22
|
+
parts.push(`${encodeURIComponent(key)}=${encodeURIComponent(v)}`);
|
|
23
|
+
}
|
|
24
|
+
return parts.length ? `?${parts.join('&')}` : '';
|
|
25
|
+
}
|
|
26
|
+
function tokenHeaders(opts) {
|
|
27
|
+
return (opts === null || opts === void 0 ? void 0 : opts.editToken) ? { 'X-Edit-Token': opts.editToken } : undefined;
|
|
28
|
+
}
|
|
29
|
+
function refString(r) {
|
|
30
|
+
return typeof r === 'string' ? r : `${r.type}:${r.id}`;
|
|
31
|
+
}
|
|
32
|
+
export var bookings;
|
|
33
|
+
(function (bookings) {
|
|
34
|
+
/**
|
|
35
|
+
* Book. All claims succeed together or nothing is written; a clash fails with 409
|
|
36
|
+
* (`SLOT_FULL`, `RESOURCE_TAKEN`, `PER_CONTACT_LIMIT`, …). Pass `idempotencyKey` so a retry never
|
|
37
|
+
* books twice.
|
|
38
|
+
*
|
|
39
|
+
* Public (admin = false): the app's `publicCreate.bookings` rules decide the status and limits; an
|
|
40
|
+
* anonymous guest may get `editToken` back (once) to manage the booking later.
|
|
41
|
+
*
|
|
42
|
+
* POST /bookings
|
|
43
|
+
*/
|
|
44
|
+
async function create(collectionId, appId, input, admin = false) {
|
|
45
|
+
return post(basePath(collectionId, appId, admin), input);
|
|
46
|
+
}
|
|
47
|
+
bookings.create = create;
|
|
48
|
+
/** List bookings (admin). GET /bookings */
|
|
49
|
+
async function list(collectionId, appId, params, admin = true) {
|
|
50
|
+
return request(`${basePath(collectionId, appId, admin)}${query(params)}`);
|
|
51
|
+
}
|
|
52
|
+
bookings.list = list;
|
|
53
|
+
/** The signed-in caller's own bookings (public). GET /bookings/mine */
|
|
54
|
+
async function mine(collectionId, appId, params) {
|
|
55
|
+
return request(`${basePath(collectionId, appId, false)}/mine${query(params)}`);
|
|
56
|
+
}
|
|
57
|
+
bookings.mine = mine;
|
|
58
|
+
/**
|
|
59
|
+
* Get one booking. Public: the signed-in booker, or a guest passing `{ editToken }`.
|
|
60
|
+
* GET /bookings/:bookingId
|
|
61
|
+
*/
|
|
62
|
+
async function get(collectionId, appId, bookingId, admin = false, opts) {
|
|
63
|
+
const path = `${basePath(collectionId, appId, admin)}/${encodeURIComponent(bookingId)}`;
|
|
64
|
+
const headers = tokenHeaders(opts);
|
|
65
|
+
return headers ? requestWithOptions(path, { method: 'GET', headers }) : request(path);
|
|
66
|
+
}
|
|
67
|
+
bookings.get = get;
|
|
68
|
+
/** Update zones and descriptive fields (admin). PATCH /bookings/:bookingId */
|
|
69
|
+
async function update(collectionId, appId, bookingId, input, admin = true) {
|
|
70
|
+
return patch(`${basePath(collectionId, appId, admin)}/${encodeURIComponent(bookingId)}`, input);
|
|
71
|
+
}
|
|
72
|
+
bookings.update = update;
|
|
73
|
+
/**
|
|
74
|
+
* held / pending / waitlisted → confirmed (idempotent). A held booking whose hold has run out fails
|
|
75
|
+
* with HOLD_EXPIRED. Public: only the booker's own hold, when `ownerActions.bookings.confirm` allows.
|
|
76
|
+
* POST /bookings/:bookingId/confirm
|
|
77
|
+
*/
|
|
78
|
+
async function confirm(collectionId, appId, bookingId, admin = false, opts) {
|
|
79
|
+
return post(`${basePath(collectionId, appId, admin)}/${encodeURIComponent(bookingId)}/confirm`, {}, tokenHeaders(opts));
|
|
80
|
+
}
|
|
81
|
+
bookings.confirm = confirm;
|
|
82
|
+
/**
|
|
83
|
+
* Cancel and give the places back (idempotent). Public: per `ownerActions.bookings.cancel` and its
|
|
84
|
+
* cutoff. `reason` is admin-only (public cancels record 'owner').
|
|
85
|
+
* POST /bookings/:bookingId/cancel
|
|
86
|
+
*/
|
|
87
|
+
async function cancel(collectionId, appId, bookingId, admin = false, opts) {
|
|
88
|
+
return post(`${basePath(collectionId, appId, admin)}/${encodeURIComponent(bookingId)}/cancel`, (opts === null || opts === void 0 ? void 0 : opts.reason) ? { reason: opts.reason } : {}, tokenHeaders(opts));
|
|
89
|
+
}
|
|
90
|
+
bookings.cancel = cancel;
|
|
91
|
+
/**
|
|
92
|
+
* Move to a new slot / time, all-or-nothing (a failed move leaves the booking as it was).
|
|
93
|
+
* Public: per `ownerActions.bookings.move`; the create rules are re-checked for the new time.
|
|
94
|
+
* POST /bookings/:bookingId/move
|
|
95
|
+
*/
|
|
96
|
+
async function move(collectionId, appId, bookingId, input, admin = false, opts) {
|
|
97
|
+
return post(`${basePath(collectionId, appId, admin)}/${encodeURIComponent(bookingId)}/move`, input, tokenHeaders(opts));
|
|
98
|
+
}
|
|
99
|
+
bookings.move = move;
|
|
100
|
+
/** Extend a hold by `holdMinutes` from now (admin; capped at 24h after the booking was made). */
|
|
101
|
+
async function extendHold(collectionId, appId, bookingId, holdMinutes) {
|
|
102
|
+
return post(`${basePath(collectionId, appId, true)}/${encodeURIComponent(bookingId)}/extend-hold`, { holdMinutes });
|
|
103
|
+
}
|
|
104
|
+
bookings.extendHold = extendHold;
|
|
105
|
+
/** confirmed → completed (admin). */
|
|
106
|
+
async function complete(collectionId, appId, bookingId) {
|
|
107
|
+
return post(`${basePath(collectionId, appId, true)}/${encodeURIComponent(bookingId)}/complete`, {});
|
|
108
|
+
}
|
|
109
|
+
bookings.complete = complete;
|
|
110
|
+
/** confirmed → no_show (admin). */
|
|
111
|
+
async function noShow(collectionId, appId, bookingId) {
|
|
112
|
+
return post(`${basePath(collectionId, appId, true)}/${encodeURIComponent(bookingId)}/no-show`, {});
|
|
113
|
+
}
|
|
114
|
+
bookings.noShow = noShow;
|
|
115
|
+
/**
|
|
116
|
+
* Busy intervals per resource (bookings, blocks, slots' own blocks) — never booking details.
|
|
117
|
+
* Public only when the app sets `publicRead.bookings.freebusy: true`.
|
|
118
|
+
* GET /bookings/freebusy
|
|
119
|
+
*/
|
|
120
|
+
async function freebusy(collectionId, appId, q, admin = false) {
|
|
121
|
+
const params = { resources: q.resources.map(refString).join(','), from: q.from, to: q.to };
|
|
122
|
+
return request(`${basePath(collectionId, appId, admin)}/freebusy${query(params)}`);
|
|
123
|
+
}
|
|
124
|
+
bookings.freebusy = freebusy;
|
|
125
|
+
// ==================== SLOTS ====================
|
|
126
|
+
let slots;
|
|
127
|
+
(function (slots_1) {
|
|
128
|
+
/** Create a slot (admin). POST /bookings/slots */
|
|
129
|
+
async function create(collectionId, appId, input) {
|
|
130
|
+
return post(`${basePath(collectionId, appId, true)}/slots`, input);
|
|
131
|
+
}
|
|
132
|
+
slots_1.create = create;
|
|
133
|
+
/** Create many slots at once — a series — all-or-nothing (admin, max 500). POST /bookings/slots/batch */
|
|
134
|
+
async function createMany(collectionId, appId, slots, opts) {
|
|
135
|
+
return post(`${basePath(collectionId, appId, true)}/slots/batch`, { slots, seriesId: opts === null || opts === void 0 ? void 0 : opts.seriesId });
|
|
136
|
+
}
|
|
137
|
+
slots_1.createMany = createMany;
|
|
138
|
+
/** List slots. Public: open, public slots only, each with `remaining`. GET /bookings/slots */
|
|
139
|
+
async function list(collectionId, appId, params, admin = false) {
|
|
140
|
+
return request(`${basePath(collectionId, appId, admin)}/slots${query(params)}`);
|
|
141
|
+
}
|
|
142
|
+
slots_1.list = list;
|
|
143
|
+
/** GET /bookings/slots/:slotId */
|
|
144
|
+
async function get(collectionId, appId, slotId, admin = false) {
|
|
145
|
+
return request(`${basePath(collectionId, appId, admin)}/slots/${encodeURIComponent(slotId)}`);
|
|
146
|
+
}
|
|
147
|
+
slots_1.get = get;
|
|
148
|
+
/**
|
|
149
|
+
* Update a slot (admin). Capacity can't drop below what's booked (SLOT_OVERBOOKED); times can't
|
|
150
|
+
* change once anything is booked (SLOT_HAS_BOOKINGS).
|
|
151
|
+
*/
|
|
152
|
+
async function update(collectionId, appId, slotId, input) {
|
|
153
|
+
return patch(`${basePath(collectionId, appId, true)}/slots/${encodeURIComponent(slotId)}`, input);
|
|
154
|
+
}
|
|
155
|
+
slots_1.update = update;
|
|
156
|
+
/** Delete a slot (admin; refused while places are booked). */
|
|
157
|
+
async function remove(collectionId, appId, slotId) {
|
|
158
|
+
return del(`${basePath(collectionId, appId, true)}/slots/${encodeURIComponent(slotId)}`);
|
|
159
|
+
}
|
|
160
|
+
slots_1.remove = remove;
|
|
161
|
+
})(slots = bookings.slots || (bookings.slots = {}));
|
|
162
|
+
// ==================== BLOCKS ====================
|
|
163
|
+
/** Blocked time on a resource with no booking — time off, a closure, maintenance (admin). */
|
|
164
|
+
let blocks;
|
|
165
|
+
(function (blocks) {
|
|
166
|
+
async function create(collectionId, appId, input) {
|
|
167
|
+
return post(`${basePath(collectionId, appId, true)}/blocks`, input);
|
|
168
|
+
}
|
|
169
|
+
blocks.create = create;
|
|
170
|
+
async function list(collectionId, appId, params) {
|
|
171
|
+
return request(`${basePath(collectionId, appId, true)}/blocks${query(params)}`);
|
|
172
|
+
}
|
|
173
|
+
blocks.list = list;
|
|
174
|
+
async function remove(collectionId, appId, blockId) {
|
|
175
|
+
return del(`${basePath(collectionId, appId, true)}/blocks/${encodeURIComponent(blockId)}`);
|
|
176
|
+
}
|
|
177
|
+
blocks.remove = remove;
|
|
178
|
+
})(blocks = bookings.blocks || (bookings.blocks = {}));
|
|
179
|
+
})(bookings || (bookings = {}));
|
package/dist/api/index.d.ts
CHANGED
|
@@ -34,6 +34,7 @@ export { adminCards } from "./adminCards.js";
|
|
|
34
34
|
export { tags } from "./tags.js";
|
|
35
35
|
export { order } from "./order.js";
|
|
36
36
|
export { app } from "./appObjects.js";
|
|
37
|
+
export { bookings } from "./bookings.js";
|
|
37
38
|
export { attestations } from "./attestations.js";
|
|
38
39
|
export { containers } from "./containers.js";
|
|
39
40
|
export { lots } from "./lots.js";
|
package/dist/api/index.js
CHANGED
|
@@ -37,6 +37,7 @@ export { adminCards } from "./adminCards.js";
|
|
|
37
37
|
export { tags } from "./tags.js";
|
|
38
38
|
export { order } from "./order.js";
|
|
39
39
|
export { app } from "./appObjects.js";
|
|
40
|
+
export { bookings } from "./bookings.js";
|
|
40
41
|
export { attestations } from "./attestations.js";
|
|
41
42
|
export { containers } from "./containers.js";
|
|
42
43
|
export { lots } from "./lots.js";
|