@acms-subir/client 0.1.23 → 0.1.25

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/README.md CHANGED
@@ -63,6 +63,7 @@ language. Update the site before shipping an app build with a newer client.
63
63
  | `live()` | Live video: the current broadcast (`snapshot` or `null`), `serverNow` and the owner's `display` choices. Never cached; 404 while `site.features.live` is false |
64
64
  | `announcements({ kind?, pinned?, page?, limit? })`, `announcement(id)`, `paginate.announcements()` | Announcements up right now in the client's language, newest first (`pinned: true`: the banners, urgent first); 404 while `site.features.announcements` is false |
65
65
  | `form(id)`, `submitForm(id, { answers, version?, idempotencyKey? })` | A published form's questions; send answers (checkbox groups as arrays). Each call makes one key; retries reuse it |
66
+ | `requestOptions()`, `submitRequest(input, { idempotencyKey? })` | Event requests without an account: what the form offers (`open`, `types`, `rooms`, `replyTime`, `notice`, `phone`, `timezone`; never cached), and asking for a new event or a change (`{ id }`). 404 while `site.features.requests` is false. See Event requests below |
66
67
  | `manageBooking(token)`, `cancelBooking(token)` | The booker's own booking from its `manageToken`, and cancelling it (or leaving a waitlist, or releasing a held spot); `can` says what is allowed. A waitlisted RSVP has `booking.position` (its place in line), an offered one `booking.holdUntil` |
67
68
  | `confirmBooking(token)` | Take a spot the waitlist offered (`can.confirm`): `confirmed`, or `pending` when RSVPs need approval. 410 once `holdUntil` passed. Core 0.3.40 or later |
68
69
  | `rescheduleAvailability(token, { from?, days?, minutes? })`, `rescheduleBooking(token, { start, minutes? })` | Open times for moving it (its own time counts as free), then the move |
