palbase 0.26.0 → 0.28.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/README.md +12 -1
  2. package/dist/ai/index.js +2 -2
  3. package/dist/backend/engine.js +2 -2
  4. package/dist/backend/env.js +1 -1
  5. package/dist/backend/index.js +3 -3
  6. package/dist/backend/stack.js +1 -1
  7. package/dist/backend/test.js +2 -2
  8. package/dist/chunks/{GHQTIJT7.js → 2XAUD7E5.js} +2 -2
  9. package/dist/chunks/{EAHHUIQP.js → 36Q4EJBD.js} +1 -1
  10. package/dist/chunks/{4W2CWOGO.js → 3G43SAQ7.js} +1 -1
  11. package/dist/chunks/{V2OJIKUV.js → 53VJSMGY.js} +1 -1
  12. package/dist/chunks/5SSYP4TM.js +2 -0
  13. package/dist/chunks/{QUX35QKY.js → 7M5HEXJC.js} +2 -2
  14. package/dist/chunks/{CZMQEBC6.js → CQ2AKEKI.js} +2 -2
  15. package/dist/chunks/{HMQIA6DH.js → D5YY344U.js} +2 -2
  16. package/dist/chunks/{OTWMAAPL.js → DJE7B7X4.js} +2 -2
  17. package/dist/chunks/{4I34RRBK.js → DJIO7ZRV.js} +1 -1
  18. package/dist/chunks/{DVRO2E2S.js → EL7LGFXD.js} +2 -2
  19. package/dist/chunks/EXT5BO4H.js +22 -0
  20. package/dist/chunks/{RC4ZSGS2.js → FJWAFNAZ.js} +2 -2
  21. package/dist/chunks/{BN5FJ3YM.js → FXV6V457.js} +1 -1
  22. package/dist/chunks/{2LNRLAVP.js → GP56VUVJ.js} +2 -2
  23. package/dist/chunks/{5RWEOPF2.js → LIB2AHJU.js} +2 -2
  24. package/dist/chunks/{B4ZHHG4H.js → LTS573ZP.js} +2 -2
  25. package/dist/chunks/{SB36QYBM.js → MVXEPZPI.js} +2 -2
  26. package/dist/chunks/{DK2JMPU3.js → QUBQS6S5.js} +2 -2
  27. package/dist/chunks/{FBCZT7JT.js → RUQZFFRU.js} +2 -2
  28. package/dist/chunks/UYPJY7TK.js +2 -0
  29. package/dist/chunks/{UKRY3HRA.js → YZCJVWWC.js} +1 -1
  30. package/dist/chunks/{Q4E3WXGS.js → ZVQZVVBH.js} +1 -1
  31. package/dist/cli.js +135 -135
  32. package/dist/cloud/index.js +2 -2
  33. package/dist/refuse/ai.js +1 -1
  34. package/dist/refuse/backend.js +1 -1
  35. package/dist/refuse/cloud.js +1 -1
  36. package/dist/refuse/server.js +1 -1
  37. package/dist/server/index.js +2 -2
  38. package/dist/server/testing.js +2 -2
  39. package/dist/web/calls-ui.js +46 -0
  40. package/dist/web/index.js +2 -2
  41. package/dist/web/message.js +2 -2
  42. package/dist/web/palbe.js +2 -2
  43. package/dist/web/paywall.js +2 -2
  44. package/dist/web/push-sw.js +2 -2
  45. package/dist/web/ssr.js +2 -2
  46. package/dist/web/vite.js +2 -2
  47. package/package.json +7 -2
  48. package/types/cloud/src/generated/project.d.ts +1 -0
  49. package/types/internal/src/modules/calls.d.ts +810 -0
  50. package/types/internal/src/modules/events.d.ts +4 -3
  51. package/types/internal/src/modules/index.d.ts +1 -0
  52. package/types/internal/src/modules/messaging.d.ts +298 -15
  53. package/types/internal/src/modules/realtime.d.ts +1 -1
  54. package/types/server/src/server.d.ts +15 -0
  55. package/types/web/src/calls-ui/index.d.ts +71 -0
  56. package/types/web/src/calls.d.ts +274 -0
  57. package/types/web/src/client.d.ts +5 -0
  58. package/types/web/src/index.d.ts +1 -0
  59. package/types/web/src/messaging.d.ts +47 -6
  60. package/dist/chunks/72VOVUBT.js +0 -22
  61. package/dist/chunks/M5MRZQPV.js +0 -2
  62. package/dist/chunks/QUPZ6GF5.js +0 -2
