@ai-matrx/meet 0.7.2 → 0.7.3
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 +20 -0
- package/dist/index.cjs +460 -35
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +268 -3
- package/dist/index.d.ts +268 -3
- package/dist/index.js +460 -35
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +463 -38
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +1 -1
- package/dist/react.d.ts +1 -1
- package/dist/react.js +463 -38
- package/dist/react.js.map +1 -1
- package/package.json +3 -3
package/dist/react.cjs
CHANGED
|
@@ -116,6 +116,7 @@ __export(react_exports, {
|
|
|
116
116
|
TRANSCRIPTION_TOPIC: () => TRANSCRIPTION_TOPIC,
|
|
117
117
|
WifiLowIcon: () => WifiLowIcon,
|
|
118
118
|
absenceSentence: () => absenceSentence,
|
|
119
|
+
announceMeeting: () => announceMeeting,
|
|
119
120
|
applyRoomEvent: () => applyRoomEvent,
|
|
120
121
|
asCallId: () => asCallId,
|
|
121
122
|
asMeetingId: () => asMeetingId,
|
|
@@ -130,6 +131,7 @@ __export(react_exports, {
|
|
|
130
131
|
canModerateParticipant: () => canModerateParticipant,
|
|
131
132
|
canTransition: () => canTransition,
|
|
132
133
|
captionSegment: () => captionSegment,
|
|
134
|
+
changesPatch: () => changesPatch,
|
|
133
135
|
computeStage: () => computeStage,
|
|
134
136
|
countLabel: () => countLabel,
|
|
135
137
|
createCallCenter: () => createCallCenter,
|
|
@@ -174,6 +176,7 @@ __export(react_exports, {
|
|
|
174
176
|
mapQuality: () => mapQuality,
|
|
175
177
|
meetingInviteAction: () => meetingInviteAction,
|
|
176
178
|
meetingLink: () => meetingLink,
|
|
179
|
+
meetingPath: () => meetingPath,
|
|
177
180
|
meetingSlug: () => meetingSlug,
|
|
178
181
|
meetingTopic: () => meetingTopic,
|
|
179
182
|
meetingWhen: () => meetingWhen,
|
|
@@ -190,9 +193,15 @@ __export(react_exports, {
|
|
|
190
193
|
parseRoomToken: () => parseRoomToken,
|
|
191
194
|
participantSummary: () => participantSummary,
|
|
192
195
|
playableRecordingFileId: () => playableRecordingFileId,
|
|
196
|
+
projectInvitee: () => projectInvitee,
|
|
193
197
|
projectNote: () => projectNote,
|
|
198
|
+
projectOccurrence: () => projectOccurrence,
|
|
199
|
+
projectOverride: () => projectOverride,
|
|
194
200
|
projectParticipant: () => projectParticipant,
|
|
201
|
+
projectRsvpInvitation: () => projectRsvpInvitation,
|
|
195
202
|
projectSegment: () => projectSegment,
|
|
203
|
+
projectUpcoming: () => projectUpcoming,
|
|
204
|
+
pushMeetingToGoogleCalendar: () => pushMeetingToGoogleCalendar,
|
|
196
205
|
readServerRefusal: () => readServerRefusal,
|
|
197
206
|
readableTranscript: () => readableTranscript,
|
|
198
207
|
recordingLabel: () => recordingLabel,
|
|
@@ -200,6 +209,7 @@ __export(react_exports, {
|
|
|
200
209
|
roleOf: () => roleOf,
|
|
201
210
|
roomTopic: () => roomTopic,
|
|
202
211
|
setGuestRecordAccess: () => setGuestRecordAccess,
|
|
212
|
+
settingsPatch: () => settingsPatch,
|
|
203
213
|
snapshotParticipant: () => snapshotParticipant,
|
|
204
214
|
unavailableFrom: () => unavailableFrom,
|
|
205
215
|
useCalls: () => useCalls,
|
|
@@ -266,7 +276,7 @@ var MeetError = class extends Error {
|
|
|
266
276
|
};
|
|
267
277
|
var FORBIDDEN_CODES = /* @__PURE__ */ new Set(["42501", "PGRST301", "PGRST302"]);
|
|
268
278
|
var NOT_FOUND_CODES = /* @__PURE__ */ new Set(["PGRST116", "PGRST205"]);
|
|
269
|
-
var CONFLICT_CODES = /* @__PURE__ */ new Set(["23505"]);
|
|
279
|
+
var CONFLICT_CODES = /* @__PURE__ */ new Set(["23505", "40001", "55000"]);
|
|
270
280
|
var SESSION_MARKERS = [
|
|
271
281
|
"auth session missing",
|
|
272
282
|
"jwt expired",
|
|
@@ -424,8 +434,19 @@ var MEET_ROUTES = {
|
|
|
424
434
|
*/
|
|
425
435
|
record: "/api/v1/meet/record",
|
|
426
436
|
/** A host chooses what guests may read of ONE meeting (MRF-1). */
|
|
427
|
-
recordAccess: "/api/v1/meet/record/access"
|
|
437
|
+
recordAccess: "/api/v1/meet/record/access",
|
|
438
|
+
/**
|
|
439
|
+
* Meet wave 1 (0.8): bring every invitee up to date after a write — sends the
|
|
440
|
+
* invitation / update / cancellation emails with their `.ics` and re-queues
|
|
441
|
+
* reminders. Idempotent. `{meeting_id}` is substituted by `meetingPath`.
|
|
442
|
+
*/
|
|
443
|
+
meetingAnnounce: "/api/v1/meet/meetings/{meeting_id}/announce",
|
|
444
|
+
/** Put a one-off meeting on the caller's own Google Calendar (gated by the server). */
|
|
445
|
+
meetingGoogleCalendar: "/api/v1/meet/meetings/{meeting_id}/google-calendar"
|
|
428
446
|
};
|
|
447
|
+
function meetingPath(template, meetingId) {
|
|
448
|
+
return template.replace("{meeting_id}", encodeURIComponent(meetingId));
|
|
449
|
+
}
|
|
429
450
|
var ROOM_TOKEN_HEADER = "x-meet-room-token";
|
|
430
451
|
var REFRESH_RATIO = 0.8;
|
|
431
452
|
function readString(source, key) {
|
|
@@ -555,6 +576,19 @@ function createTokenClient(options) {
|
|
|
555
576
|
"The link is wrong or the meeting was deleted. Show the 'meeting not found' screen; a durable link that 404s is never a retry."
|
|
556
577
|
);
|
|
557
578
|
}
|
|
579
|
+
if (response.status === 410) {
|
|
580
|
+
let reason = "This meeting was cancelled.";
|
|
581
|
+
try {
|
|
582
|
+
const body = await response.json();
|
|
583
|
+
if (typeof body?.detail?.message === "string") reason = body.detail.message;
|
|
584
|
+
} catch {
|
|
585
|
+
}
|
|
586
|
+
throw new MeetError(
|
|
587
|
+
"cancelled",
|
|
588
|
+
reason,
|
|
589
|
+
"Nobody can join a cancelled meeting. Show the cancelled screen with this sentence; ask the host to schedule a new one."
|
|
590
|
+
);
|
|
591
|
+
}
|
|
558
592
|
if (response.status === 423) {
|
|
559
593
|
throw new MeetError(
|
|
560
594
|
"room-locked",
|
|
@@ -756,12 +790,12 @@ function createMeetAi(options) {
|
|
|
756
790
|
async function dispatch(route, body, operation) {
|
|
757
791
|
const response = await send({ path: route, body, operation, requireAuth: true });
|
|
758
792
|
if (!response.ok) {
|
|
759
|
-
const
|
|
760
|
-
options.store.patch({ noteTakerRefusal:
|
|
793
|
+
const refusal2 = await refusalFor(response, operation);
|
|
794
|
+
options.store.patch({ noteTakerRefusal: refusal2 });
|
|
761
795
|
throw new MeetError(
|
|
762
796
|
response.status === 403 ? "forbidden" : "transport",
|
|
763
|
-
|
|
764
|
-
|
|
797
|
+
refusal2.reason,
|
|
798
|
+
refusal2.remedy
|
|
765
799
|
);
|
|
766
800
|
}
|
|
767
801
|
options.store.patch({ noteTakerRefusal: null });
|
|
@@ -799,11 +833,11 @@ function createMeetAi(options) {
|
|
|
799
833
|
...signal !== void 0 ? { signal } : {}
|
|
800
834
|
});
|
|
801
835
|
if (!response.ok) {
|
|
802
|
-
const
|
|
836
|
+
const refusal2 = await refusalFor(response, "meet.ai.ask");
|
|
803
837
|
throw new MeetError(
|
|
804
838
|
response.status === 403 || response.status === 401 ? "forbidden" : response.status === 404 ? "not-found" : "transport",
|
|
805
|
-
|
|
806
|
-
|
|
839
|
+
refusal2.reason,
|
|
840
|
+
refusal2.remedy
|
|
807
841
|
);
|
|
808
842
|
}
|
|
809
843
|
const body = response.body;
|
|
@@ -2243,11 +2277,11 @@ function createMeetingSession(options) {
|
|
|
2243
2277
|
} catch {
|
|
2244
2278
|
body = null;
|
|
2245
2279
|
}
|
|
2246
|
-
const
|
|
2280
|
+
const refusal2 = readServerRefusal(body);
|
|
2247
2281
|
throw new MeetError(
|
|
2248
2282
|
response.status === 403 ? "forbidden" : "transport",
|
|
2249
|
-
|
|
2250
|
-
|
|
2283
|
+
refusal2?.reason ?? `meet.endForEveryone: the server answered ${response.status}`,
|
|
2284
|
+
refusal2?.remedy !== void 0 && refusal2.remedy.length > 0 ? refusal2.remedy : "The meeting is still running. Only a host may end it, and the server re-checks that \u2014 being a host on this screen is not the decision."
|
|
2251
2285
|
);
|
|
2252
2286
|
}
|
|
2253
2287
|
let payload = null;
|
|
@@ -2290,7 +2324,11 @@ var TABLES = {
|
|
|
2290
2324
|
invites: "meet_call_invites",
|
|
2291
2325
|
recordings: "meet_recordings",
|
|
2292
2326
|
transcripts: "meet_transcript_segments",
|
|
2293
|
-
notes: "meet_notes"
|
|
2327
|
+
notes: "meet_notes",
|
|
2328
|
+
/** Wave 1 (0.8): who a meeting was sent to, and what they answered. */
|
|
2329
|
+
invitees: "meet_invitees",
|
|
2330
|
+
/** Wave 1 (0.8): one occurrence of a series cancelled or moved. */
|
|
2331
|
+
occurrenceOverrides: "meet_occurrence_overrides"
|
|
2294
2332
|
};
|
|
2295
2333
|
var RPCS = {
|
|
2296
2334
|
/** Atomic: create the invite row and stamp its expiry in one statement. */
|
|
@@ -2306,10 +2344,41 @@ var RPCS = {
|
|
|
2306
2344
|
admit: "meet_admit_participant",
|
|
2307
2345
|
setLock: "meet_set_lock",
|
|
2308
2346
|
endMeeting: "meet_end_meeting",
|
|
2309
|
-
recordConsent: "meet_record_consent"
|
|
2347
|
+
recordConsent: "meet_record_consent",
|
|
2348
|
+
/*
|
|
2349
|
+
* ── MEET WAVE 1 — management (0.8). Every write is a SECURITY DEFINER door
|
|
2350
|
+
* authorized by the meeting's host or a real iam grant (editor to change,
|
|
2351
|
+
* admin = co-host to archive or name a co-host) — never an organization
|
|
2352
|
+
* match. After any of these writes, call `announceMeeting` so the server
|
|
2353
|
+
* sends invitations / updates / cancellations and re-queues reminders.
|
|
2354
|
+
*/
|
|
2355
|
+
/** Schedule with every setting at create; unset settings come from the knobs. */
|
|
2356
|
+
scheduleMeeting: "meet_schedule_meeting",
|
|
2357
|
+
/** Edit / reschedule — a JSON patch with a version compare-and-swap. */
|
|
2358
|
+
updateMeeting: "meet_update_meeting",
|
|
2359
|
+
/** Cancel is a state (`cancelled_at`); the link keeps resolving. */
|
|
2360
|
+
cancelMeeting: "meet_cancel_meeting",
|
|
2361
|
+
/** Archive (soft delete) — the invitations and exceptions cascade. */
|
|
2362
|
+
archiveMeeting: "meet_archive_meeting",
|
|
2363
|
+
restoreMeeting: "meet_restore_meeting",
|
|
2364
|
+
/** Cancel, move or restore ONE occurrence of a series by its original start. */
|
|
2365
|
+
setOccurrence: "meet_set_occurrence",
|
|
2366
|
+
addInvitees: "meet_add_invitees",
|
|
2367
|
+
setInviteeRole: "meet_set_invitee_role",
|
|
2368
|
+
removeInvitee: "meet_remove_invitee",
|
|
2369
|
+
/** A signed-in invitee answers for themselves. */
|
|
2370
|
+
respond: "meet_respond",
|
|
2371
|
+
/** The emailed RSVP link (no account): read and answer. */
|
|
2372
|
+
invitationByToken: "meet_invitation_by_token",
|
|
2373
|
+
respondByToken: "meet_respond_by_token",
|
|
2374
|
+
/** One meeting's occurrences between two instants (INVOKER — the reader's RLS). */
|
|
2375
|
+
meetingOccurrences: "meet_meeting_occurrences",
|
|
2376
|
+
/** Every occurrence the reader can see between two instants — the Upcoming list. */
|
|
2377
|
+
occurrencesBetween: "meet_occurrences_between"
|
|
2310
2378
|
};
|
|
2311
2379
|
var VOID_RPCS = [RPCS.admit, RPCS.recordConsent];
|
|
2312
|
-
var MEETING_COLUMNS = "id,organization_id,room_name,slug,title,kind,host_user_id,scheduled_for,scheduled_duration_minutes,started_at,ended_at,locked,lobby_enabled,recording_policy,ai_enabled,metadata";
|
|
2380
|
+
var MEETING_COLUMNS = "id,organization_id,room_name,slug,title,kind,host_user_id,scheduled_for,scheduled_duration_minutes,started_at,ended_at,locked,lobby_enabled,recording_policy,ai_enabled,metadata,time_zone,agenda,recurrence_rule,join_before_host,cancelled_at,cancellation_reason,deleted_at,calendar_sequence,version";
|
|
2381
|
+
var INVITEE_COLUMNS = "id,meeting_id,invitee_user_id,email,display_name,role,rsvp_state,responded_at,rsvp_note,last_sent_sequence,last_sent_at";
|
|
2313
2382
|
var RECORDING_COLUMNS = "id,meeting_id,state,started_at,ended_at,started_by,file_id,failure_reason";
|
|
2314
2383
|
var SEGMENT_COLUMNS = "id,meeting_id,identity,speaker,text,started_at,is_final,metadata";
|
|
2315
2384
|
var NOTE_COLUMNS = "id,meeting_id,text,kind,assignee_user_id,created_at,metadata";
|
|
@@ -2407,6 +2476,138 @@ function projectNote(row) {
|
|
|
2407
2476
|
source: "record"
|
|
2408
2477
|
};
|
|
2409
2478
|
}
|
|
2479
|
+
var RSVP_STATES = ["needs_action", "accepted", "declined", "tentative"];
|
|
2480
|
+
var OCCURRENCE_STATES = ["scheduled", "moved", "cancelled"];
|
|
2481
|
+
function rsvpState(value) {
|
|
2482
|
+
return RSVP_STATES.includes(value) ? value : "needs_action";
|
|
2483
|
+
}
|
|
2484
|
+
function num(row, key) {
|
|
2485
|
+
const value = row[key];
|
|
2486
|
+
return typeof value === "number" ? value : null;
|
|
2487
|
+
}
|
|
2488
|
+
function when(row, key) {
|
|
2489
|
+
const value = row[key];
|
|
2490
|
+
if (value instanceof Date) return value.toISOString();
|
|
2491
|
+
return text(row, key);
|
|
2492
|
+
}
|
|
2493
|
+
function projectInvitee(row) {
|
|
2494
|
+
const operation = "meet.projectInvitee";
|
|
2495
|
+
const userId = text(row, "invitee_user_id");
|
|
2496
|
+
return {
|
|
2497
|
+
id: requireText(row, "id", operation),
|
|
2498
|
+
meetingId: asMeetingId(requireText(row, "meeting_id", operation)),
|
|
2499
|
+
userId: userId === null ? null : asUserId(userId),
|
|
2500
|
+
email: text(row, "email"),
|
|
2501
|
+
displayName: text(row, "display_name"),
|
|
2502
|
+
role: text(row, "role") === "cohost" ? "cohost" : "invitee",
|
|
2503
|
+
rsvpState: rsvpState(text(row, "rsvp_state")),
|
|
2504
|
+
respondedAt: when(row, "responded_at"),
|
|
2505
|
+
rsvpNote: text(row, "rsvp_note"),
|
|
2506
|
+
lastSentSequence: num(row, "last_sent_sequence"),
|
|
2507
|
+
lastSentAt: when(row, "last_sent_at")
|
|
2508
|
+
};
|
|
2509
|
+
}
|
|
2510
|
+
function projectOccurrence(row) {
|
|
2511
|
+
const operation = "meet.projectOccurrence";
|
|
2512
|
+
const state = text(row, "state");
|
|
2513
|
+
return {
|
|
2514
|
+
meetingId: asMeetingId(requireText(row, "meeting_id", operation)),
|
|
2515
|
+
originalStart: when(row, "original_start") ?? requireText(row, "original_start", operation),
|
|
2516
|
+
occurrenceStart: when(row, "occurrence_start") ?? requireText(row, "occurrence_start", operation),
|
|
2517
|
+
durationMinutes: num(row, "duration_minutes"),
|
|
2518
|
+
// An unknown state is shown as scheduled, never dropped: the row is real.
|
|
2519
|
+
state: OCCURRENCE_STATES.includes(state) ? state : "scheduled",
|
|
2520
|
+
sequence: num(row, "sequence") ?? 0
|
|
2521
|
+
};
|
|
2522
|
+
}
|
|
2523
|
+
function projectUpcoming(row) {
|
|
2524
|
+
const operation = "meet.projectUpcoming";
|
|
2525
|
+
const kind = text(row, "kind");
|
|
2526
|
+
const myRole = text(row, "my_role");
|
|
2527
|
+
const myRsvp = text(row, "my_rsvp");
|
|
2528
|
+
return {
|
|
2529
|
+
...projectOccurrence(row),
|
|
2530
|
+
organizationId: asOrganizationId(requireText(row, "organization_id", operation)),
|
|
2531
|
+
title: text(row, "title") ?? "Meeting",
|
|
2532
|
+
slug: requireText(row, "slug", operation),
|
|
2533
|
+
kind: kind === "scheduled" || kind === "recurring" ? kind : "instant",
|
|
2534
|
+
hostUserId: asUserId(requireText(row, "host_user_id", operation)),
|
|
2535
|
+
timeZone: text(row, "time_zone") ?? "UTC",
|
|
2536
|
+
meetingCancelled: bool(row, "meeting_cancelled", false),
|
|
2537
|
+
myRsvp: myRsvp === null ? null : rsvpState(myRsvp),
|
|
2538
|
+
myRole: myRole === "host" || myRole === "cohost" || myRole === "invitee" ? myRole : null
|
|
2539
|
+
};
|
|
2540
|
+
}
|
|
2541
|
+
function projectOverride(row) {
|
|
2542
|
+
const operation = "meet.projectOverride";
|
|
2543
|
+
return {
|
|
2544
|
+
id: requireText(row, "id", operation),
|
|
2545
|
+
meetingId: asMeetingId(requireText(row, "meeting_id", operation)),
|
|
2546
|
+
originalStart: when(row, "original_start") ?? requireText(row, "original_start", operation),
|
|
2547
|
+
state: text(row, "state") === "moved" ? "moved" : "cancelled",
|
|
2548
|
+
newStart: when(row, "new_start"),
|
|
2549
|
+
newDurationMinutes: num(row, "new_duration_minutes"),
|
|
2550
|
+
reason: text(row, "reason"),
|
|
2551
|
+
calendarSequence: num(row, "calendar_sequence") ?? 0,
|
|
2552
|
+
deletedAt: when(row, "deleted_at")
|
|
2553
|
+
};
|
|
2554
|
+
}
|
|
2555
|
+
function projectRsvpInvitation(body) {
|
|
2556
|
+
const operation = "meet.projectRsvpInvitation";
|
|
2557
|
+
if (typeof body !== "object" || body === null) {
|
|
2558
|
+
throw invalidResponse(operation, "the RSVP door returned no object");
|
|
2559
|
+
}
|
|
2560
|
+
const row = body;
|
|
2561
|
+
if (row["ok"] !== true) {
|
|
2562
|
+
return {
|
|
2563
|
+
ok: false,
|
|
2564
|
+
message: text(row, "message") ?? "This invitation link is no longer valid \u2014 ask the host to send it again."
|
|
2565
|
+
};
|
|
2566
|
+
}
|
|
2567
|
+
const meeting = row["meeting"] ?? {};
|
|
2568
|
+
const invitee = row["invitee"] ?? {};
|
|
2569
|
+
return {
|
|
2570
|
+
ok: true,
|
|
2571
|
+
meeting: {
|
|
2572
|
+
title: text(meeting, "title") ?? "Meeting",
|
|
2573
|
+
slug: requireText(meeting, "slug", operation),
|
|
2574
|
+
scheduledFor: when(meeting, "scheduled_for"),
|
|
2575
|
+
durationMinutes: num(meeting, "duration_minutes"),
|
|
2576
|
+
timeZone: text(meeting, "time_zone") ?? "UTC",
|
|
2577
|
+
agenda: text(meeting, "agenda"),
|
|
2578
|
+
recurrenceRule: text(meeting, "recurrence_rule"),
|
|
2579
|
+
cancelledAt: when(meeting, "cancelled_at"),
|
|
2580
|
+
cancellationReason: text(meeting, "cancellation_reason"),
|
|
2581
|
+
endedAt: when(meeting, "ended_at")
|
|
2582
|
+
},
|
|
2583
|
+
invitee: {
|
|
2584
|
+
displayName: text(invitee, "display_name"),
|
|
2585
|
+
email: text(invitee, "email"),
|
|
2586
|
+
rsvpState: rsvpState(text(invitee, "rsvp_state")),
|
|
2587
|
+
respondedAt: when(invitee, "responded_at")
|
|
2588
|
+
}
|
|
2589
|
+
};
|
|
2590
|
+
}
|
|
2591
|
+
function settingsPatch(settings) {
|
|
2592
|
+
const patch = {};
|
|
2593
|
+
if (settings.lobbyEnabled !== void 0) patch["lobby_enabled"] = settings.lobbyEnabled;
|
|
2594
|
+
if (settings.recordingPolicy !== void 0) patch["recording_policy"] = settings.recordingPolicy;
|
|
2595
|
+
if (settings.aiEnabled !== void 0) patch["ai_enabled"] = settings.aiEnabled;
|
|
2596
|
+
if (settings.joinBeforeHost !== void 0) patch["join_before_host"] = settings.joinBeforeHost;
|
|
2597
|
+
return patch;
|
|
2598
|
+
}
|
|
2599
|
+
function changesPatch(changes) {
|
|
2600
|
+
const patch = settingsPatch(changes);
|
|
2601
|
+
if (changes.title !== void 0) patch["title"] = changes.title;
|
|
2602
|
+
if (changes.agenda !== void 0) patch["agenda"] = changes.agenda;
|
|
2603
|
+
if (changes.timeZone !== void 0) patch["time_zone"] = changes.timeZone;
|
|
2604
|
+
if (changes.scheduledFor !== void 0) patch["scheduled_for"] = changes.scheduledFor;
|
|
2605
|
+
if (changes.scheduledDurationMinutes !== void 0) {
|
|
2606
|
+
patch["scheduled_duration_minutes"] = changes.scheduledDurationMinutes;
|
|
2607
|
+
}
|
|
2608
|
+
if (changes.recurrenceRule !== void 0) patch["recurrence_rule"] = changes.recurrenceRule;
|
|
2609
|
+
return patch;
|
|
2610
|
+
}
|
|
2410
2611
|
function createMeetRepository(options) {
|
|
2411
2612
|
const db = options.client.schema(MEET_SCHEMA);
|
|
2412
2613
|
async function guardVoid(operation, run) {
|
|
@@ -2476,7 +2677,16 @@ function createMeetRepository(options) {
|
|
|
2476
2677
|
lobbyEnabled: bool(row, "lobby_enabled", true),
|
|
2477
2678
|
recordingPolicy: policy === "disabled" || policy === "always-on" ? policy : "host-controlled",
|
|
2478
2679
|
aiEnabled: bool(row, "ai_enabled", true),
|
|
2479
|
-
metadata: typeof metadata === "object" && metadata !== null && !Array.isArray(metadata) ? metadata : {}
|
|
2680
|
+
metadata: typeof metadata === "object" && metadata !== null && !Array.isArray(metadata) ? metadata : {},
|
|
2681
|
+
timeZone: text(row, "time_zone") ?? "UTC",
|
|
2682
|
+
agenda: text(row, "agenda"),
|
|
2683
|
+
recurrenceRule: text(row, "recurrence_rule"),
|
|
2684
|
+
joinBeforeHost: bool(row, "join_before_host", true),
|
|
2685
|
+
cancelledAt: text(row, "cancelled_at"),
|
|
2686
|
+
cancellationReason: text(row, "cancellation_reason"),
|
|
2687
|
+
deletedAt: text(row, "deleted_at"),
|
|
2688
|
+
calendarSequence: typeof row["calendar_sequence"] === "number" ? row["calendar_sequence"] : 0,
|
|
2689
|
+
version: typeof row["version"] === "number" ? row["version"] : 1
|
|
2480
2690
|
};
|
|
2481
2691
|
}
|
|
2482
2692
|
function projectRecording(row) {
|
|
@@ -2563,6 +2773,170 @@ function createMeetRepository(options) {
|
|
|
2563
2773
|
projectNote,
|
|
2564
2774
|
projectRecording,
|
|
2565
2775
|
projectAttendee,
|
|
2776
|
+
projectInvitee,
|
|
2777
|
+
async scheduleMeeting(input) {
|
|
2778
|
+
requireOrg(input.organizationId, "meet.scheduleMeeting");
|
|
2779
|
+
const row = await guard(
|
|
2780
|
+
"meet.scheduleMeeting",
|
|
2781
|
+
() => db.rpc(RPCS.scheduleMeeting, {
|
|
2782
|
+
p_organization_id: input.organizationId,
|
|
2783
|
+
p_host_user_id: input.hostUserId,
|
|
2784
|
+
p_title: input.title,
|
|
2785
|
+
p_scheduled_for: input.scheduledFor,
|
|
2786
|
+
p_time_zone: input.timeZone,
|
|
2787
|
+
p_duration_minutes: input.durationMinutes ?? null,
|
|
2788
|
+
p_agenda: input.agenda ?? null,
|
|
2789
|
+
p_recurrence_rule: input.recurrenceRule ?? null,
|
|
2790
|
+
p_settings: settingsPatch(input.settings ?? {})
|
|
2791
|
+
})
|
|
2792
|
+
);
|
|
2793
|
+
return projectMeeting(row);
|
|
2794
|
+
},
|
|
2795
|
+
async updateMeeting(meetingId, changes, options2 = {}) {
|
|
2796
|
+
const row = await guard(
|
|
2797
|
+
"meet.updateMeeting",
|
|
2798
|
+
() => db.rpc(RPCS.updateMeeting, {
|
|
2799
|
+
p_meeting_id: meetingId,
|
|
2800
|
+
p_changes: changesPatch(changes),
|
|
2801
|
+
p_expected_version: options2.expectedVersion ?? null,
|
|
2802
|
+
p_by_user_id: options2.byUserId ?? null
|
|
2803
|
+
})
|
|
2804
|
+
);
|
|
2805
|
+
return projectMeeting(row);
|
|
2806
|
+
},
|
|
2807
|
+
async cancelMeeting(meetingId, reason, byUserId = null) {
|
|
2808
|
+
const row = await guard(
|
|
2809
|
+
"meet.cancelMeeting",
|
|
2810
|
+
() => db.rpc(RPCS.cancelMeeting, {
|
|
2811
|
+
p_meeting_id: meetingId,
|
|
2812
|
+
p_reason: reason,
|
|
2813
|
+
p_by_user_id: byUserId
|
|
2814
|
+
})
|
|
2815
|
+
);
|
|
2816
|
+
return projectMeeting(row);
|
|
2817
|
+
},
|
|
2818
|
+
async archiveMeeting(meetingId, byUserId = null) {
|
|
2819
|
+
const row = await guard(
|
|
2820
|
+
"meet.archiveMeeting",
|
|
2821
|
+
() => db.rpc(RPCS.archiveMeeting, { p_meeting_id: meetingId, p_by_user_id: byUserId })
|
|
2822
|
+
);
|
|
2823
|
+
return projectMeeting(row);
|
|
2824
|
+
},
|
|
2825
|
+
async restoreMeeting(meetingId, byUserId = null) {
|
|
2826
|
+
const row = await guard(
|
|
2827
|
+
"meet.restoreMeeting",
|
|
2828
|
+
() => db.rpc(RPCS.restoreMeeting, { p_meeting_id: meetingId, p_by_user_id: byUserId })
|
|
2829
|
+
);
|
|
2830
|
+
return projectMeeting(row);
|
|
2831
|
+
},
|
|
2832
|
+
async setOccurrence(args) {
|
|
2833
|
+
const row = await guard(
|
|
2834
|
+
"meet.setOccurrence",
|
|
2835
|
+
() => db.rpc(RPCS.setOccurrence, {
|
|
2836
|
+
p_meeting_id: args.meetingId,
|
|
2837
|
+
p_original_start: args.originalStart,
|
|
2838
|
+
p_action: args.action,
|
|
2839
|
+
p_new_start: args.newStart ?? null,
|
|
2840
|
+
p_new_duration_minutes: args.newDurationMinutes ?? null,
|
|
2841
|
+
p_reason: args.reason ?? null,
|
|
2842
|
+
p_by_user_id: args.byUserId ?? null
|
|
2843
|
+
})
|
|
2844
|
+
);
|
|
2845
|
+
return projectOverride(row);
|
|
2846
|
+
},
|
|
2847
|
+
async meetingOccurrences(meetingId, { from, to, limit = 200 }) {
|
|
2848
|
+
const rows = await guard(
|
|
2849
|
+
"meet.meetingOccurrences",
|
|
2850
|
+
() => db.rpc(RPCS.meetingOccurrences, {
|
|
2851
|
+
p_meeting_id: meetingId,
|
|
2852
|
+
p_from: from,
|
|
2853
|
+
p_to: to,
|
|
2854
|
+
p_limit: limit
|
|
2855
|
+
})
|
|
2856
|
+
);
|
|
2857
|
+
return rows.map(projectOccurrence);
|
|
2858
|
+
},
|
|
2859
|
+
async occurrencesBetween({ from, to, organizationId = null, limit = 500 }) {
|
|
2860
|
+
const rows = await guard(
|
|
2861
|
+
"meet.occurrencesBetween",
|
|
2862
|
+
() => db.rpc(RPCS.occurrencesBetween, {
|
|
2863
|
+
p_from: from,
|
|
2864
|
+
p_to: to,
|
|
2865
|
+
p_organization_id: organizationId,
|
|
2866
|
+
p_limit: limit
|
|
2867
|
+
})
|
|
2868
|
+
);
|
|
2869
|
+
return rows.map(projectUpcoming);
|
|
2870
|
+
},
|
|
2871
|
+
async invitees(meetingId) {
|
|
2872
|
+
const response = await db.from(TABLES.invitees).select(INVITEE_COLUMNS).eq("meeting_id", meetingId).is("deleted_at", null).order("created_at", { ascending: true }).order("id", { ascending: true });
|
|
2873
|
+
if (response.error !== null) throw normalizeMeetError(response.error, "meet.invitees");
|
|
2874
|
+
return (response.data ?? []).map(projectInvitee);
|
|
2875
|
+
},
|
|
2876
|
+
async addInvitees(meetingId, people, byUserId = null) {
|
|
2877
|
+
const rows = await guard(
|
|
2878
|
+
"meet.addInvitees",
|
|
2879
|
+
() => db.rpc(RPCS.addInvitees, {
|
|
2880
|
+
p_meeting_id: meetingId,
|
|
2881
|
+
p_invitees: people.map((person) => ({
|
|
2882
|
+
...person.userId !== void 0 ? { user_id: person.userId } : {},
|
|
2883
|
+
...person.email !== void 0 ? { email: person.email } : {},
|
|
2884
|
+
...person.displayName !== void 0 ? { display_name: person.displayName } : {},
|
|
2885
|
+
...person.role !== void 0 ? { role: person.role } : {}
|
|
2886
|
+
})),
|
|
2887
|
+
p_by_user_id: byUserId
|
|
2888
|
+
})
|
|
2889
|
+
);
|
|
2890
|
+
return rows.map(projectInvitee);
|
|
2891
|
+
},
|
|
2892
|
+
async setInviteeRole(inviteeId, role, byUserId = null) {
|
|
2893
|
+
const row = await guard(
|
|
2894
|
+
"meet.setInviteeRole",
|
|
2895
|
+
() => db.rpc(RPCS.setInviteeRole, {
|
|
2896
|
+
p_invitee_id: inviteeId,
|
|
2897
|
+
p_role: role,
|
|
2898
|
+
p_by_user_id: byUserId
|
|
2899
|
+
})
|
|
2900
|
+
);
|
|
2901
|
+
return projectInvitee(row);
|
|
2902
|
+
},
|
|
2903
|
+
async removeInvitee(inviteeId, byUserId = null) {
|
|
2904
|
+
const row = await guard(
|
|
2905
|
+
"meet.removeInvitee",
|
|
2906
|
+
() => db.rpc(RPCS.removeInvitee, { p_invitee_id: inviteeId, p_by_user_id: byUserId })
|
|
2907
|
+
);
|
|
2908
|
+
return projectInvitee(row);
|
|
2909
|
+
},
|
|
2910
|
+
async respond(meetingId, answer, note = null) {
|
|
2911
|
+
const row = await guard(
|
|
2912
|
+
"meet.respond",
|
|
2913
|
+
() => db.rpc(RPCS.respond, {
|
|
2914
|
+
p_meeting_id: meetingId,
|
|
2915
|
+
p_response: answer,
|
|
2916
|
+
p_note: note,
|
|
2917
|
+
p_by_user_id: null
|
|
2918
|
+
})
|
|
2919
|
+
);
|
|
2920
|
+
return projectInvitee(row);
|
|
2921
|
+
},
|
|
2922
|
+
async invitationByToken(secret) {
|
|
2923
|
+
const body = await guard(
|
|
2924
|
+
"meet.invitationByToken",
|
|
2925
|
+
() => db.rpc(RPCS.invitationByToken, { p_secret: secret })
|
|
2926
|
+
);
|
|
2927
|
+
return projectRsvpInvitation(body);
|
|
2928
|
+
},
|
|
2929
|
+
async respondByToken(secret, answer, note = null) {
|
|
2930
|
+
const body = await guard(
|
|
2931
|
+
"meet.respondByToken",
|
|
2932
|
+
() => db.rpc(RPCS.respondByToken, {
|
|
2933
|
+
p_secret: secret,
|
|
2934
|
+
p_response: answer,
|
|
2935
|
+
p_note: note
|
|
2936
|
+
})
|
|
2937
|
+
);
|
|
2938
|
+
return projectRsvpInvitation(body);
|
|
2939
|
+
},
|
|
2566
2940
|
async attendees(meetingId) {
|
|
2567
2941
|
const response = await db.from(TABLES.participants).select(ATTENDEE_COLUMNS).eq("meeting_id", meetingId).order("joined_at", { ascending: true }).order("id", { ascending: true });
|
|
2568
2942
|
if (response.error !== null) throw normalizeMeetError(response.error, "meet.attendees");
|
|
@@ -2990,14 +3364,14 @@ function noteTakerStatus(args) {
|
|
|
2990
3364
|
const row = typeof raw === "object" && raw !== null && !Array.isArray(raw) ? raw : {};
|
|
2991
3365
|
const recorded = readState(row["state"]);
|
|
2992
3366
|
const detail = typeof row["reason"] === "string" && row["reason"].length > 0 ? row["reason"] : null;
|
|
2993
|
-
const
|
|
3367
|
+
const refusal2 = args.refusal ?? null;
|
|
2994
3368
|
if (recorded === null) {
|
|
2995
|
-
return { state: "absent", detail, present, refusal };
|
|
3369
|
+
return { state: "absent", detail, present, refusal: refusal2 };
|
|
2996
3370
|
}
|
|
2997
3371
|
if (recorded === "transcribing" && !present) {
|
|
2998
|
-
return { state: "handoff_pending", detail, present, refusal };
|
|
3372
|
+
return { state: "handoff_pending", detail, present, refusal: refusal2 };
|
|
2999
3373
|
}
|
|
3000
|
-
return { state: recorded, detail, present, refusal };
|
|
3374
|
+
return { state: recorded, detail, present, refusal: refusal2 };
|
|
3001
3375
|
}
|
|
3002
3376
|
function noteTakerLabel(status) {
|
|
3003
3377
|
switch (status.state) {
|
|
@@ -4022,11 +4396,11 @@ function computeStage(args) {
|
|
|
4022
4396
|
presenting: sharer !== null
|
|
4023
4397
|
};
|
|
4024
4398
|
}
|
|
4025
|
-
function gridColumns(
|
|
4026
|
-
if (
|
|
4027
|
-
if (
|
|
4028
|
-
if (
|
|
4029
|
-
if (
|
|
4399
|
+
function gridColumns(count2) {
|
|
4400
|
+
if (count2 <= 1) return 1;
|
|
4401
|
+
if (count2 <= 4) return 2;
|
|
4402
|
+
if (count2 <= 9) return 3;
|
|
4403
|
+
if (count2 <= 16) return 4;
|
|
4030
4404
|
return 5;
|
|
4031
4405
|
}
|
|
4032
4406
|
|
|
@@ -4200,7 +4574,7 @@ function meetingWhen(meeting, locale) {
|
|
|
4200
4574
|
if (start === null) return "Time not recorded";
|
|
4201
4575
|
const startedAt = new Date(start);
|
|
4202
4576
|
if (Number.isNaN(startedAt.getTime())) return "Time not recorded";
|
|
4203
|
-
const
|
|
4577
|
+
const when2 = startedAt.toLocaleString(locale, {
|
|
4204
4578
|
weekday: "long",
|
|
4205
4579
|
year: "numeric",
|
|
4206
4580
|
month: "long",
|
|
@@ -4208,11 +4582,11 @@ function meetingWhen(meeting, locale) {
|
|
|
4208
4582
|
hour: "numeric",
|
|
4209
4583
|
minute: "2-digit"
|
|
4210
4584
|
});
|
|
4211
|
-
if (meeting.endedAt === null || meeting.startedAt === null) return
|
|
4585
|
+
if (meeting.endedAt === null || meeting.startedAt === null) return when2;
|
|
4212
4586
|
const endedAt = new Date(meeting.endedAt);
|
|
4213
|
-
if (Number.isNaN(endedAt.getTime())) return
|
|
4587
|
+
if (Number.isNaN(endedAt.getTime())) return when2;
|
|
4214
4588
|
const elapsedMs = endedAt.getTime() - startedAt.getTime();
|
|
4215
|
-
return `${
|
|
4589
|
+
return `${when2} \xB7 ${(0, import_format.formatDurationMs)(elapsedMs, { style: "long" })}`;
|
|
4216
4590
|
}
|
|
4217
4591
|
var GUEST_RECORD_ACCESS_LEVELS = [
|
|
4218
4592
|
"none",
|
|
@@ -4319,8 +4693,8 @@ async function loadGuestMeetingRecord(args) {
|
|
|
4319
4693
|
);
|
|
4320
4694
|
}
|
|
4321
4695
|
if (!response.ok) {
|
|
4322
|
-
const
|
|
4323
|
-
return refusedBundle(meeting,
|
|
4696
|
+
const refusal2 = await readRefusal(response);
|
|
4697
|
+
return refusedBundle(meeting, refusal2.message, refusal2.remedy);
|
|
4324
4698
|
}
|
|
4325
4699
|
const body = await response.json();
|
|
4326
4700
|
const payload = typeof body["data"] === "object" && body["data"] !== null ? body["data"] : body;
|
|
@@ -4411,8 +4785,8 @@ async function setGuestRecordAccess(args) {
|
|
|
4411
4785
|
}
|
|
4412
4786
|
});
|
|
4413
4787
|
if (!response.ok) {
|
|
4414
|
-
const
|
|
4415
|
-
throw new MeetError("forbidden",
|
|
4788
|
+
const refusal2 = await readRefusal(response);
|
|
4789
|
+
throw new MeetError("forbidden", refusal2.message, refusal2.remedy);
|
|
4416
4790
|
}
|
|
4417
4791
|
const body = await response.json();
|
|
4418
4792
|
const payload = typeof body["data"] === "object" && body["data"] !== null ? body["data"] : body;
|
|
@@ -5079,8 +5453,8 @@ function callStateLabel(state, outgoing) {
|
|
|
5079
5453
|
return "Call";
|
|
5080
5454
|
}
|
|
5081
5455
|
}
|
|
5082
|
-
function countLabel(
|
|
5083
|
-
return `${
|
|
5456
|
+
function countLabel(count2, singular, plural = `${singular}s`) {
|
|
5457
|
+
return `${count2} ${count2 === 1 ? singular : plural}`;
|
|
5084
5458
|
}
|
|
5085
5459
|
|
|
5086
5460
|
// src/react/icons.tsx
|
|
@@ -6138,7 +6512,7 @@ function ScheduleMeetingBody({
|
|
|
6138
6512
|
host
|
|
6139
6513
|
}) {
|
|
6140
6514
|
const [title, setTitle] = (0, import_react4.useState)("");
|
|
6141
|
-
const [
|
|
6515
|
+
const [when2, setWhen] = (0, import_react4.useState)("");
|
|
6142
6516
|
const [kind, setKind] = (0, import_react4.useState)("scheduled");
|
|
6143
6517
|
const [busy, setBusy] = (0, import_react4.useState)(false);
|
|
6144
6518
|
const [link, setLink] = (0, import_react4.useState)(null);
|
|
@@ -6158,7 +6532,7 @@ function ScheduleMeetingBody({
|
|
|
6158
6532
|
hostUserId: host.identity.userId,
|
|
6159
6533
|
title: title.trim(),
|
|
6160
6534
|
kind,
|
|
6161
|
-
scheduledFor:
|
|
6535
|
+
scheduledFor: when2.length > 0 ? new Date(when2).toISOString() : null
|
|
6162
6536
|
}).then((meeting) => {
|
|
6163
6537
|
setLink(meetingLink(appBaseUrl, meeting.slug));
|
|
6164
6538
|
onScheduled?.(meeting.slug);
|
|
@@ -6188,7 +6562,7 @@ function ScheduleMeetingBody({
|
|
|
6188
6562
|
{
|
|
6189
6563
|
className: "mx-meet__input",
|
|
6190
6564
|
type: "datetime-local",
|
|
6191
|
-
value:
|
|
6565
|
+
value: when2,
|
|
6192
6566
|
onChange: (event) => setWhen(event.target.value)
|
|
6193
6567
|
}
|
|
6194
6568
|
)
|
|
@@ -6768,4 +7142,55 @@ function createMeetingInviteHandler(options) {
|
|
|
6768
7142
|
}
|
|
6769
7143
|
};
|
|
6770
7144
|
}
|
|
7145
|
+
|
|
7146
|
+
// src/core/management.ts
|
|
7147
|
+
async function refusal(response, operation) {
|
|
7148
|
+
let body = null;
|
|
7149
|
+
try {
|
|
7150
|
+
body = await response.json();
|
|
7151
|
+
} catch {
|
|
7152
|
+
body = null;
|
|
7153
|
+
}
|
|
7154
|
+
const said = readServerRefusal(body);
|
|
7155
|
+
return new MeetError(
|
|
7156
|
+
response.status === 403 || response.status === 401 ? "forbidden" : response.status === 404 ? "not-found" : response.status === 409 ? "conflict" : "transport",
|
|
7157
|
+
`${operation}: ${said?.reason ?? `the server answered ${response.status}`}`,
|
|
7158
|
+
said?.remedy || "The meeting itself is saved \u2014 only the telling failed. Try again; the call is idempotent."
|
|
7159
|
+
);
|
|
7160
|
+
}
|
|
7161
|
+
function count(body, key) {
|
|
7162
|
+
const value = body[key];
|
|
7163
|
+
return typeof value === "number" ? value : 0;
|
|
7164
|
+
}
|
|
7165
|
+
async function announceMeeting(api, meetingId) {
|
|
7166
|
+
const operation = "meet.announceMeeting";
|
|
7167
|
+
const response = await api.request({
|
|
7168
|
+
path: meetingPath(MEET_ROUTES.meetingAnnounce, meetingId),
|
|
7169
|
+
method: "POST",
|
|
7170
|
+
requireAuth: true,
|
|
7171
|
+
operation
|
|
7172
|
+
});
|
|
7173
|
+
if (!response.ok) throw await refusal(response, operation);
|
|
7174
|
+
const body = await response.json();
|
|
7175
|
+
return {
|
|
7176
|
+
invitations: count(body, "invitations"),
|
|
7177
|
+
updates: count(body, "updates"),
|
|
7178
|
+
cancellations: count(body, "cancellations"),
|
|
7179
|
+
alreadyCurrent: count(body, "already_current"),
|
|
7180
|
+
remindersQueued: count(body, "reminders_queued"),
|
|
7181
|
+
remindersCancelled: count(body, "reminders_cancelled")
|
|
7182
|
+
};
|
|
7183
|
+
}
|
|
7184
|
+
async function pushMeetingToGoogleCalendar(api, meetingId, target) {
|
|
7185
|
+
const operation = "meet.pushMeetingToGoogleCalendar";
|
|
7186
|
+
const response = await api.request({
|
|
7187
|
+
path: meetingPath(MEET_ROUTES.meetingGoogleCalendar, meetingId),
|
|
7188
|
+
method: "POST",
|
|
7189
|
+
requireAuth: true,
|
|
7190
|
+
operation,
|
|
7191
|
+
body: { connection_id: target.connectionId, calendar_id: target.calendarId ?? "primary" }
|
|
7192
|
+
});
|
|
7193
|
+
if (!response.ok) throw await refusal(response, operation);
|
|
7194
|
+
return await response.json();
|
|
7195
|
+
}
|
|
6771
7196
|
//# sourceMappingURL=react.cjs.map
|