@@ -149,7 +150,7 @@ await pending.catch(() => {});
149
150
  ```
150
151
 
151
152
  Requests that are safe to repeat (GET, PUT, DELETE, device registration, and
152
- POSTs with an Idempotency-Key: bookings and form responses) retry network
153
+ POSTs with an Idempotency-Key: bookings, form responses and event requests) retry network
153
154
  failures, 5xx and 429 responses at most twice (three attempts total), with
154
155
  250/500ms backoff and at least the server's `Retry-After` delay (seconds or HTTP
155
156
  date). A wait that would outlast `timeoutMs` throws the 429 straight away, with
@@ -170,6 +171,52 @@ booking must be retried with its existing key. `AcmsError` exposes `status`,
170
171
  `aborted`, or `invalid_response`; non-JSON HTTP errors use `http_error`.
171
172
  Convenience lookups apply the timeout separately to each underlying request.
172
173
 
174
+ ## Event requests
175
+
176
+ A site can take event requests from people
177
+ without an account (`acms({ requests: true })`, so `site.features.requests`
178
+ is true; staff answer them in Calendar → Requests). Someone asks for
179
+ something new, or for a change to an event, and gives a name, an email and
180
+ optionally a phone. Nothing goes on the calendar until staff approve it.
181
+
182
+ ```ts
183
+ import type { RequestInput } from '@acms-subir/client';
184
+
185
+ const options = await client.requestOptions();
186
+ // { open, types: [{ id, label }], rooms: [{ slug, name, color }], replyTime: '3 days', notice, phone, timezone }
187
+ if (!options.open) {
188
+ // say "We aren't taking requests here right now." and show options.phone; keep the screen itself reachable
189
+ }
190
+ const ask: RequestInput = {
191
+ kind: 'new', type: options.types[0]?.id, title: 'Guitar workshop',
192
+ // the site's wall clock (options.timezone), in the future; the end may be just HH:mm on the same day
193
+ start: '2026-11-07T18:00', end: '20:00',
194
+ repeat: 'weekly', // 'once' (default), 'weekly', or 'other' with repeatText
195
+ rooms: ['fellowship-hall'], // slugs from options.rooms, or roomsUnsure: true
196
+ people: 12, message: 'We bring our own chairs.',
197
+ name: 'Example Guest', email: 'guest@example.com', phone: '555 0100',
198
+ };
199
+ const { id } = await client.submitRequest(ask, { idempotencyKey: crypto.randomUUID() });
200
+
201
+ // a change to a public event: one date of it (YYYY-MM-DD, the site's day), or leave date out for every date
202
+ await client.submitRequest({ kind: 'change', event: 'fall-fair', date: '2026-11-08', message: 'Could it start at 10?', name: 'Example Guest', email: 'guest@example.com' });
203
+ ```
204
+
205
+ - Check whether a room looks free first with `roomFree({ room, start, end })`
206
+ (needs bookings on the site; the times there take a zone, so convert the
207
+ wall-clock times with `options.timezone`).
208
+ - Keep one Idempotency-Key per request and reuse it for retries: a retry
209
+ answers the same `{ id }`, and the same key with other details is a 409
210
+ `changed`. Each call without `idempotencyKey` makes a new one.
211
+ - The client's `locale` (or `input.locale`) goes in the body, so the emails
212
+ about the request speak the app's language.
213
+ - A refusal is an `AcmsError` whose `code` says why: `closed` (409, requests
214
+ closed meanwhile), a field (400: `title`, `type`, `start`, `end`, `past`,
215
+ `far`, `repeat`, `room`, `people`, `event`, `date`, `what` (the change's
216
+ message), `name`, `email`, `phone`), `changed` (409), or `busy` / `full`
217
+ (429, with `retryAfter`). 10 requests a minute per address, plus the
218
+ site's daily cap.
219
+
173
220
  ## Push notifications
174
221
 
175
222
  Available when the site enables push (`acms({ mobile: { push: true } })`);
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { Site, Theme, Page, Content, Post, ContentList, SearchResults, Links, Form, FormReceipt, FormResponseInput, ManagedBooking, RescheduleInput, ManageAvailabilityQuery, GuestCodeSent, GuestToken, GuestBookings, GuestBookingsQuery, GuestSignedOut, Events, Event, Calendars, Resources, Resource, Availability, BookingInput, BookingResult, RsvpStatus, Device, DeviceInput, DeviceUpdate, DeviceRegistration, DeviceRemoved, StaffLink, PushTopics, LiveStatus, Announcements, AnnouncementDetail, EventDetail, RoomFree } from './types.js';
1
+ import type { Site, Theme, Page, Content, Post, ContentList, SearchResults, Links, Form, FormReceipt, FormResponseInput, ManagedBooking, RescheduleInput, ManageAvailabilityQuery, GuestCodeSent, GuestToken, GuestBookings, GuestBookingsQuery, GuestSignedOut, Events, Event, Calendars, Resources, Resource, Availability, BookingInput, BookingResult, RsvpStatus, Device, DeviceInput, DeviceUpdate, DeviceRegistration, DeviceRemoved, StaffLink, PushTopics, LiveStatus, Announcements, AnnouncementDetail, EventDetail, RoomFree, EventRequestOptions, RequestReceipt } from './types.js';
2
2
  export { AcmsError, isAcmsError } from './errors.js';
3
3
  export type * from './types.js';
4
4
  export * from './editor.js';
@@ -72,6 +72,44 @@ export interface RoomFreeOptions extends RequestOptions {
72
72
  export type BookOptions = BookingInput & RequestOptions & {
73
73
  idempotencyKey?: string;
74
74
  };
75
+ /** Who's asking. `locale`: the language for the emails about it (default: the client's). */
76
+ interface RequestAsker {
77
+ name: string;
78
+ email: string;
79
+ phone?: string;
80
+ locale?: string;
81
+ }
82
+ /** Ask for a new event. Times are the site's wall clock (`requestOptions().timezone`). */
83
+ export interface NewEventRequest extends RequestAsker {
84
+ kind: 'new';
85
+ /** One of `requestOptions().types` (an `id`); required when the site lists any. */
86
+ type?: string;
87
+ title: string;
88
+ /** `YYYY-MM-DDTHH:mm`, in the future. */
89
+ start: string;
90
+ /** `YYYY-MM-DDTHH:mm`, or `HH:mm`: the start's day, or the next when it's before the start (20:00 → 01:00); within a day. */
91
+ end: string;
92
+ /** Default `once`; `other` needs `repeatText` ("every other Tuesday"). */
93
+ repeat?: 'once' | 'weekly' | 'other';
94
+ repeatText?: string;
95
+ /** Room slugs from `requestOptions().rooms`, or `roomsUnsure: true`. */
96
+ rooms?: string[];
97
+ roomsUnsure?: boolean;
98
+ people?: number | null;
99
+ /** Anything else they want staff to know. */
100
+ message?: string;
101
+ }
102
+ /** Ask for a change to a public event. */
103
+ export interface ChangeRequest extends RequestAsker {
104
+ kind: 'change';
105
+ /** The event's slug. */
106
+ event: string;
107
+ /** One of its dates (`YYYY-MM-DD`, the site's day); leave it out for every date. */
108
+ date?: string;
109
+ /** What should change. */
110
+ message: string;
111
+ }
112
+ export type RequestInput = NewEventRequest | ChangeRequest;
75
113
  export interface ApiResponse<T> {
76
114
  version: 1;
77
115
  data: T;
@@ -214,6 +252,14 @@ export declare const endpoints: {
214
252
  readonly method: "GET";
215
253
  readonly path: "/announcements/{id}";
216
254
  };
255
+ readonly requestOptions: {
256
+ readonly method: "GET";
257
+ readonly path: "/requests/options";
258
+ };
259
+ readonly submitRequest: {
260
+ readonly method: "POST";
261
+ readonly path: "/requests";
262
+ };
217
263
  readonly manageBooking: {
218
264
  readonly method: "GET";
219
265
  readonly path: "/bookings/manage";
@@ -325,12 +371,30 @@ export interface AcmsClient {
325
371
  announcements(o?: AnnouncementOptions): Promise<Announcements>;
326
372
  /** One announcement that is up; 404 once it came down. */
327
373
  announcement(id: string, o?: RequestOptions): Promise<AnnouncementDetail>;
328
- /** A published form's questions. 410 when it stopped accepting responses. Requires `site.features.forms`. */
374
+ /**
375
+ * A published form's questions, in the client's `locale` where the form has
376
+ * its words (older sites: the main language). 410 when it stopped accepting
377
+ * responses. Requires `site.features.forms`. A `time` answer is HH:mm (24-hour).
378
+ */
329
379
  form(id: string, o?: RequestOptions): Promise<Form>;
330
- /** Send answers (checkbox groups as arrays). Retries reuse the same Idempotency-Key, so they never duplicate. */
380
+ /** Send answers (checkbox groups as arrays; a choice as it was shown). Retries reuse the same Idempotency-Key, so they never duplicate. The receipt's `confirmation` is in the client's `locale`. */
331
381
  submitForm(id: string, input: FormResponseInput & {
332
382
  idempotencyKey?: string;
333
383
  }, o?: RequestOptions): Promise<FormReceipt>;
384
+ /**
385
+ * What the event request form offers (`site.features.requests`): `open` (false: say so, show `phone`, and keep
386
+ * the screen reachable), `types` and `rooms` to choose from, the site's `replyTime` and `notice` in the client's language,
387
+ * and its `timezone` (the times in a request are its wall clock). Never cached; 404 while the site has requests off.
388
+ */
389
+ requestOptions(o?: RequestOptions): Promise<EventRequestOptions>;
390
+ /**
391
+ * Ask for a new event or a change to one, without an account: `{ id }`. Retries reuse the same Idempotency-Key, so they
392
+ * never send twice; the same key with other details is a 409 `changed`. Refusals carry a `code` (`closed`, `title`,
393
+ * `start`, `email`, `busy`, …). Sends the client's `locale` (or `o.locale`), so the emails about it speak it.
394
+ */
395
+ submitRequest(input: RequestInput, o?: RequestOptions & {
396
+ idempotencyKey?: string;
397
+ }): Promise<RequestReceipt>;
334
398
  /** The booker's own booking, from its private token (`manageToken`). Never cached. Requires `site.features.bookingChanges`. */
335
399
  manageBooking(token: string, o?: RequestOptions): Promise<ManagedBooking>;
336
400
  /** Cancel it; for an RSVP on a waitlist, leave the line or release a held spot. */
package/dist/index.js CHANGED
@@ -25,6 +25,8 @@ export const endpoints = {
25
25
  live: { method: 'GET', path: '/live' },
26
26
  // announcements (404 unless the site turns them on)
27
27
  announcements: { method: 'GET', path: '/announcements' }, announcement: { method: 'GET', path: '/announcements/{id}' },
28
+ // event requests without an account (404 unless the site turns them on): what the form offers (never cached), and sending one
29
+ requestOptions: { method: 'GET', path: '/requests/options' }, submitRequest: { method: 'POST', path: '/requests' },
28
30
  // the booker's own booking: its private token goes in the Booking-Token header
29
31
  manageBooking: { method: 'GET', path: '/bookings/manage' }, cancelBooking: { method: 'POST', path: '/bookings/manage/cancel' },
30
32
  // take a spot an RSVP's waitlist offered
@@ -35,10 +37,13 @@ export const endpoints = {
35
37
  requestGuestCode: { method: 'POST', path: '/guest/code' }, guestSignIn: { method: 'POST', path: '/guest/token' },
36
38
  guestBookings: { method: 'GET', path: '/guest/bookings' }, guestSignOut: { method: 'POST', path: '/guest/revoke' },
37
39
  };
38
- // site: its legal links; pushTopics: topic names
39
- const localized = new Set(['home', 'page', 'content', 'contentById', 'search', 'events', 'rsvpStatus', 'site', 'pushTopics', 'announcements', 'announcement', 'eventDetail']);
40
- // localized since core 0.3.32; older sites answer ?locale= with a 400, so ask them again without it
41
- const lateLocalized = new Set(['site', 'pushTopics']);
40
+ // site: its legal links; pushTopics: topic names; form: its questions;
41
+ // submitForm: the receipt's thank-you (any site ignores it on that POST);
42
+ // requestOptions: the kinds and the site's words
43
+ const localized = new Set(['home', 'page', 'content', 'contentById', 'search', 'events', 'rsvpStatus', 'site', 'pushTopics', 'announcements', 'announcement', 'eventDetail', 'form', 'submitForm', 'requestOptions']);
44
+ // localized later (site, pushTopics: core 0.3.32; form: with form
45
+ // translations); older sites answer ?locale= with a 400, so ask them again without it
46
+ const lateLocalized = new Set(['site', 'pushTopics', 'form']);
42
47
  function uuid() {
43
48
  if (globalThis.crypto?.randomUUID)
44
49
  return globalThis.crypto.randomUUID();
@@ -120,8 +125,8 @@ export function createClient(options) {
120
125
  opts.signal?.addEventListener('abort', abort, { once: true });
121
126
  const timer = setTimeout(() => controller.abort(new AcmsError(0, 'timeout', 'Request timed out.', undefined, undefined, key)), timeoutMs);
122
127
  const signal = controller.signal;
123
- // availability, live status and RSVP seats are never served from the cache
124
- const cacheable = endpoint.method === 'GET' && name !== 'availability' && name !== 'live' && name !== 'rsvpStatus' && name !== 'roomFree' && !extra.headers && cache;
128
+ // availability, live status, RSVP seats, free rooms and whether requests are open are never served from the cache
129
+ const cacheable = endpoint.method === 'GET' && name !== 'availability' && name !== 'live' && name !== 'rsvpStatus' && name !== 'roomFree' && name !== 'requestOptions' && !extra.headers && cache;
125
130
  // only replay what the server treats as repeatable: a lost reply to a code
126
131
  // exchange or a move must not run it twice
127
132
  const replayable = endpoint.method !== 'POST' || !!key || name === 'registerDevice';
@@ -329,6 +334,13 @@ export function createClient(options) {
329
334
  const { idempotencyKey, ...body } = input;
330
335
  return request('submitForm', o, {}, id, body, idempotencyKey ?? uuid());
331
336
  },
337
+ requestOptions: (o = {}) => request('requestOptions', o),
338
+ submitRequest: (input, o = {}) => {
339
+ const { idempotencyKey, signal } = o;
340
+ // the language rides in the body: the emails about it speak it
341
+ const locale = input.locale ?? o.locale ?? options.locale;
342
+ return request('submitRequest', { signal }, {}, undefined, locale === undefined ? input : { ...input, locale }, idempotencyKey ?? uuid());
343
+ },
332
344
  manageBooking: (token, o = {}) => request('manageBooking', o, {}, undefined, undefined, undefined, bookingAuth(token)),
333
345
  cancelBooking: (token, o = {}) => request('cancelBooking', o, {}, undefined, undefined, undefined, bookingAuth(token)),
334
346
  confirmBooking: (token, o = {}) => request('confirmBooking', o, {}, undefined, undefined, undefined, bookingAuth(token)),
package/dist/types.d.ts CHANGED
@@ -37,6 +37,7 @@ export type Site = {
37
37
  "links": boolean;
38
38
  "live": boolean;
39
39
  "announcements": boolean;
40
+ "requests": boolean;
40
41
  };
41
42
  "legal": {
42
43
  "privacy": string | null;
@@ -248,7 +249,7 @@ export type Event = {
248
249
  "confirmation": string;
249
250
  "fields": Array<{
250
251
  "id": string;
251
- "type": "text" | "textarea" | "email" | "phone" | "number" | "select" | "checkbox" | "date" | "radio" | "checkboxes" | "url" | "consent" | "heading";
252
+ "type": "text" | "textarea" | "email" | "phone" | "number" | "select" | "checkbox" | "date" | "radio" | "checkboxes" | "url" | "consent" | "heading" | "time";
252
253
  "label": string;
253
254
  "required": boolean;
254
255
  "help": string;
@@ -256,7 +257,23 @@ export type Event = {
256
257
  "placeholder"?: string;
257
258
  "width"?: "full" | "half";
258
259
  "allowOther"?: boolean;
260
+ "translations"?: {
261
+ [key: string]: {
262
+ "label"?: string;
263
+ "help"?: string;
264
+ "placeholder"?: string;
265
+ "options"?: Array<string>;
266
+ };
267
+ };
259
268
  }>;
269
+ "translations"?: {
270
+ [key: string]: {
271
+ "title"?: string;
272
+ "intro"?: string;
273
+ "submitLabel"?: string;
274
+ "confirmation"?: string;
275
+ };
276
+ };
260
277
  };
261
278
  };
262
279
  "url": string;
@@ -370,7 +387,7 @@ export type Events = {
370
387
  "confirmation": string;
371
388
  "fields": Array<{
372
389
  "id": string;
373
- "type": "text" | "textarea" | "email" | "phone" | "number" | "select" | "checkbox" | "date" | "radio" | "checkboxes" | "url" | "consent" | "heading";
390
+ "type": "text" | "textarea" | "email" | "phone" | "number" | "select" | "checkbox" | "date" | "radio" | "checkboxes" | "url" | "consent" | "heading" | "time";
374
391
  "label": string;
375
392
  "required": boolean;
376
393
  "help": string;
@@ -378,7 +395,23 @@ export type Events = {
378
395
  "placeholder"?: string;
379
396
  "width"?: "full" | "half";
380
397
  "allowOther"?: boolean;
398
+ "translations"?: {
399
+ [key: string]: {
400
+ "label"?: string;
401
+ "help"?: string;
402
+ "placeholder"?: string;
403
+ "options"?: Array<string>;
404
+ };
405
+ };
381
406
  }>;
407
+ "translations"?: {
408
+ [key: string]: {
409
+ "title"?: string;
410
+ "intro"?: string;
411
+ "submitLabel"?: string;
412
+ "confirmation"?: string;
413
+ };
414
+ };
382
415
  };
383
416
  };
384
417
  "url": string;
@@ -487,7 +520,7 @@ export type EventDetail = {
487
520
  "confirmation": string;
488
521
  "fields": Array<{
489
522
  "id": string;
490
- "type": "text" | "textarea" | "email" | "phone" | "number" | "select" | "checkbox" | "date" | "radio" | "checkboxes" | "url" | "consent" | "heading";
523
+ "type": "text" | "textarea" | "email" | "phone" | "number" | "select" | "checkbox" | "date" | "radio" | "checkboxes" | "url" | "consent" | "heading" | "time";
491
524
  "label": string;
492
525
  "required": boolean;
493
526
  "help": string;
@@ -495,7 +528,23 @@ export type EventDetail = {
495
528
  "placeholder"?: string;
496
529
  "width"?: "full" | "half";
497
530
  "allowOther"?: boolean;
531
+ "translations"?: {
532
+ [key: string]: {
533
+ "label"?: string;
534
+ "help"?: string;
535
+ "placeholder"?: string;
536
+ "options"?: Array<string>;
537
+ };
538
+ };
498
539
  }>;
540
+ "translations"?: {
541
+ [key: string]: {
542
+ "title"?: string;
543
+ "intro"?: string;
544
+ "submitLabel"?: string;
545
+ "confirmation"?: string;
546
+ };
547
+ };
499
548
  };
500
549
  };
501
550
  "url": string;
@@ -657,7 +706,7 @@ export type SearchResults = {
657
706
  "confirmation": string;
658
707
  "fields": Array<{
659
708
  "id": string;
660
- "type": "text" | "textarea" | "email" | "phone" | "number" | "select" | "checkbox" | "date" | "radio" | "checkboxes" | "url" | "consent" | "heading";
709
+ "type": "text" | "textarea" | "email" | "phone" | "number" | "select" | "checkbox" | "date" | "radio" | "checkboxes" | "url" | "consent" | "heading" | "time";
661
710
  "label": string;
662
711
  "required": boolean;
663
712
  "help": string;
@@ -665,7 +714,23 @@ export type SearchResults = {
665
714
  "placeholder"?: string;
666
715
  "width"?: "full" | "half";
667
716
  "allowOther"?: boolean;
717
+ "translations"?: {
718
+ [key: string]: {
719
+ "label"?: string;
720
+ "help"?: string;
721
+ "placeholder"?: string;
722
+ "options"?: Array<string>;
723
+ };
724
+ };
668
725
  }>;
726
+ "translations"?: {
727
+ [key: string]: {
728
+ "title"?: string;
729
+ "intro"?: string;
730
+ "submitLabel"?: string;
731
+ "confirmation"?: string;
732
+ };
733
+ };
669
734
  };
670
735
  };
671
736
  "url": string;
@@ -799,7 +864,7 @@ export type Form = {
799
864
  "confirmation": string;
800
865
  "fields": Array<{
801
866
  "id": string;
802
- "type": "text" | "textarea" | "email" | "phone" | "number" | "select" | "checkbox" | "date" | "radio" | "checkboxes" | "url" | "consent" | "heading";
867
+ "type": "text" | "textarea" | "email" | "phone" | "number" | "select" | "checkbox" | "date" | "radio" | "checkboxes" | "url" | "consent" | "heading" | "time";
803
868
  "label": string;
804
869
  "required": boolean;
805
870
  "help": string;
@@ -843,7 +908,7 @@ export type RsvpStatus = {
843
908
  "confirmation": string;
844
909
  "fields": Array<{
845
910
  "id": string;
846
- "type": "text" | "textarea" | "email" | "phone" | "number" | "select" | "checkbox" | "date" | "radio" | "checkboxes" | "url" | "consent" | "heading";
911
+ "type": "text" | "textarea" | "email" | "phone" | "number" | "select" | "checkbox" | "date" | "radio" | "checkboxes" | "url" | "consent" | "heading" | "time";
847
912
  "label": string;
848
913
  "required": boolean;
849
914
  "help": string;
@@ -1041,7 +1106,7 @@ export type BookingResult = {
1041
1106
  "confirmation": string;
1042
1107
  "fields": Array<{
1043
1108
  "id": string;
1044
- "type": "text" | "textarea" | "email" | "phone" | "number" | "select" | "checkbox" | "date" | "radio" | "checkboxes" | "url" | "consent" | "heading";
1109
+ "type": "text" | "textarea" | "email" | "phone" | "number" | "select" | "checkbox" | "date" | "radio" | "checkboxes" | "url" | "consent" | "heading" | "time";
1045
1110
  "label": string;
1046
1111
  "required": boolean;
1047
1112
  "help": string;
@@ -1049,7 +1114,23 @@ export type BookingResult = {
1049
1114
  "placeholder"?: string;
1050
1115
  "width"?: "full" | "half";
1051
1116
  "allowOther"?: boolean;
1117
+ "translations"?: {
1118
+ [key: string]: {
1119
+ "label"?: string;
1120
+ "help"?: string;
1121
+ "placeholder"?: string;
1122
+ "options"?: Array<string>;
1123
+ };
1124
+ };
1052
1125
  }>;
1126
+ "translations"?: {
1127
+ [key: string]: {
1128
+ "title"?: string;
1129
+ "intro"?: string;
1130
+ "submitLabel"?: string;
1131
+ "confirmation"?: string;
1132
+ };
1133
+ };
1053
1134
  };
1054
1135
  "answers": {
1055
1136
  [key: string]: string;
@@ -1212,10 +1293,34 @@ export type LiveStatus = {
1212
1293
  "dock": boolean;
1213
1294
  };
1214
1295
  };
1296
+ export type EventRequestOptions = {
1297
+ "open": boolean;
1298
+ "types": Array<{
1299
+ "id": string;
1300
+ "label": string;
1301
+ }>;
1302
+ "rooms": Array<{
1303
+ "slug": string;
1304
+ "name": string;
1305
+ "color": string;
1306
+ }>;
1307
+ "replyTime": string;
1308
+ "notice": string;
1309
+ "phone": string;
1310
+ "timezone": string;
1311
+ "events": Array<{
1312
+ "slug": string;
1313
+ "title": string;
1314
+ "dates": Array<string>;
1315
+ }>;
1316
+ };
1317
+ export type RequestReceipt = {
1318
+ "id": string;
1319
+ };
1215
1320
  export type ApiErrorResponse = {
1216
1321
  "version": 1;
1217
1322
  "error": {
1218
- "code": "invalid_request" | "unauthorized" | "forbidden" | "not_found" | "method_not_allowed" | "conflict" | "duplicate" | "gone" | "payload_too_large" | "unsupported_media_type" | "rate_limited" | "upstream_error" | "internal_error";
1323
+ "code": "invalid_request" | "unauthorized" | "forbidden" | "not_found" | "method_not_allowed" | "conflict" | "duplicate" | "gone" | "payload_too_large" | "unsupported_media_type" | "rate_limited" | "upstream_error" | "internal_error" | "closed" | "trap" | "busy" | "full" | "changed" | "title" | "type" | "start" | "end" | "past" | "far" | "repeat" | "room" | "people" | "event" | "date" | "what" | "name" | "email" | "phone";
1219
1324
  "message": string;
1220
1325
  "issues"?: Array<{
1221
1326
  "path": Array<string | number>;
@@ -1412,7 +1517,7 @@ export type EditorDocument = {
1412
1517
  "confirmation": string;
1413
1518
  "fields": Array<{
1414
1519
  "id": string;
1415
- "type": "text" | "textarea" | "email" | "phone" | "number" | "select" | "checkbox" | "date" | "radio" | "checkboxes" | "url" | "consent" | "heading";
1520
+ "type": "text" | "textarea" | "email" | "phone" | "number" | "select" | "checkbox" | "date" | "radio" | "checkboxes" | "url" | "consent" | "heading" | "time";
1416
1521
  "label": string;
1417
1522
  "required": boolean;
1418
1523
  "help": string;
@@ -1420,7 +1525,23 @@ export type EditorDocument = {
1420
1525
  "placeholder"?: string;
1421
1526
  "width"?: "full" | "half";
1422
1527
  "allowOther"?: boolean;
1528
+ "translations"?: {
1529
+ [key: string]: {
1530
+ "label"?: string;
1531
+ "help"?: string;
1532
+ "placeholder"?: string;
1533
+ "options"?: Array<string>;
1534
+ };
1535
+ };
1423
1536
  }>;
1537
+ "translations"?: {
1538
+ [key: string]: {
1539
+ "title"?: string;
1540
+ "intro"?: string;
1541
+ "submitLabel"?: string;
1542
+ "confirmation"?: string;
1543
+ };
1544
+ };
1424
1545
  };
1425
1546
  };
1426
1547
  }) | (null);
@@ -1615,7 +1736,7 @@ export type EditorBooking = {
1615
1736
  "confirmation": string;
1616
1737
  "fields": Array<{
1617
1738
  "id": string;
1618
- "type": "text" | "textarea" | "email" | "phone" | "number" | "select" | "checkbox" | "date" | "radio" | "checkboxes" | "url" | "consent" | "heading";
1739
+ "type": "text" | "textarea" | "email" | "phone" | "number" | "select" | "checkbox" | "date" | "radio" | "checkboxes" | "url" | "consent" | "heading" | "time";
1619
1740
  "label": string;
1620
1741
  "required": boolean;
1621
1742
  "help": string;
@@ -1623,7 +1744,23 @@ export type EditorBooking = {
1623
1744
  "placeholder"?: string;
1624
1745
  "width"?: "full" | "half";
1625
1746
  "allowOther"?: boolean;
1747
+ "translations"?: {
1748
+ [key: string]: {
1749
+ "label"?: string;
1750
+ "help"?: string;
1751
+ "placeholder"?: string;
1752
+ "options"?: Array<string>;
1753
+ };
1754
+ };
1626
1755
  }>;
1756
+ "translations"?: {
1757
+ [key: string]: {
1758
+ "title"?: string;
1759
+ "intro"?: string;
1760
+ "submitLabel"?: string;
1761
+ "confirmation"?: string;
1762
+ };
1763
+ };
1627
1764
  };
1628
1765
  "answers": {
1629
1766
  [key: string]: string;
@@ -1662,7 +1799,7 @@ export type EditorBookingList = {
1662
1799
  "confirmation": string;
1663
1800
  "fields": Array<{
1664
1801
  "id": string;
1665
- "type": "text" | "textarea" | "email" | "phone" | "number" | "select" | "checkbox" | "date" | "radio" | "checkboxes" | "url" | "consent" | "heading";
1802
+ "type": "text" | "textarea" | "email" | "phone" | "number" | "select" | "checkbox" | "date" | "radio" | "checkboxes" | "url" | "consent" | "heading" | "time";
1666
1803
  "label": string;
1667
1804
  "required": boolean;
1668
1805
  "help": string;
@@ -1670,7 +1807,23 @@ export type EditorBookingList = {
1670
1807
  "placeholder"?: string;
1671
1808
  "width"?: "full" | "half";
1672
1809
  "allowOther"?: boolean;
1810
+ "translations"?: {
1811
+ [key: string]: {
1812
+ "label"?: string;
1813
+ "help"?: string;
1814
+ "placeholder"?: string;
1815
+ "options"?: Array<string>;
1816
+ };
1817
+ };
1673
1818
  }>;
1819
+ "translations"?: {
1820
+ [key: string]: {
1821
+ "title"?: string;
1822
+ "intro"?: string;
1823
+ "submitLabel"?: string;
1824
+ "confirmation"?: string;
1825
+ };
1826
+ };
1674
1827
  };
1675
1828
  "answers": {
1676
1829
  [key: string]: string;
@@ -2353,7 +2506,7 @@ export type EditorSaveInput = {
2353
2506
  "confirmation"?: string;
2354
2507
  "fields"?: Array<{
2355
2508
  "id": string;
2356
- "type": "text" | "textarea" | "email" | "phone" | "number" | "select" | "checkbox" | "date" | "radio" | "checkboxes" | "url" | "consent" | "heading";
2509
+ "type": "text" | "textarea" | "email" | "phone" | "number" | "select" | "checkbox" | "date" | "radio" | "checkboxes" | "url" | "consent" | "heading" | "time";
2357
2510
  "label": string;
2358
2511
  "required"?: boolean;
2359
2512
  "help"?: string;
@@ -2361,7 +2514,23 @@ export type EditorSaveInput = {
2361
2514
  "placeholder"?: string;
2362
2515
  "width"?: "full" | "half";
2363
2516
  "allowOther"?: boolean;
2517
+ "translations"?: {
2518
+ [key: string]: {
2519
+ "label"?: string;
2520
+ "help"?: string;
2521
+ "placeholder"?: string;
2522
+ "options"?: Array<string>;
2523
+ };
2524
+ };
2364
2525
  }>;
2526
+ "translations"?: {
2527
+ [key: string]: {
2528
+ "title"?: string;
2529
+ "intro"?: string;
2530
+ "submitLabel"?: string;
2531
+ "confirmation"?: string;
2532
+ };
2533
+ };
2365
2534
  };
2366
2535
  };
2367
2536
  });
@@ -2720,6 +2889,26 @@ export type FormResponseInput = {
2720
2889
  "version"?: string;
2721
2890
  "website"?: string;
2722
2891
  };
2892
+ export type RequestFields = {
2893
+ "kind": "new" | "change";
2894
+ "type"?: string;
2895
+ "title"?: string;
2896
+ "start"?: string;
2897
+ "end"?: string;
2898
+ "repeat"?: "once" | "weekly" | "other";
2899
+ "repeatText"?: string;
2900
+ "rooms"?: Array<string>;
2901
+ "roomsUnsure"?: boolean;
2902
+ "people"?: (number) | (null);
2903
+ "event"?: string;
2904
+ "date"?: string;
2905
+ "message"?: string;
2906
+ "name": string;
2907
+ "email": string;
2908
+ "phone"?: string;
2909
+ "locale"?: string;
2910
+ "website"?: string;
2911
+ };
2723
2912
  export type RescheduleInput = {
2724
2913
  "start": string;
2725
2914
  "minutes"?: number;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@acms-subir/client",
3
- "version": "0.1.23",
3
+ "version": "0.1.25",
4
4
  "description": "Typed, dependency-free client for the ACMS public mobile API.",
5
5
  "type": "module",
6
6
  "license": "MIT",