palbase 0.19.1 → 0.20.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 (53) hide show
  1. package/dist/ai/index.js +2 -2
  2. package/dist/backend/engine.js +2 -2
  3. package/dist/backend/env.js +1 -1
  4. package/dist/backend/index.js +3 -3
  5. package/dist/backend/stack.js +1 -1
  6. package/dist/backend/test.js +2 -2
  7. package/dist/chunks/{MW3TKB25.js → 2NYI4FOR.js} +2 -2
  8. package/dist/chunks/{E64JU3BI.js → 45465257.js} +2 -2
  9. package/dist/chunks/{33IVA4BF.js → 4UGIL34D.js} +2 -2
  10. package/dist/chunks/{QFSDHCVW.js → 5QSFOMN7.js} +2 -2
  11. package/dist/chunks/{M3ISZUMT.js → 6TW5HR5D.js} +1 -1
  12. package/dist/chunks/{UXROASPM.js → 7BSKXUEV.js} +2 -2
  13. package/dist/chunks/{6BHXBWO2.js → BSJV6PEL.js} +1 -1
  14. package/dist/chunks/{PAYTQB5N.js → CFJYJRJ7.js} +2 -2
  15. package/dist/chunks/{7KRALA6Q.js → CGTOJ44L.js} +1 -1
  16. package/dist/chunks/{BCTD3FJ7.js → DUO4FFKV.js} +2 -2
  17. package/dist/chunks/{BNMHHWXR.js → ILHFQK3J.js} +1 -1
  18. package/dist/chunks/KGAMXI25.js +2 -0
  19. package/dist/chunks/{UFED6IQR.js → KSRRQWGG.js} +2 -2
  20. package/dist/chunks/{ZX4XWAGN.js → LN7FO4IE.js} +2 -2
  21. package/dist/chunks/{V2CPPIF7.js → MPCXNC4L.js} +1 -1
  22. package/dist/chunks/{WJYO5EHR.js → O65ATC5C.js} +2 -2
  23. package/dist/chunks/{SO7CPQKM.js → Q6OD5IUC.js} +1 -1
  24. package/dist/chunks/{I6XSBSCX.js → U3U53UJF.js} +1 -1
  25. package/dist/chunks/{Y6ICMAUF.js → UE4A6DEG.js} +2 -2
  26. package/dist/chunks/{YAVDYP2M.js → W4JKOGHG.js} +3 -3
  27. package/dist/chunks/{ZNUDS44B.js → WXDISYY6.js} +2 -2
  28. package/dist/chunks/{ETIZ76MU.js → X6Y7MMBI.js} +2 -2
  29. package/dist/chunks/{2565R445.js → ZYBPLNPD.js} +2 -2
  30. package/dist/cli.js +4 -4
  31. package/dist/cloud/index.js +2 -2
  32. package/dist/refuse/ai.js +1 -1
  33. package/dist/refuse/backend.js +1 -1
  34. package/dist/refuse/cloud.js +1 -1
  35. package/dist/refuse/server.js +1 -1
  36. package/dist/server/index.js +2 -2
  37. package/dist/server/testing.js +2 -2
  38. package/dist/web/index.js +2 -2
  39. package/dist/web/message.js +2 -2
  40. package/dist/web/palbe.js +2 -2
  41. package/dist/web/paywall.js +2 -2
  42. package/dist/web/push-sw.js +1 -1
  43. package/dist/web/ssr.js +2 -2
  44. package/dist/web/vite.js +2 -2
  45. package/package.json +2 -2
  46. package/types/internal/src/messaging/index.d.ts +1 -0
  47. package/types/internal/src/messaging/search.d.ts +19 -0
  48. package/types/internal/src/modules/ai.d.ts +3 -3
  49. package/types/internal/src/modules/machines.d.ts +28 -2
  50. package/types/internal/src/modules/messaging.d.ts +69 -2
  51. package/types/web/src/index.d.ts +1 -1
  52. package/types/web/src/messaging.d.ts +119 -9
  53. package/dist/chunks/MZWR5LM3.js +0 -2
