@ai-matrx/meet 0.11.27 → 0.11.28

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 CHANGED
@@ -1,5 +1,11 @@
1
1
  # Changelog — `@ai-matrx/meet`
2
2
 
3
+ ## 0.11.28
4
+
5
+ Automatic changed-only republish (docs/metadata drift since the last tag — see
6
+ `git diff npm/meet/v0.11.27..npm/meet/v0.11.28 -- apps/shared/meet`).
7
+ No source changes intended and no consumer action required.
8
+
3
9
  ## 0.11.27
4
10
 
5
11
  Automatic changed-only republish (docs/metadata drift since the last tag — see
@@ -149,6 +149,17 @@ interface MeetParticipant {
149
149
  readonly attributes: Readonly<Record<string, string>>;
150
150
  }
151
151
  type MeetingKind = "instant" | "scheduled" | "recurring";
152
+ /**
153
+ * WHAT THE LINK'S CURRENT RUN IS, read through the no-pass link door (`meet_link_state`) so the
154
+ * entry screen can say it before any Join (CORE-DESIGN §2.3). One vocabulary: `reason` is a
155
+ * join-gate reason code (`ended` · `cancelled`) or null; no private data rides it.
156
+ */
157
+ interface LinkRunState {
158
+ readonly state: "open" | "not_started" | "ended" | "cancelled";
159
+ readonly reason: "ended" | "cancelled" | null;
160
+ /** `ended`: the next run's start (null = the meeting can never run again). `not_started`: when it starts. */
161
+ readonly nextStart: string | null;
162
+ }
152
163
  interface MeetingRecord {
153
164
  readonly id: MeetingId;
154
165
  readonly organizationId: OrganizationId;
@@ -163,6 +174,8 @@ interface MeetingRecord {
163
174
  readonly scheduledDurationMinutes: number | null;
164
175
  readonly startedAt: string | null;
165
176
  readonly endedAt: string | null;
177
+ /** Present only on a row resolved through the link door; absent = unknown (never guessed). */
178
+ readonly linkRun?: LinkRunState | undefined;
166
179
  readonly locked: boolean;
167
180
  readonly lobbyEnabled: boolean;
168
181
  readonly recordingPolicy: RecordingPolicy;
@@ -149,6 +149,17 @@ interface MeetParticipant {
149
149
  readonly attributes: Readonly<Record<string, string>>;
150
150
  }
151
151
  type MeetingKind = "instant" | "scheduled" | "recurring";
152
+ /**
153
+ * WHAT THE LINK'S CURRENT RUN IS, read through the no-pass link door (`meet_link_state`) so the
154
+ * entry screen can say it before any Join (CORE-DESIGN §2.3). One vocabulary: `reason` is a
155
+ * join-gate reason code (`ended` · `cancelled`) or null; no private data rides it.
156
+ */
157
+ interface LinkRunState {
158
+ readonly state: "open" | "not_started" | "ended" | "cancelled";
159
+ readonly reason: "ended" | "cancelled" | null;
160
+ /** `ended`: the next run's start (null = the meeting can never run again). `not_started`: when it starts. */
161
+ readonly nextStart: string | null;
162
+ }
152
163
  interface MeetingRecord {
153
164
  readonly id: MeetingId;
154
165
  readonly organizationId: OrganizationId;
@@ -163,6 +174,8 @@ interface MeetingRecord {
163
174
  readonly scheduledDurationMinutes: number | null;
164
175
  readonly startedAt: string | null;
165
176
  readonly endedAt: string | null;
177
+ /** Present only on a row resolved through the link door; absent = unknown (never guessed). */
178
+ readonly linkRun?: LinkRunState | undefined;
166
179
  readonly locked: boolean;
167
180
  readonly lobbyEnabled: boolean;
168
181
  readonly recordingPolicy: RecordingPolicy;
@@ -1,5 +1,5 @@
1
1
  import { ReactNode } from 'react';
2
- import { M as MeetingRecord, P as ParticipantIdentity, R as RoomName, a as MeetParticipant } from './collab-CIyXdQ5l.js';
2
+ import { M as MeetingRecord, P as ParticipantIdentity, R as RoomName, a as MeetParticipant } from './collab-CUxjUtrb.js';
3
3
 
4
4
  /**
5
5
  * THE PRODUCT UI (R6/R7). Not a headless kernel with a note telling the host to
@@ -1,5 +1,5 @@
1
1
  import { ReactNode } from 'react';
2
- import { M as MeetingRecord, P as ParticipantIdentity, R as RoomName, a as MeetParticipant } from './collab-CIyXdQ5l.cjs';
2
+ import { M as MeetingRecord, P as ParticipantIdentity, R as RoomName, a as MeetParticipant } from './collab-CUxjUtrb.cjs';
3
3
 
4
4
  /**
5
5
  * THE PRODUCT UI (R6/R7). Not a headless kernel with a note telling the host to
package/dist/core.cjs CHANGED
@@ -1367,6 +1367,8 @@ function nextPhase(from, event) {
1367
1367
  return from === "resolving" ? "prejoin" : null;
1368
1368
  case "unsupported":
1369
1369
  return from === "resolving" ? "unsupported" : null;
1370
+ case "link_state":
1371
+ return from === "resolving" && event.reason !== null && isJoinRefusalReason(event.reason) ? refusalPhase(event.reason) : null;
1370
1372
  case "join":
1371
1373
  return JOINABLE_FROM.has(from) ? "joining" : null;
1372
1374
  case "back_to_prejoin":
@@ -1775,6 +1777,8 @@ var RPCS = {
1775
1777
  getOrCreateMeeting: "meet_get_or_create_meeting",
1776
1778
  /** Resolve a durable public link, before/during/after its scheduled time. */
1777
1779
  meetingBySlug: "meet_meeting_by_slug",
1780
+ /** The current run of a durable link (open / not started / ended + next start), no pass needed. */
1781
+ linkState: "meet_link_state",
1778
1782
  /*
1779
1783
  * ── S4 ADMISSION (CORE-DESIGN §2.4). Each returns the decided row; the caller then
1780
1784
  * sends the payload-free `mx.state.changed` hint. Authorized by `who_may_admit`.
@@ -2083,6 +2087,14 @@ function createMeetRepository(options) {
2083
2087
  if (response.error !== null) throw normalizeMeetError(response.error, operation);
2084
2088
  }
2085
2089
  }
2090
+ async function readLinkRun(slug) {
2091
+ try {
2092
+ const response = await db.rpc(RPCS.linkState, { p_slug: slug });
2093
+ return projectLinkRun(response.error === null ? response.data : null);
2094
+ } catch {
2095
+ return void 0;
2096
+ }
2097
+ }
2086
2098
  async function guard(operation, run) {
2087
2099
  let response = await run();
2088
2100
  if (response.error !== null) {
@@ -2484,11 +2496,12 @@ function createMeetRepository(options) {
2484
2496
  return projectMeeting(row);
2485
2497
  },
2486
2498
  async meetingBySlug(slug) {
2487
- const row = await guard(
2488
- "meet.meetingBySlug",
2489
- () => db.rpc(RPCS.meetingBySlug, { p_slug: slug })
2490
- );
2491
- return withRunNoteTaker(projectMeeting(row));
2499
+ const [row, linkRun] = await Promise.all([
2500
+ guard("meet.meetingBySlug", () => db.rpc(RPCS.meetingBySlug, { p_slug: slug })),
2501
+ readLinkRun(slug)
2502
+ ]);
2503
+ const record = withRunNoteTaker(projectMeeting(row));
2504
+ return linkRun === void 0 ? record : { ...record, linkRun };
2492
2505
  },
2493
2506
  async meeting(id) {
2494
2507
  const response = await db.from(TABLES.meetings).select(MEETING_COLUMNS).eq("id", id).single();
@@ -2677,6 +2690,15 @@ function snippetRuns(snippet) {
2677
2690
  if (last < snippet.length) runs.push({ text: snippet.slice(last), hit: false });
2678
2691
  return runs;
2679
2692
  }
2693
+ function projectLinkRun(value) {
2694
+ if (typeof value !== "object" || value === null) return void 0;
2695
+ const row = value;
2696
+ const state = row["state"];
2697
+ if (state !== "open" && state !== "not_started" && state !== "ended" && state !== "cancelled") return void 0;
2698
+ const reason = row["reason"] === "ended" || row["reason"] === "cancelled" ? row["reason"] : null;
2699
+ const nextStart = typeof row["next_start"] === "string" ? row["next_start"] : null;
2700
+ return { state, reason, nextStart };
2701
+ }
2680
2702
 
2681
2703
  // src/core/app-panel.ts
2682
2704
  function appPanelOf(meeting) {