@@ -0,0 +1,71 @@
1
+ import type { Call, CallSession, Calls } from '../calls.js';
2
+ /** Every word the screens show. */
3
+ export interface CallUITexts {
4
+ incomingVoice: string;
5
+ incomingVideo: string;
6
+ accept: string;
7
+ acceptVoiceOnly: string;
8
+ decline: string;
9
+ calling: string;
10
+ connecting: string;
11
+ reconnecting: string;
12
+ /** How the call ended for this device, by its endReason; `ended` for any other. */
13
+ declined: string;
14
+ missed: string;
15
+ busy: string;
16
+ hungUp: string;
17
+ canceled: string;
18
+ failed: string;
19
+ answeredElsewhere: string;
20
+ left: string;
21
+ ended: string;
22
+ }
23
+ /** What a screen reader says of what shows no words of its own. */
24
+ export interface CallUILabels {
25
+ /** The ringing sheet. */
26
+ incoming: string;
27
+ /** The call's view. */
28
+ call: string;
29
+ mute: string;
30
+ unmute: string;
31
+ cameraOn: string;
32
+ cameraOff: string;
33
+ switchCamera: string;
34
+ hangUp: string;
35
+ /** This device's camera. */
36
+ self: string;
37
+ }
38
+ /** The screens' colors, corners and font: CSS values, set as --pb-call-<name> on the root element. */
39
+ export interface CallUITheme {
40
+ accent?: string;
41
+ background?: string;
42
+ foreground?: string;
43
+ danger?: string;
44
+ /** A length; a number is pixels. */
45
+ radius?: string | number;
46
+ font?: string;
47
+ }
48
+ export interface CallUIOptions {
49
+ /** The element the screens are drawn in (positioned): over the whole page (the body) unless given. */
50
+ container?: HTMLElement;
51
+ texts?: Partial<CallUITexts>;
52
+ labels?: Partial<CallUILabels>;
53
+ /** The light and dark colors the system asks for, unless given. */
54
+ theme?: CallUITheme;
55
+ /** Added to the root element's classes. */
56
+ className?: string;
57
+ /** A soft ring while a sheet shows (true by default); silent where the page may not play sound yet. */
58
+ ringtone?: boolean;
59
+ /** Asked once for each call that rings: false leaves it to the app's own screen. */
60
+ incoming?(call: Call, session: CallSession): boolean;
61
+ /** An answer, a microphone or a camera that failed (the person refused the camera, the network). */
62
+ onError?(error: unknown, session: CallSession): void;
63
+ }
64
+ export interface CallUI {
65
+ /** Takes the screens away and stops listening; a call goes on. */
66
+ unmount(): void;
67
+ }
68
+ export declare const CALL_UI_TEXTS: Readonly<CallUITexts>;
69
+ export declare const CALL_UI_LABELS: Readonly<CallUILabels>;
70
+ /** Shows pb.calls' ringing calls and the call this page is in, until unmount. */
71
+ export declare function mountCallUI(calls: Calls, options?: CallUIOptions): CallUI;
@@ -0,0 +1,274 @@
1
+ import { calls as api } from '../../internal/src/modules/index.js';
2
+ /** A call as the module keeps it: its people, its state, how it ended. */
3
+ export type Call = api.Call;
4
+ /** A person (or the project's agent) in a call, as the call lists them. */
5
+ export type CallParticipant = api.Participant;
6
+ /** A page of calls, newest first. */
7
+ export type CallPage = api.CallPage;
8
+ type Listener = () => void;
9
+ /**
10
+ * Where a call is, as this device has it:
11
+ * - `calling` — the person called is being rung;
12
+ * - `incoming` — this person is rung; `invited` — asked into a call that does not ring (a huddle: join it);
13
+ * - `connecting` — answered, the media on its way; `connected`; `reconnecting` — the network dropped for a moment;
14
+ * - `elsewhere` — answered on another device or in another tab;
15
+ * - `ended` — over for this device (endReason says why).
16
+ */
17
+ export type CallPhase = 'calling' | 'incoming' | 'invited' | 'connecting' | 'connected' | 'reconnecting' | 'elsewhere' | 'ended';
18
+ /** Someone else in the call, and what is heard and seen of them. */
19
+ export interface RemoteParticipant {
20
+ /** Their user id — or, for the project's agent, bot:<identity>. */
21
+ userId: string;
22
+ name: string | null;
23
+ imageUrl: string | null;
24
+ bot: boolean;
25
+ /** Their audio and video: one stream for the whole call, whichever way the media flows. */
26
+ stream: MediaStream;
27
+ /** Their microphone is heard. */
28
+ audio: boolean;
29
+ /** Their camera is seen. */
30
+ video: boolean;
31
+ }
32
+ export interface CallState {
33
+ /** The call as the module last said it (the highest version heard). */
34
+ call: Call;
35
+ /** This person, as the call lists them. */
36
+ me: CallParticipant | null;
37
+ phase: CallPhase;
38
+ /** This person rang (or started the group). */
39
+ outgoing: boolean;
40
+ /** Between the two devices, or through the media server. */
41
+ mode: 'p2p' | 'sfu';
42
+ /** This device's microphone and camera, while it is in the call. */
43
+ local: MediaStream | null;
44
+ microphone: boolean;
45
+ camera: boolean;
46
+ /** The others in the call. */
47
+ remote: RemoteParticipant[];
48
+ /** Why it ended for this device: the call's end_reason, `left` (this person left a group that goes on), `declined`, `missed`, `answered_elsewhere`. */
49
+ endReason: string | null;
50
+ /** The last thing that went wrong with this device's media (a camera refused, the media server not reached). */
51
+ error: Error | null;
52
+ }
53
+ export interface StartCallOptions {
54
+ /** A video call; a voice call unless true (pb.calls.video and pb.calls.voice say it). */
55
+ video?: boolean;
56
+ /** Ring the people asked (true by default); false: a group call they join (a huddle). */
57
+ ring?: boolean;
58
+ /** A group call even with one person asked: others may be asked later. */
59
+ group?: boolean;
60
+ /** The conversation it is made from: its members alone may be called, and it keeps the call as a message. */
61
+ conversationId?: string;
62
+ /** The app's own words about the call, shown to those rung (32 strings, 2 KiB at most). */
63
+ metadata?: Record<string, string>;
64
+ /** The name and picture shown to those rung; else the caller's messaging profile's. */
65
+ callerName?: string;
66
+ callerImageUrl?: string;
67
+ /** This call's media through the relay alone (CallsOptions.forceRelay, for one call). */
68
+ forceRelay?: boolean;
69
+ /** A microphone (and camera) stream the app opened already; left open when the call ends. */
70
+ media?: MediaStream;
71
+ }
72
+ export interface AnswerOptions {
73
+ /** Send video (the call's own kind unless said): a video call answered by voice, or a voice call with the camera on. */
74
+ video?: boolean;
75
+ forceRelay?: boolean;
76
+ media?: MediaStream;
77
+ }
78
+ export interface HistoryOptions {
79
+ /** 1 to 100; 20 when absent. */
80
+ limit?: number;
81
+ /** The page after the one that handed out this cursor (next_cursor). */
82
+ cursor?: string;
83
+ /** Only the calls the person missed (or was busy for). */
84
+ missed?: boolean;
85
+ state?: 'ringing' | 'active' | 'ended';
86
+ }
87
+ /** The browser's media, as calls uses it: a test's or a runtime's own. */
88
+ export interface CallsRTC {
89
+ RTCPeerConnection: typeof RTCPeerConnection;
90
+ MediaStream: typeof MediaStream;
91
+ getUserMedia(constraints: MediaStreamConstraints): Promise<MediaStream>;
92
+ }
93
+ export interface CallsOptions {
94
+ /**
95
+ * Every call's media through the relay (iceTransportPolicy relay), never straight between the devices: neither
96
+ * learns the other's address, at the price of a hop. The project's relay_all setting says it for every app.
97
+ */
98
+ forceRelay?: boolean;
99
+ /** The others' voices play by themselves (true by default): false leaves each RemoteParticipant's stream to the app. */
100
+ playAudio?: boolean;
101
+ }
102
+ /**
103
+ * One call as this device has it: its state to draw (subscribe), and what the person does in it. Made by
104
+ * pb.calls.start/voice/video/join, or heard (pb.calls.onIncoming).
105
+ */
106
+ export declare class CallSession {
107
+ readonly id: string;
108
+ private c;
109
+ private call;
110
+ private snapshot;
111
+ private readonly listeners;
112
+ /** This tab acts in the call: it made, answered or joined it here. */
113
+ private owned;
114
+ /** This tab is answering or joining it: what the module says meanwhile does not end it. */
115
+ private entering;
116
+ private phase;
117
+ private endReason;
118
+ private error;
119
+ private relay;
120
+ private local;
121
+ private tracks;
122
+ /** The tracks this device opened, stopped when the call is done with them; an app's own stream is left open. */
123
+ private readonly opened;
124
+ private mic;
125
+ private facing;
126
+ private link;
127
+ private linking;
128
+ private linkState;
129
+ private sdpSent;
130
+ private answered;
131
+ private answer;
132
+ private inbox;
133
+ private lastSeq;
134
+ private readonly seen;
135
+ private readonly sentSeqs;
136
+ private room;
137
+ private joiningRoom;
138
+ private roomState;
139
+ private readonly streams;
140
+ private readonly via;
141
+ private readonly mutedInRoom;
142
+ private readonly players;
143
+ private sink;
144
+ private quieted;
145
+ private heartbeat;
146
+ private poll;
147
+ private done;
148
+ get state(): CallState;
149
+ /** Listens to every change of state; returns the unsubscribe. */
150
+ subscribe(listener: Listener): () => void;
151
+ /** Answers the call on this device (the first of the person's devices to answer has it). */
152
+ accept(o?: AnswerOptions): Promise<void>;
153
+ /** Comes into a group call this person was asked to (or was in before). */
154
+ join(o?: AnswerOptions): Promise<void>;
155
+ /** Turns the call down on every device of this person's: a direct call ends; a group goes on, and may still be joined. */
156
+ decline(): Promise<void>;
157
+ /** Hangs up (or, while it rings, cancels): a direct call ends for both; a group goes on for the others. */
158
+ leave(): Promise<void>;
159
+ /** Asks more people in (ringing them unless ring is false): a direct call becomes a group, going on. */
160
+ invite(userIds: string | string[], o?: {
161
+ ring?: boolean;
162
+ }): Promise<void>;
163
+ /** The microphone heard (true) or muted. */
164
+ setMicrophone(on: boolean): Promise<void>;
165
+ /** The camera on or off: off, it is closed (its light goes out); on, opened again — a voice call's too. */
166
+ setCamera(on: boolean): Promise<void>;
167
+ /** Another camera: the one named (a videoinput's deviceId), or the other facing one (front, back). */
168
+ switchCamera(deviceId?: string): Promise<void>;
169
+ /** Where the others' voices play: an audiooutput's deviceId (a browser that can choose one: setSinkId). */
170
+ setAudioOutput(deviceId: string): Promise<void>;
171
+ /** Reads the call as it is now. */
172
+ refresh(): Promise<void>;
173
+ private me;
174
+ /** What the call now means for this device, and the media that follows. */
175
+ private derive;
176
+ private mediaPhase;
177
+ private enter;
178
+ /** This device's microphone (and camera): the app's stream, or opened here. */
179
+ private open;
180
+ private camera;
181
+ /** The camera's track now (null: off), wherever the media flows. */
182
+ private putVideo;
183
+ private toPeer;
184
+ /** Sends a signal once the call is answered (nothing leaves before): an offer or answer in order, candidates after it. */
185
+ private signal;
186
+ private take;
187
+ /** A signal between the last one handled and this one that is neither handled nor this device's own: missed. */
188
+ private gapBefore;
189
+ private fetchSignals;
190
+ private handle;
191
+ /** The connection between the devices is gone: what came through it goes too. */
192
+ private unlink;
193
+ private toRoom;
194
+ private streamOf;
195
+ private heard;
196
+ private gone;
197
+ private play;
198
+ private beat;
199
+ private stillHere;
200
+ private end;
201
+ /** The tracks this device opened are closed: the camera's light goes out. */
202
+ private release;
203
+ private stopIfOpened;
204
+ /** Its notification goes, once: the call no longer rings here. */
205
+ private quiet;
206
+ private failed;
207
+ private refusal;
208
+ private refused;
209
+ private changed;
210
+ private remoteOf;
211
+ }
212
+ /** pb.calls: the signed-in person's calls. */
213
+ export declare class Calls {
214
+ /** This install's device id: the one its pushes are registered with (web-<installation id>). */
215
+ readonly deviceId: string;
216
+ private readonly transportFor;
217
+ private readonly session;
218
+ private readonly socket;
219
+ private readonly ref;
220
+ private readonly opts;
221
+ private readonly beacon;
222
+ private user;
223
+ private api;
224
+ private channel;
225
+ private off;
226
+ private readonly sessions;
227
+ private readonly incoming;
228
+ private readonly entered;
229
+ private workerHeard;
230
+ /** The call this page is in (made, answered or joined here), or null. */
231
+ get current(): CallSession | null;
232
+ /**
233
+ * Calls one person (a direct call: their devices ring) or several (a group call), from this device — its
234
+ * microphone (and camera) asked for first: a refusal rings no one. A call to someone calling this person this moment
235
+ * is that call, answered. Refused with a PalbaseError: `not_allowed` (403), `in_another_call` (409),
236
+ * `too_many_calls` or `quota_exceeded` (429), `invalid_user_ids` or `call_full` (400).
237
+ */
238
+ start(userIds: string | string[], o?: StartCallOptions): Promise<CallSession>;
239
+ /** A voice call. */
240
+ voice(userIds: string | string[], o?: Omit<StartCallOptions, 'video'>): Promise<CallSession>;
241
+ /** A video call. */
242
+ video(userIds: string | string[], o?: Omit<StartCallOptions, 'video'>): Promise<CallSession>;
243
+ /** Comes into a group call this person was asked to — a huddle, one they declined or left — on this device. */
244
+ join(callId: string, o?: AnswerOptions): Promise<CallSession>;
245
+ /**
246
+ * Listens for calls that ring this person (and group calls they are asked to: phase `invited`), while the page is
247
+ * open — and those ringing as it opens (a tap on the call's notification). Returns the unsubscribe.
248
+ */
249
+ onIncoming(listener: (call: CallSession) => void): () => void;
250
+ /** Listens for each call this page comes into — made, answered or joined here (a call UI follows them). Returns the unsubscribe. */
251
+ onCall(listener: (call: CallSession) => void): () => void;
252
+ /** This person's calls, newest first, with how each went for them (their participant's state: `missed` among them). */
253
+ history(o?: HistoryOptions): Promise<CallPage>;
254
+ /** A call of this person's, as it is now. */
255
+ get(callId: string): Promise<Call>;
256
+ /**
257
+ * Follows the signed-in person's calls (start, join and onIncoming do it themselves): their channel, and the calls
258
+ * ringing them now. Rejects when no one is signed in.
259
+ */
260
+ ready(): Promise<void>;
261
+ private stop;
262
+ private unfollow;
263
+ private follow;
264
+ /** The calls ringing this person now: a page opened by the call's notification, or a channel that was down. */
265
+ private ringing;
266
+ /** A tap on a call's notification, told by the service worker (palbase/web/push-sw.js). */
267
+ private listenToWorker;
268
+ private heardCall;
269
+ private tell;
270
+ /** The session of a call: the one kept, or a new one (entering: this device is about to answer or join it). */
271
+ private sessionOf;
272
+ private rtc;
273
+ }
274
+ export {};
@@ -11,6 +11,7 @@ import { Purchases } from './purchases.js';
11
11
  import { type ChatToolCall } from './chat.js';