@@ -798,6 +798,10 @@ export type MessagePage = {
798
798
  * The messages.
799
799
  */
800
800
  data: Message[];
801
+ /**
802
+ * The cursor to read on toward the newest (after); absent when the page reaches it. Only a page opened at a message (around), or read forward (after), has one.
803
+ */
804
+ newer_cursor?: string;
801
805
  /**
802
806
  * The next page's cursor; absent on the last page.
803
807
  */
@@ -1234,6 +1238,58 @@ export type ScheduledPage = {
1234
1238
  */
1235
1239
  next_cursor?: string;
1236
1240
  };
1241
+ /**
1242
+ * A message a search found, and where it says what was asked.
1243
+ */
1244
+ export type SearchHit = {
1245
+ /**
1246
+ * Where it says a word of the search, in the order said.
1247
+ */
1248
+ matches: SearchMatch[];
1249
+ message: Message;
1250
+ };
1251
+ /**
1252
+ * Where a message found says a word of the search: in its text, or a file's name. offset and length are in UTF-16 code units, as mentions are.
1253
+ */
1254
+ export type SearchMatch = {
1255
+ /**
1256
+ * The file whose name it is (attachment_name).
1257
+ */
1258
+ attachment_id?: string;
1259
+ /**
1260
+ * Where: `text`, or `attachment_name` (a file's name).
1261
+ */
1262
+ field: "text" | "attachment_name";
1263
+ /**
1264
+ * How long what was asked is (the word's beginning that matched), in UTF-16 code units.
1265
+ */
1266
+ length: number;
1267
+ /**
1268
+ * Where the word starts, in UTF-16 code units.
1269
+ */
1270
+ offset: number;
1271
+ };
1272
+ /**
1273
+ * A page of what a search found, the newest first, with the conversations it is in and the people it shows — its writers, and the other person of a direct conversation — each once.
1274
+ */
1275
+ export type SearchPage = {
1276
+ /**
1277
+ * The conversations of the messages found, each once, as the reader's list shows them.
1278
+ */
1279
+ conversations: Conversation[];
1280
+ /**
1281
+ * The messages found.
1282
+ */
1283
+ data: SearchHit[];
1284
+ /**
1285
+ * The next page's cursor; absent on the last page. A page may hold fewer than limit — even none — while there is more to read: read on while next_cursor is there.
1286
+ */
1287
+ next_cursor?: string;
1288
+ /**
1289
+ * The people the page shows, each once: who wrote what was found, and the other person of a direct conversation. Someone with no profile is not here.
1290
+ */
1291
+ profiles: Profile[];
1292
+ };
1237
1293
  /**
1238
1294
  * A message to send.
1239
1295
  */
@@ -2048,7 +2104,7 @@ export declare function client(t: Transport): {
2048
2104
  /**
2049
2105
  * A conversation's messages
2050
2106
  *
2051
- * The conversation's own timeline as the reader sees it, the newest first, a page at a time; a message removed is there, said removed.
2107
+ * The conversation's own timeline as the reader sees it, the newest first, a page at a time; a message removed is there, said removed. Paged back from the newest (cursor: next_cursor), or opened at a message (around: the page holds it, with what came before and after it) and paged forward from there (after: newer_cursor) — a search's find shown where it was said. cursor, after and around are one at a time.
2052
2108
  */
2053
2109
  listMessages(input: {
2054
2110
  path: {
@@ -2056,7 +2112,9 @@ export declare function client(t: Transport): {
2056
2112
  };
2057
2113
  query?: {
2058
2114
  limit?: number; /** The cursor a page handed out (next_cursor). */
2059
- cursor?: string;
2115
+ cursor?: string; /** Open the timeline at this message: the page holds it, about half the page before it and half after (next_cursor pages back, newer_cursor forward). A thread's answer is read in its thread (`in_thread`). */
2116
+ around?: string; /** The cursor a page handed out to read on toward the newest (newer_cursor). */
2117
+ after?: string;
2060
2118
  }; /** Stops the call: the request in flight, a wait before a retry, a proof-of-work being solved. */
2061
2119
  signal?: AbortSignal;
2062
2120
  }): Promise<Reply<200, MessagePage>>;
@@ -2328,6 +2386,15 @@ export declare function client(t: Transport): {
2328
2386
  body: UpdateScheduled; /** Stops the call: the request in flight, a wait before a retry, a proof-of-work being solved. */
2329
2387
  signal?: AbortSignal;
2330
2388
  }): Promise<Reply<200, ScheduledMessage>>;
2389
+ searchMessages(input: {
2390
+ query: {
2391
+ q: string; /** Search one conversation of the reader's only. */
2392
+ conversation_id?: string; /** How many (1 to 50; 20 when absent). */
2393
+ limit?: number; /** The cursor a page handed out (next_cursor). */
2394
+ cursor?: string;
2395
+ }; /** Stops the call: the request in flight, a wait before a retry, a proof-of-work being solved. */
2396
+ signal?: AbortSignal;
2397
+ }): Promise<Reply<200, SearchPage>>;
2331
2398
  /**
2332
2399
  * How the project runs its conversations
2333
2400
  *
@@ -10,7 +10,7 @@ export { connectVoice, type StartedVoice, type VoiceConnection, type VoiceOption
10
10
  export { Purchases, redemptionToken, type CheckoutSource, type CustomerInfo, type CustomerInfoListener, type GrantInfo, type MergeGrant, type OfferView, type Offerings, type Redeemed, type RedemptionLink, } from './purchases.js';
11
11
  export { Notify, WebPush, type PushPermission, type PushSubscribeOptions } from './notify.js';
12
12
  export { Flags, type FlagSource, type FlagsListener } from './flags.js';
13
- export { ConversationList, ConversationView, DeletedGroupList, indexedDBKeyValue, Messaging, ScheduledList, ThreadView, type Conversation, type ConversationViewState, type ConversationListState, type DeletedGroup, type DeletedGroupListState, type Entry, type Member, type Message, type MessagingOptions, type MyProfile, type Observed, type OpenedFile, type OutboxItem, type OutgoingFile, type Profile, type ScheduledMessage, type SendOptions, type ThreadState, type ThreadViewState, } from './messaging.js';
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
14
  export { Inbox, type InboxItem, type InboxListOptions, type InboxPage, type InboxView, type InboxViewOptions } from './inbox.js';
15
15
  export { InApp, SESSION_START, type InAppOptions } from './inapp.js';
16
16
  export type { Paywall, PaywallRenderOptions } from './paywall/placement.js';
@@ -1,5 +1,5 @@
1
1
  import { messaging as api } from '../../internal/src/modules/index.js';
2
- import { Engine, type DeletedGroup, type Entry, type KeyValue, type OutboxItem, type Touched } from '../../internal/src/messaging/index.js';
2
+ import { Engine, type DeletedGroup, type Entry, type Hit, type KeyValue, type OutboxItem, type Touched } from '../../internal/src/messaging/index.js';
3
3
  import { type Fetch, type Transport } from '../../internal/src/transport.js';
4
4
  import { type SessionManager } from './session.js';
5
5
  import type { RealtimeSocket } from './socket.js';
@@ -10,7 +10,8 @@ export type MyProfile = api.MyProfile;
10
10
  export type Profile = api.Profile;
11
11
  export type ScheduledMessage = api.ScheduledMessage;
12
12
  export type ThreadState = api.ThreadState;
13
- export type { DeletedGroup, Entry, OutboxItem } from '../../internal/src/messaging/index.js';
13
+ export type SearchMatch = api.SearchMatch;
14
+ export type { DeletedGroup, Entry, Hit, OutboxItem } from '../../internal/src/messaging/index.js';
14
15
  export interface MessagingOptions {
15
16
  /**
16
17
  * What the device keeps of a person's conversations when they sign out:
@@ -80,18 +81,74 @@ export interface DeletedGroupListState {
80
81
  }
81
82
  export interface ConversationViewState {
82
83
  conversation: Conversation | null;
83
- /** Its timeline: its messages, the oldest first, then what is on its way. */
84
+ /**
85
+ * Its timeline: its messages, the oldest first, then what is on its way. Opened at a message away from the newest
86
+ * (conversation(id, { at })), the stretch around it — what is on its way shows once it reaches the newest; nothing
87
+ * while the stretch is read (it is read once the view is subscribed), never the newest in the message's place.
88
+ */
84
89
  entries: Entry[];
85
90
  members: Member[];
86
91
  /** Who is typing now, by user id. */
87
92
  typing: string[];
88
93
  /** Older messages are there to read (loadEarlier). */
89
94
  hasEarlier: boolean;
95
+ /** Newer messages are there to read before the newest (loadLater): opened at a message away from it. */
96
+ hasLater: boolean;
97
+ /** The message it was opened at — what the app scrolls to and marks; null when opened at the newest. */
98
+ focus: string | null;
90
99
  }
91
100
  export interface ThreadViewState {
92
101
  root: Message | null;
93
102
  entries: Entry[];
94
103
  thread: ThreadState | null;
104
+ /** The answer it was opened at (thread(…, { at })); null otherwise. */
105
+ focus: string | null;
106
+ }
107
+ export interface SearchOptions {
108
+ /** Search one conversation of the person's only. */
109
+ conversationId?: string;
110
+ /** How many messages a page holds (1 to 50; 20 when absent). */
111
+ limit?: number;
112
+ /** The page after the one that handed out this cursor (nextCursor). */
113
+ cursor?: string;
114
+ }
115
+ /** A message a search found, with what the app draws it with and where it opens. */
116
+ export interface SearchHit {
117
+ message: Message;
118
+ /** The conversation it is in. */
119
+ conversation: Conversation;
120
+ /** The conversation's name: a group's title, the other person's name (null when they have none). */
121
+ title: string | null;
122
+ /** A group's photo, the other person's image. */
123
+ photo: string | null;
124
+ /** Who wrote it (null: the project's server, or someone with no profile). */
125
+ sender: Profile | null;
126
+ /** The other person of a direct conversation. */
127
+ peer: Profile | null;
128
+ /** Where it says what was asked: its text, or a file's name (UTF-16 code units). */
129
+ matches: SearchMatch[];
130
+ /**
131
+ * The thread it answers in, when its conversation's timeline does not show it: open it with
132
+ * thread(conversation.id, threadRootId, { at: message.id }); null — open conversation(conversation.id, { at: message.id }).
133
+ */
134
+ threadRootId: string | null;
135
+ }
136
+ /** A conversation of the person's whose name says what was asked. */
137
+ export interface ConversationMatch {
138
+ conversation: Conversation;
139
+ title: string | null;
140
+ photo: string | null;
141
+ peer: Profile | null;
142
+ /** Where its title says what was asked (UTF-16 code units). */
143
+ matches: Hit[];
144
+ }
145
+ export interface SearchResults {
146
+ /** The person's conversations whose name says every word asked, the latest first — on the first page alone. */
147
+ conversations: ConversationMatch[];
148
+ /** The messages found, the newest first. */
149
+ messages: SearchHit[];
150
+ /** The next page's cursor (search(query, { cursor })); null on the last. */
151
+ nextCursor: string | null;
95
152
  }
96
153
  /** Where a browser keeps it: IndexedDB, one object store of each person's state. */
97
154
  export declare function indexedDBKeyValue(name?: string): KeyValue | null;
@@ -125,6 +182,9 @@ export declare class Messaging {
125
182
  private saving;
126
183
  private readonly reopeners;
127
184
  private readonly incoming;
185
+ private readonly windows;
186
+ /** People's profiles read for a search (a direct conversation's name is the other person's), and when. */
187
+ private readonly people;
128
188
  private readonly session;
129
189
  private readonly socket;
130
190
  private readonly ref;
@@ -154,6 +214,12 @@ export declare class Messaging {
154
214
  private heardLive;
155
215
  /** Applies what changed to the person's conversations — to e's alone: what came for one who is gone goes nowhere. */
156
216
  private changed;
217
+ /** What changed, applied to the stretches read around a message too. */
218
+ private toWindows;
219
+ /** Messages put in a stretch: each goes when its time is up, as the timeline's do. */
220
+ private putWindow;
221
+ /** Runs take on each stretch of a conversation; answers whether any changed. */
222
+ private fromWindows;
157
223
  /** What follows a change: timers to take messages away, deliveries told, the device's copy saved. */
158
224
  private after;
159
225
  /** A message whose time is up goes from the device at once: the server says so too, a moment after. */
@@ -181,8 +247,14 @@ export declare class Messaging {
181
247
  * the word came (on the deleter's own device, now and then, the group the person deleted).
182
248
  */
183
249
  deletedGroups(): DeletedGroupList;
184
- /** A conversation of the person's, kept up to date: its timeline, its members, who is typing. */
185
- conversation(conversationId: string): ConversationView;
250
+ /**
251
+ * A conversation of the person's, kept up to date: its timeline, its members, who is typing. Opened at a message
252
+ * (at — a search's find), its timeline is the stretch around it, focus the message: loadEarlier and loadLater read
253
+ * on from there, and once it reaches the newest it is the conversation's timeline again.
254
+ */
255
+ conversation(conversationId: string, opts?: {
256
+ at?: string;
257
+ }): ConversationView;
186
258
  /** The direct conversation with someone — the one there is, or a new one. */
187
259
  direct(userId: string): Promise<ConversationView>;
188
260
  /** A new group, the person its owner. */
@@ -196,8 +268,20 @@ export declare class Messaging {
196
268
  conversation: ConversationView;
197
269
  notAdded: api.NotAdded[];
198
270
  }>;
199
- /** A thread: a message's answers, kept up to date. */
200
- thread(conversationId: string, rootId: string): ThreadView;
271
+ /** A thread: a message's answers, kept up to date — opened at an answer (at, a search's find), read on until it is there. */
272
+ thread(conversationId: string, rootId: string, opts?: {
273
+ at?: string;
274
+ }): ThreadView;
275
+ /**
276
+ * Finds the person's messages by their words — every word asked, each a word's beginning, as they type it
277
+ * ("cafe" finds "Café's", capitals and the Turkish i's alike) — in what they say or their files' names, the newest
278
+ * first, a page at a time: in all their conversations, or one (conversationId). Each comes with its conversation, its name and picture, who wrote
279
+ * it and where it says what was asked. On the first page, the conversations whose name says it too (a group's
280
+ * title, the other person's name), from the person's own list. A query with no word finds nothing.
281
+ */
282
+ search(query: string, opts?: SearchOptions): Promise<SearchResults>;
283
+ /** The person's conversations whose name says every word asked: a group's title, the other person's name. */
284
+ private named;
201
285
  /** The person's messages scheduled for later, kept up to date. */
202
286
  scheduled(): ScheduledList;
203
287
  /** The threads the person follows, the latest answered first. */
@@ -246,6 +330,11 @@ export declare class Messaging {
246
330
  * reportableUntil, naming no message: the last 30 messages the person saw in it go with the report.
247
331
  */
248
332
  report(input: api.ReportRequest): Promise<api.ReportCreated>;
333
+ /**
334
+ * A stretch that reaches the newest becomes the timeline's: both run to the newest, so together they are one —
335
+ * read back from the older of their ends.
336
+ */
337
+ private merge;
249
338
  }
250
339
  declare abstract class View<S> implements Observed<S> {
251
340
  protected listeners: Set<Listener>;
@@ -258,6 +347,7 @@ declare abstract class View<S> implements Observed<S> {
258
347
  get state(): S;
259
348
  subscribe(listener: Listener): () => void;
260
349
  protected opened(): void;
350
+ protected closed(): void;
261
351
  protected abstract touches(t: Touched): boolean;
262
352
  protected abstract read(): S;
263
353
  }
@@ -271,14 +361,32 @@ export declare class DeletedGroupList extends View<DeletedGroupListState> {
271
361
  }
272
362
  export declare class ConversationView extends View<ConversationViewState> {
273
363
  readonly id: string;
274
- constructor(m: Messaging, id: string);
364
+ /** The message it was opened at (conversation(id, { at })). */
365
+ readonly focus: string | null;
366
+ private window;
367
+ /** Opening it at its message: read, or failed (it opens at the newest then). */
368
+ private opening;
369
+ /** Opened at its message: until then nothing is drawn — not the newest in the message's place. */
370
+ private settled;
371
+ constructor(m: Messaging, id: string, focus?: string | null);
275
372
  protected opened(): void;
373
+ protected closed(): void;
276
374
  protected touches(t: Touched): boolean;
375
+ /** The stretch around the message it was opened at, while it is apart from the timeline. */
376
+ private stretch;
277
377
  protected read(): ConversationViewState;
278
378
  /** Reads the conversation's newest page now (opening it does). */
279
379
  refresh(): Promise<boolean>;
280
380
  /** Reads the page of messages before the oldest one drawn; answers whether there are more. */
281
381
  loadEarlier(): Promise<boolean>;
382
+ /**
383
+ * Reads the page of messages after the newest one drawn, opened at a message away from the newest; answers whether
384
+ * there are more. Once it reaches the newest, the timeline is the conversation's again — what comes live, what is on
385
+ * its way.
386
+ */
387
+ loadLater(): Promise<boolean>;
388
+ /** Puts aside the stretch it was opened at: its timeline is the conversation's newest again (focus stays). */
389
+ showLatest(): void;
282
390
  send(input: string | SendOptions): Promise<OutboxItem>;
283
391
  markRead(seq?: number): Promise<void>;
284
392
  typing(): Promise<void>;
@@ -287,7 +395,9 @@ export declare class ConversationView extends View<ConversationViewState> {
287
395
  export declare class ThreadView extends View<ThreadViewState> {
288
396
  readonly conversationId: string;
289
397
  readonly rootId: string;
290
- constructor(m: Messaging, conversationId: string, rootId: string);
398
+ /** The answer it was opened at (thread(…, { at })). */
399
+ readonly focus: string | null;
400
+ constructor(m: Messaging, conversationId: string, rootId: string, focus?: string | null);
291
401
  protected opened(): void;
292
402
  protected touches(t: Touched): boolean;
293
403
  protected read(): ThreadViewState;