12
12
  import { Flags } from './flags.js';
13
13
  import { Messaging, type MessagingOptions } from './messaging.js';
14
+ import { Calls, type CallsOptions } from './calls.js';
14
15
  export interface ClientOptions {
15
16
  /** The project's address: https://<ref>.<domain> */
16
17
  url: string;
@@ -71,6 +72,8 @@ export interface ClientOptions {
71
72
  language?: string | readonly string[];
72
73
  /** What the device keeps of the signed-in person's conversations (pb.messaging): dropped on sign-out unless keepOnSignOut. */
73
74
  messaging?: MessagingOptions;
75
+ /** How the signed-in person's calls go (pb.calls): every call through the relay (forceRelay), voices played by themselves (playAudio). */
76
+ calls?: CallsOptions;
74
77
  }
75
78
  /**
76
79
  * The app's client. A backend's generated Palbe module (palbase apps:sync)
@@ -98,6 +101,8 @@ export interface PalbaseClient {
98
101
  flags: Flags;
99
102
  /** The signed-in person's conversations — direct ones and groups — kept up to date, on the device and live. */
100
103
  messaging: Messaging;
104
+ /** The signed-in person's voice and video calls: made, rung, answered — one to one or in a group. */
105
+ calls: Calls;
101
106
  /** The language every request says from now on (ClientOptions.language); null for the browser's own. */
102
107
  setLanguage(language: string | readonly string[] | null): void;
103
108
  /**
@@ -11,6 +11,7 @@ export { Purchases, redemptionToken, type CheckoutSource, type CustomerInfo, typ
11
11
  export { Notify, WebPush, type PushPermission, type PushSubscribeOptions } from './notify.js';
12
12
  export { Flags, type FlagSource, type FlagsListener } from './flags.js';
13
13
  export { ConversationList, ConversationView, DeletedGroupList, indexedDBKeyValue, Messaging, ScheduledList, ThreadView, type Conversation, type ConversationMatch, type ConversationViewState, type ConversationListState, type DeletedGroup, type DeletedGroupListState, type Entry, type Hit, type Member, type Message, type MessagingOptions, type MyProfile, type Observed, type OpenedFile, type OutboxItem, type OutgoingFile, type Profile, type ScheduledMessage, type SearchHit, type SearchMatch, type SearchOptions, type SearchResults, type SendOptions, type ThreadState, type ThreadViewState, } from './messaging.js';
14
+ export { Calls, CallSession, type AnswerOptions, type Call, type CallPage, type CallParticipant, type CallPhase, type CallsOptions, type CallState, type HistoryOptions, type RemoteParticipant, type StartCallOptions, } from './calls.js';
14
15
  export { Inbox, type InboxItem, type InboxListOptions, type InboxPage, type InboxView, type InboxViewOptions } from './inbox.js';
15
16
  export { InApp, SESSION_START, type InAppOptions } from './inapp.js';
16
17
  export type { Paywall, PaywallRenderOptions } from './paywall/placement.js';
@@ -11,6 +11,7 @@ export type Profile = api.Profile;
11
11
  export type ScheduledMessage = api.ScheduledMessage;
12
12
  export type ThreadState = api.ThreadState;
13
13
  export type SearchMatch = api.SearchMatch;
14
+ export type OpenGroup = api.OpenGroup;
14
15
  export type { DeletedGroup, Entry, Hit, OutboxItem } from '../../internal/src/messaging/index.js';
15
16
  export interface MessagingOptions {
16
17
  /**
@@ -117,6 +118,8 @@ export interface SearchOptions {
117
118
  by?: 'words' | 'meaning';
118
119
  /** Search one conversation of the person's only. */
119
120
  conversationId?: string;
121
+ /** Search the conversations of one space only (org:<id>): a place of the app's they belong to. */
122
+ space?: string;
120
123
  /** How many messages a page holds (1 to 50; 20 when absent). */
121
124
  limit?: number;
122
125
  /** The page after the one that handed out this cursor (nextCursor): a search by words alone. */
@@ -256,8 +259,13 @@ export declare class Messaging {
256
259
  private seat;
257
260
  private typed;
258
261
  private tell;
259
- /** The person's conversations, the latest first, kept up to date. */
260
- conversations(): ConversationList;
262
+ /**
263
+ * The person's conversations, the latest first, kept up to date — those of some spaces only (spaces: the places of
264
+ * the app's they belong to, as org:<id>), when it names any.
265
+ */
266
+ conversations(opts?: {
267
+ spaces?: string[];
268
+ }): ConversationList;
261
269
  /**
262
270
  * The groups the person was in that someone deleted, kept up to date while the person may still report them
263
271
  * (reportableUntil, 14 days after), the latest to stop first: report() names one by its id, no message needed. A
@@ -273,15 +281,27 @@ export declare class Messaging {
273
281
  conversation(conversationId: string, opts?: {
274
282
  at?: string;
275
283
  }): ConversationView;
276
- /** The direct conversation with someone — the one there is, or a new one. */
277
- direct(userId: string): Promise<ConversationView>;
278
- /** A new group, the person its owner. */
284
+ /**
285
+ * The direct conversation with someone — the one there is, or a new one — in a space (org:<id>): the two have one in
286
+ * each space, and one with none. The project's hook is asked, the space named.
287
+ */
288
+ direct(userId: string, opts?: {
289
+ space?: string;
290
+ }): Promise<ConversationView>;
291
+ /**
292
+ * A new group, the person its owner — in a space (org:<id>), and open (found in the space's open groups and joined
293
+ * by whom the project's hook lets: openGroups, join) or closed (the default: joined when someone adds you). An open
294
+ * group names its space ('space_required'), and the project's hook is asked whether the person may make one there
295
+ * ('open_group'; refused: 'not_allowed').
296
+ */
279
297
  group(input: {
280
298
  title: string;
281
299
  memberIds?: string[];
282
300
  description?: string;
283
301
  photo?: string;
284
302
  settings?: api.GroupSettings;
303
+ space?: string;
304
+ visibility?: 'open' | 'closed';
285
305
  }): Promise<{
286
306
  conversation: ConversationView;
287
307
  notAdded: api.NotAdded[];
@@ -301,8 +321,26 @@ export declare class Messaging {
301
321
  * means instead, the nearest first, each with its score: one page, no conversations by name. Opened as any find is.
302
322
  */
303
323
  search(query: string, opts?: SearchOptions): Promise<SearchResults>;
304
- /** The person's conversations whose name says every word asked: a group's title, the other person's name. */
324
+ /** The person's conversations (of a space, when one is named) whose name says every word asked: a group's title, the other person's name. */
305
325
  private named;
326
+ /**
327
+ * A space's open groups (org:<id>), the oldest first, a page at a time — each with whether the person is in it
328
+ * (joined) — when the project's hook lets them find them; refused otherwise (a PalbaseError, code 'not_allowed').
329
+ */
330
+ openGroups(space: string, opts?: {
331
+ limit?: number;
332
+ cursor?: string;
333
+ }): Promise<{
334
+ items: OpenGroup[];
335
+ nextCursor: string | null;
336
+ }>;
337
+ /**
338
+ * Joins an open group by themselves — when the project's hook lets them and it has room — and answers it, the person
339
+ * in it. Joining one they are in answers it as it is. Refused (a PalbaseError) when the hook does not let them
340
+ * ('not_allowed'), an admin removed them ('removed'), it is read-only ('read_only') or full ('group_full'); a closed
341
+ * group is not found.
342
+ */
343
+ join(conversationId: string): Promise<ConversationView>;
306
344
  /** The person's messages scheduled for later, kept up to date. */
307
345
  scheduled(): ScheduledList;
308
346
  /** The threads the person follows, the latest answered first. */
@@ -373,6 +411,9 @@ declare abstract class View<S> implements Observed<S> {
373
411
  protected abstract read(): S;
374
412
  }
375
413
  export declare class ConversationList extends View<ConversationListState> {
414
+ /** The spaces it is narrowed to (none: every conversation). */
415
+ readonly spaces: readonly string[];
416
+ constructor(m: Messaging, spaces?: readonly string[]);
376
417
  protected touches(t: Touched): boolean;
377
418
  protected read(): ConversationListState;
378
419
  }