@poolse/sdk 1.1.0 → 2.0.1
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 +43 -0
- package/README.md +15 -13
- package/dist/index.cjs +55 -45
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +47 -22
- package/dist/index.d.ts +47 -22
- package/dist/index.js +55 -46
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -77,7 +77,16 @@ type MemberRole = 'owner' | 'admin' | 'member';
|
|
|
77
77
|
interface Membership {
|
|
78
78
|
id: Uuid;
|
|
79
79
|
conversation_id: Uuid;
|
|
80
|
+
/** Internal poolse user id. Most consumer code uses `external_id` instead. */
|
|
80
81
|
user_id: Uuid;
|
|
82
|
+
/**
|
|
83
|
+
* The tenant's own user identifier (the same string you pass as
|
|
84
|
+
* `external_id` when minting JWTs or referencing users in
|
|
85
|
+
* `member_external_ids`). Every user reference on the wire carries
|
|
86
|
+
* this so the SDK's `userResolver(externalId)` is a complete API
|
|
87
|
+
* — no need to maintain a `poolse_user_id` mapping on your side.
|
|
88
|
+
*/
|
|
89
|
+
external_id: string;
|
|
81
90
|
role: MemberRole;
|
|
82
91
|
last_read_message_id: Uuid | null;
|
|
83
92
|
last_read_at: IsoDateTime | null;
|
|
@@ -107,7 +116,15 @@ interface Message {
|
|
|
107
116
|
id: Uuid;
|
|
108
117
|
tenant_id: Uuid;
|
|
109
118
|
conversation_id: Uuid;
|
|
119
|
+
/** Internal poolse user id of the sender. Null for system messages. */
|
|
110
120
|
sender_id: Uuid | null;
|
|
121
|
+
/**
|
|
122
|
+
* The tenant's own user identifier for the sender — passed straight
|
|
123
|
+
* to `userResolver(externalId)` to render display name + avatar.
|
|
124
|
+
* Null for system messages, and null on read paths that didn't
|
|
125
|
+
* preload the sender (very rare; every client-facing path preloads).
|
|
126
|
+
*/
|
|
127
|
+
sender_external_id: string | null;
|
|
111
128
|
type: MessageType;
|
|
112
129
|
body: string | null;
|
|
113
130
|
reply_to_id: Uuid | null;
|
|
@@ -179,6 +196,8 @@ interface PoolseUserProfile {
|
|
|
179
196
|
interface QuotedMessagePreview {
|
|
180
197
|
id: Uuid;
|
|
181
198
|
sender_id: Uuid | null;
|
|
199
|
+
/** Same external-id story as `Message.sender_external_id`. */
|
|
200
|
+
sender_external_id: string | null;
|
|
182
201
|
/** Truncated to ~200 chars server-side; null when the original was deleted. */
|
|
183
202
|
body: string | null;
|
|
184
203
|
deleted_at: IsoDateTime | null;
|
|
@@ -351,32 +370,33 @@ interface PoolseConfig {
|
|
|
351
370
|
*/
|
|
352
371
|
onSocketError?: (err: Error) => void;
|
|
353
372
|
/**
|
|
354
|
-
* Resolve
|
|
355
|
-
*
|
|
356
|
-
*
|
|
357
|
-
*
|
|
373
|
+
* Resolve the tenant's user identifier (`external_id` — same string
|
|
374
|
+
* you pass when minting JWTs and referencing users in
|
|
375
|
+
* `member_external_ids`) to the customer's own user metadata
|
|
376
|
+
* (display name + avatar). Called by `chat.users.get(externalId)`
|
|
377
|
+
* and the `useUser(externalId)` React hook whenever a UI component
|
|
378
|
+
* needs to render a participant.
|
|
358
379
|
*
|
|
359
380
|
* The SDK caches results in-memory and dedupes concurrent calls,
|
|
360
381
|
* so a busy chat with 50 messages from 5 senders fires the
|
|
361
382
|
* resolver 5 times — once per unique sender — not 50.
|
|
362
383
|
*
|
|
363
|
-
* Customers
|
|
384
|
+
* Customers hit their OWN backend / store here, keyed by **their own
|
|
385
|
+
* user id** (no poolse uuid mapping required):
|
|
364
386
|
*
|
|
365
|
-
* userResolver: async (
|
|
366
|
-
* const u = await fetch(`/api/users
|
|
367
|
-
* .then((r) => r.json());
|
|
387
|
+
* userResolver: async (externalId) => {
|
|
388
|
+
* const u = await fetch(`/api/users/${externalId}`).then((r) => r.json());
|
|
368
389
|
* return { displayName: u.full_name, avatarUrl: u.avatar_url };
|
|
369
390
|
* }
|
|
370
391
|
*
|
|
371
|
-
* Sync returns are fine when the
|
|
372
|
-
* data in memory (e.g., from a directory loaded at app boot):
|
|
392
|
+
* Sync returns are fine when the data's already in memory:
|
|
373
393
|
*
|
|
374
|
-
* userResolver: (
|
|
394
|
+
* userResolver: (externalId) => directory[externalId] ?? null
|
|
375
395
|
*
|
|
376
|
-
* Return `null` when the user can't be found — components fall
|
|
377
|
-
*
|
|
396
|
+
* Return `null` when the user can't be found — components fall back
|
|
397
|
+
* to the external_id as a label and an initials avatar.
|
|
378
398
|
*/
|
|
379
|
-
userResolver?: (
|
|
399
|
+
userResolver?: (externalId: string) => Promise<PoolseUserProfile | null> | PoolseUserProfile | null;
|
|
380
400
|
}
|
|
381
401
|
/** Internal resolved config — all the defaults filled in. */
|
|
382
402
|
interface ResolvedConfig {
|
|
@@ -432,7 +452,10 @@ interface MessageDeletedEvent {
|
|
|
432
452
|
}
|
|
433
453
|
/** `typing:start` / `typing:stop`. */
|
|
434
454
|
interface TypingEvent {
|
|
455
|
+
/** Internal poolse user id. Most consumer code uses `external_id` instead. */
|
|
435
456
|
user_id: Uuid;
|
|
457
|
+
/** The tenant's own id — what your `userResolver` consumes. */
|
|
458
|
+
external_id: string | null;
|
|
436
459
|
}
|
|
437
460
|
/** `reaction:added` / `reaction:removed`. */
|
|
438
461
|
interface ReactionEvent {
|
|
@@ -880,22 +903,22 @@ declare class UsersResource {
|
|
|
880
903
|
* "not in cache yet" (different from `null`, which means "resolver
|
|
881
904
|
* ran and the user wasn't found").
|
|
882
905
|
*/
|
|
883
|
-
peek(
|
|
906
|
+
peek(externalId: string): PoolseUserProfile | null | undefined;
|
|
884
907
|
/**
|
|
885
908
|
* Resolve a user, hitting the customer's `userResolver` on cache
|
|
886
|
-
* miss. Concurrent calls for the same
|
|
909
|
+
* miss. Concurrent calls for the same external_id share one Promise.
|
|
887
910
|
*/
|
|
888
|
-
get(
|
|
911
|
+
get(externalId: string): Promise<PoolseUserProfile | null>;
|
|
889
912
|
/**
|
|
890
|
-
* Subscribe to changes for a single
|
|
913
|
+
* Subscribe to changes for a single external_id. The listener fires
|
|
891
914
|
* when the resolver lands (or when the entry is invalidated).
|
|
892
915
|
* Returns an unsubscribe.
|
|
893
916
|
*
|
|
894
917
|
* `useUser` in @poolse/react uses this with `useSyncExternalStore`.
|
|
895
918
|
*/
|
|
896
|
-
subscribe(
|
|
919
|
+
subscribe(externalId: string, listener: Listener): () => void;
|
|
897
920
|
/** Drop a single cached entry — next `get` re-fetches via the resolver. */
|
|
898
|
-
invalidate(
|
|
921
|
+
invalidate(externalId: string): void;
|
|
899
922
|
/**
|
|
900
923
|
* Drop the entire cache. Use after a sign-out, tenant swap, or any
|
|
901
924
|
* other event that invalidates every cached profile (e.g., the
|
|
@@ -993,6 +1016,8 @@ declare class AuthError extends ApiError {
|
|
|
993
1016
|
constructor(envelope: ErrorEnvelope['error']);
|
|
994
1017
|
}
|
|
995
1018
|
|
|
996
|
-
declare const version = "
|
|
1019
|
+
declare const version = "2.0.1";
|
|
1020
|
+
|
|
1021
|
+
declare function safeUuid(): string;
|
|
997
1022
|
|
|
998
|
-
export { type AddMemberOptions, ApiError, type Attachment, type AttachmentDownloadResponse, AttachmentHandle, type AttachmentOptions, type AttachmentProgressEvent, type AttachmentStatus, type AttachmentUploadInput, type AttachmentUploadRequest, type AttachmentUploadResponse, AttachmentsResource, AuthError, type Conversation, ConversationChannel, type ConversationCreateRequest, type ConversationCreatedEvent, ConversationHandle, type ConversationList, ConversationMessages, type ConversationType, type ConversationUpdateRequest, ConversationsResource, type ErrorEnvelope, type IsoDateTime, type Me, MeResource, type MemberReadEvent, type MemberRole, type Membership, type MembershipCreateRequest, type MembershipList, type MentionEvent, type Message, type MessageCreateRequest, type MessageDeletedEvent, MessageHandle, type MessageList, type MessageNewEvent, type MessageType, type MessageUpdateRequest, type MessageUpdatedEvent, MessagesResource, NetworkError, POOLSE_API_URL, Poolse, type PoolseConfig, PoolseError, PoolseRealtime, type PoolseUserProfile, type PresenceSnapshot, type QuotedMessagePreview, RateLimitedError, type ReactionEvent, type ReactionRequest, type ReadRequest, type RealtimeStatus, type TypingEvent, type Unsubscribe, UserChannel, UsersResource, type Uuid, version };
|
|
1023
|
+
export { type AddMemberOptions, ApiError, type Attachment, type AttachmentDownloadResponse, AttachmentHandle, type AttachmentOptions, type AttachmentProgressEvent, type AttachmentStatus, type AttachmentUploadInput, type AttachmentUploadRequest, type AttachmentUploadResponse, AttachmentsResource, AuthError, type Conversation, ConversationChannel, type ConversationCreateRequest, type ConversationCreatedEvent, ConversationHandle, type ConversationList, ConversationMessages, type ConversationType, type ConversationUpdateRequest, ConversationsResource, type ErrorEnvelope, type IsoDateTime, type Me, MeResource, type MemberReadEvent, type MemberRole, type Membership, type MembershipCreateRequest, type MembershipList, type MentionEvent, type Message, type MessageCreateRequest, type MessageDeletedEvent, MessageHandle, type MessageList, type MessageNewEvent, type MessageType, type MessageUpdateRequest, type MessageUpdatedEvent, MessagesResource, NetworkError, POOLSE_API_URL, Poolse, type PoolseConfig, PoolseError, PoolseRealtime, type PoolseUserProfile, type PresenceSnapshot, type QuotedMessagePreview, RateLimitedError, type ReactionEvent, type ReactionRequest, type ReadRequest, type RealtimeStatus, type TypingEvent, type Unsubscribe, UserChannel, UsersResource, type Uuid, safeUuid, version };
|
package/dist/index.d.ts
CHANGED
|
@@ -77,7 +77,16 @@ type MemberRole = 'owner' | 'admin' | 'member';
|
|
|
77
77
|
interface Membership {
|
|
78
78
|
id: Uuid;
|
|
79
79
|
conversation_id: Uuid;
|
|
80
|
+
/** Internal poolse user id. Most consumer code uses `external_id` instead. */
|
|
80
81
|
user_id: Uuid;
|
|
82
|
+
/**
|
|
83
|
+
* The tenant's own user identifier (the same string you pass as
|
|
84
|
+
* `external_id` when minting JWTs or referencing users in
|
|
85
|
+
* `member_external_ids`). Every user reference on the wire carries
|
|
86
|
+
* this so the SDK's `userResolver(externalId)` is a complete API
|
|
87
|
+
* — no need to maintain a `poolse_user_id` mapping on your side.
|
|
88
|
+
*/
|
|
89
|
+
external_id: string;
|
|
81
90
|
role: MemberRole;
|
|
82
91
|
last_read_message_id: Uuid | null;
|
|
83
92
|
last_read_at: IsoDateTime | null;
|
|
@@ -107,7 +116,15 @@ interface Message {
|
|
|
107
116
|
id: Uuid;
|
|
108
117
|
tenant_id: Uuid;
|
|
109
118
|
conversation_id: Uuid;
|
|
119
|
+
/** Internal poolse user id of the sender. Null for system messages. */
|
|
110
120
|
sender_id: Uuid | null;
|
|
121
|
+
/**
|
|
122
|
+
* The tenant's own user identifier for the sender — passed straight
|
|
123
|
+
* to `userResolver(externalId)` to render display name + avatar.
|
|
124
|
+
* Null for system messages, and null on read paths that didn't
|
|
125
|
+
* preload the sender (very rare; every client-facing path preloads).
|
|
126
|
+
*/
|
|
127
|
+
sender_external_id: string | null;
|
|
111
128
|
type: MessageType;
|
|
112
129
|
body: string | null;
|
|
113
130
|
reply_to_id: Uuid | null;
|
|
@@ -179,6 +196,8 @@ interface PoolseUserProfile {
|
|
|
179
196
|
interface QuotedMessagePreview {
|
|
180
197
|
id: Uuid;
|
|
181
198
|
sender_id: Uuid | null;
|
|
199
|
+
/** Same external-id story as `Message.sender_external_id`. */
|
|
200
|
+
sender_external_id: string | null;
|
|
182
201
|
/** Truncated to ~200 chars server-side; null when the original was deleted. */
|
|
183
202
|
body: string | null;
|
|
184
203
|
deleted_at: IsoDateTime | null;
|
|
@@ -351,32 +370,33 @@ interface PoolseConfig {
|
|
|
351
370
|
*/
|
|
352
371
|
onSocketError?: (err: Error) => void;
|
|
353
372
|
/**
|
|
354
|
-
* Resolve
|
|
355
|
-
*
|
|
356
|
-
*
|
|
357
|
-
*
|
|
373
|
+
* Resolve the tenant's user identifier (`external_id` — same string
|
|
374
|
+
* you pass when minting JWTs and referencing users in
|
|
375
|
+
* `member_external_ids`) to the customer's own user metadata
|
|
376
|
+
* (display name + avatar). Called by `chat.users.get(externalId)`
|
|
377
|
+
* and the `useUser(externalId)` React hook whenever a UI component
|
|
378
|
+
* needs to render a participant.
|
|
358
379
|
*
|
|
359
380
|
* The SDK caches results in-memory and dedupes concurrent calls,
|
|
360
381
|
* so a busy chat with 50 messages from 5 senders fires the
|
|
361
382
|
* resolver 5 times — once per unique sender — not 50.
|
|
362
383
|
*
|
|
363
|
-
* Customers
|
|
384
|
+
* Customers hit their OWN backend / store here, keyed by **their own
|
|
385
|
+
* user id** (no poolse uuid mapping required):
|
|
364
386
|
*
|
|
365
|
-
* userResolver: async (
|
|
366
|
-
* const u = await fetch(`/api/users
|
|
367
|
-
* .then((r) => r.json());
|
|
387
|
+
* userResolver: async (externalId) => {
|
|
388
|
+
* const u = await fetch(`/api/users/${externalId}`).then((r) => r.json());
|
|
368
389
|
* return { displayName: u.full_name, avatarUrl: u.avatar_url };
|
|
369
390
|
* }
|
|
370
391
|
*
|
|
371
|
-
* Sync returns are fine when the
|
|
372
|
-
* data in memory (e.g., from a directory loaded at app boot):
|
|
392
|
+
* Sync returns are fine when the data's already in memory:
|
|
373
393
|
*
|
|
374
|
-
* userResolver: (
|
|
394
|
+
* userResolver: (externalId) => directory[externalId] ?? null
|
|
375
395
|
*
|
|
376
|
-
* Return `null` when the user can't be found — components fall
|
|
377
|
-
*
|
|
396
|
+
* Return `null` when the user can't be found — components fall back
|
|
397
|
+
* to the external_id as a label and an initials avatar.
|
|
378
398
|
*/
|
|
379
|
-
userResolver?: (
|
|
399
|
+
userResolver?: (externalId: string) => Promise<PoolseUserProfile | null> | PoolseUserProfile | null;
|
|
380
400
|
}
|
|
381
401
|
/** Internal resolved config — all the defaults filled in. */
|
|
382
402
|
interface ResolvedConfig {
|
|
@@ -432,7 +452,10 @@ interface MessageDeletedEvent {
|
|
|
432
452
|
}
|
|
433
453
|
/** `typing:start` / `typing:stop`. */
|
|
434
454
|
interface TypingEvent {
|
|
455
|
+
/** Internal poolse user id. Most consumer code uses `external_id` instead. */
|
|
435
456
|
user_id: Uuid;
|
|
457
|
+
/** The tenant's own id — what your `userResolver` consumes. */
|
|
458
|
+
external_id: string | null;
|
|
436
459
|
}
|
|
437
460
|
/** `reaction:added` / `reaction:removed`. */
|
|
438
461
|
interface ReactionEvent {
|
|
@@ -880,22 +903,22 @@ declare class UsersResource {
|
|
|
880
903
|
* "not in cache yet" (different from `null`, which means "resolver
|
|
881
904
|
* ran and the user wasn't found").
|
|
882
905
|
*/
|
|
883
|
-
peek(
|
|
906
|
+
peek(externalId: string): PoolseUserProfile | null | undefined;
|
|
884
907
|
/**
|
|
885
908
|
* Resolve a user, hitting the customer's `userResolver` on cache
|
|
886
|
-
* miss. Concurrent calls for the same
|
|
909
|
+
* miss. Concurrent calls for the same external_id share one Promise.
|
|
887
910
|
*/
|
|
888
|
-
get(
|
|
911
|
+
get(externalId: string): Promise<PoolseUserProfile | null>;
|
|
889
912
|
/**
|
|
890
|
-
* Subscribe to changes for a single
|
|
913
|
+
* Subscribe to changes for a single external_id. The listener fires
|
|
891
914
|
* when the resolver lands (or when the entry is invalidated).
|
|
892
915
|
* Returns an unsubscribe.
|
|
893
916
|
*
|
|
894
917
|
* `useUser` in @poolse/react uses this with `useSyncExternalStore`.
|
|
895
918
|
*/
|
|
896
|
-
subscribe(
|
|
919
|
+
subscribe(externalId: string, listener: Listener): () => void;
|
|
897
920
|
/** Drop a single cached entry — next `get` re-fetches via the resolver. */
|
|
898
|
-
invalidate(
|
|
921
|
+
invalidate(externalId: string): void;
|
|
899
922
|
/**
|
|
900
923
|
* Drop the entire cache. Use after a sign-out, tenant swap, or any
|
|
901
924
|
* other event that invalidates every cached profile (e.g., the
|
|
@@ -993,6 +1016,8 @@ declare class AuthError extends ApiError {
|
|
|
993
1016
|
constructor(envelope: ErrorEnvelope['error']);
|
|
994
1017
|
}
|
|
995
1018
|
|
|
996
|
-
declare const version = "
|
|
1019
|
+
declare const version = "2.0.1";
|
|
1020
|
+
|
|
1021
|
+
declare function safeUuid(): string;
|
|
997
1022
|
|
|
998
|
-
export { type AddMemberOptions, ApiError, type Attachment, type AttachmentDownloadResponse, AttachmentHandle, type AttachmentOptions, type AttachmentProgressEvent, type AttachmentStatus, type AttachmentUploadInput, type AttachmentUploadRequest, type AttachmentUploadResponse, AttachmentsResource, AuthError, type Conversation, ConversationChannel, type ConversationCreateRequest, type ConversationCreatedEvent, ConversationHandle, type ConversationList, ConversationMessages, type ConversationType, type ConversationUpdateRequest, ConversationsResource, type ErrorEnvelope, type IsoDateTime, type Me, MeResource, type MemberReadEvent, type MemberRole, type Membership, type MembershipCreateRequest, type MembershipList, type MentionEvent, type Message, type MessageCreateRequest, type MessageDeletedEvent, MessageHandle, type MessageList, type MessageNewEvent, type MessageType, type MessageUpdateRequest, type MessageUpdatedEvent, MessagesResource, NetworkError, POOLSE_API_URL, Poolse, type PoolseConfig, PoolseError, PoolseRealtime, type PoolseUserProfile, type PresenceSnapshot, type QuotedMessagePreview, RateLimitedError, type ReactionEvent, type ReactionRequest, type ReadRequest, type RealtimeStatus, type TypingEvent, type Unsubscribe, UserChannel, UsersResource, type Uuid, version };
|
|
1023
|
+
export { type AddMemberOptions, ApiError, type Attachment, type AttachmentDownloadResponse, AttachmentHandle, type AttachmentOptions, type AttachmentProgressEvent, type AttachmentStatus, type AttachmentUploadInput, type AttachmentUploadRequest, type AttachmentUploadResponse, AttachmentsResource, AuthError, type Conversation, ConversationChannel, type ConversationCreateRequest, type ConversationCreatedEvent, ConversationHandle, type ConversationList, ConversationMessages, type ConversationType, type ConversationUpdateRequest, ConversationsResource, type ErrorEnvelope, type IsoDateTime, type Me, MeResource, type MemberReadEvent, type MemberRole, type Membership, type MembershipCreateRequest, type MembershipList, type MentionEvent, type Message, type MessageCreateRequest, type MessageDeletedEvent, MessageHandle, type MessageList, type MessageNewEvent, type MessageType, type MessageUpdateRequest, type MessageUpdatedEvent, MessagesResource, NetworkError, POOLSE_API_URL, Poolse, type PoolseConfig, PoolseError, PoolseRealtime, type PoolseUserProfile, type PresenceSnapshot, type QuotedMessagePreview, RateLimitedError, type ReactionEvent, type ReactionRequest, type ReadRequest, type RealtimeStatus, type TypingEvent, type Unsubscribe, UserChannel, UsersResource, type Uuid, safeUuid, version };
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,26 @@
|
|
|
1
1
|
import { Socket } from 'phoenix';
|
|
2
2
|
|
|
3
|
+
// src/uuid.ts
|
|
4
|
+
function safeUuid() {
|
|
5
|
+
const c = globalThis.crypto;
|
|
6
|
+
if (c?.randomUUID) return c.randomUUID();
|
|
7
|
+
const bytes = new Uint8Array(16);
|
|
8
|
+
if (c?.getRandomValues) {
|
|
9
|
+
c.getRandomValues(bytes);
|
|
10
|
+
} else {
|
|
11
|
+
for (let i = 0; i < 16; i++) {
|
|
12
|
+
bytes[i] = Math.floor(Math.random() * 256);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
bytes[6] = bytes[6] & 15 | 64;
|
|
16
|
+
bytes[8] = bytes[8] & 63 | 128;
|
|
17
|
+
const hex = [];
|
|
18
|
+
for (let i = 0; i < 16; i++) {
|
|
19
|
+
hex.push(bytes[i].toString(16).padStart(2, "0"));
|
|
20
|
+
}
|
|
21
|
+
return hex.slice(0, 4).join("") + "-" + hex.slice(4, 6).join("") + "-" + hex.slice(6, 8).join("") + "-" + hex.slice(8, 10).join("") + "-" + hex.slice(10).join("");
|
|
22
|
+
}
|
|
23
|
+
|
|
3
24
|
// src/config.ts
|
|
4
25
|
var POOLSE_API_URL = "https://api.poolse.dev";
|
|
5
26
|
var DEFAULT_MAX_RETRIES = 3;
|
|
@@ -34,13 +55,7 @@ function trimTrailingSlash(s) {
|
|
|
34
55
|
return s.endsWith("/") ? s.slice(0, -1) : s;
|
|
35
56
|
}
|
|
36
57
|
function defaultIdempotencyKey() {
|
|
37
|
-
|
|
38
|
-
if (c && typeof c.randomUUID === "function") {
|
|
39
|
-
return c.randomUUID();
|
|
40
|
-
}
|
|
41
|
-
throw new Error(
|
|
42
|
-
"Poolse: globalThis.crypto.randomUUID() is not available; supply `config.generateIdempotencyKey` instead."
|
|
43
|
-
);
|
|
58
|
+
return safeUuid();
|
|
44
59
|
}
|
|
45
60
|
|
|
46
61
|
// src/errors.ts
|
|
@@ -663,13 +678,7 @@ var MessagesResource = class {
|
|
|
663
678
|
}
|
|
664
679
|
};
|
|
665
680
|
function generateClientMessageId() {
|
|
666
|
-
|
|
667
|
-
if (c && typeof c.randomUUID === "function") {
|
|
668
|
-
return c.randomUUID();
|
|
669
|
-
}
|
|
670
|
-
throw new Error(
|
|
671
|
-
"Poolse: globalThis.crypto.randomUUID() unavailable \u2014 pass `id` explicitly in MessageCreateRequest (your env lacks a built-in UUID generator)."
|
|
672
|
-
);
|
|
681
|
+
return safeUuid();
|
|
673
682
|
}
|
|
674
683
|
|
|
675
684
|
// src/resources/conversations.ts
|
|
@@ -813,55 +822,55 @@ var UsersResource = class {
|
|
|
813
822
|
* "not in cache yet" (different from `null`, which means "resolver
|
|
814
823
|
* ran and the user wasn't found").
|
|
815
824
|
*/
|
|
816
|
-
peek(
|
|
817
|
-
return this.cache.get(
|
|
825
|
+
peek(externalId) {
|
|
826
|
+
return this.cache.get(externalId);
|
|
818
827
|
}
|
|
819
828
|
/**
|
|
820
829
|
* Resolve a user, hitting the customer's `userResolver` on cache
|
|
821
|
-
* miss. Concurrent calls for the same
|
|
830
|
+
* miss. Concurrent calls for the same external_id share one Promise.
|
|
822
831
|
*/
|
|
823
|
-
async get(
|
|
824
|
-
if (this.cache.has(
|
|
825
|
-
return this.cache.get(
|
|
832
|
+
async get(externalId) {
|
|
833
|
+
if (this.cache.has(externalId)) {
|
|
834
|
+
return this.cache.get(externalId) ?? null;
|
|
826
835
|
}
|
|
827
|
-
const existingPending = this.pending.get(
|
|
836
|
+
const existingPending = this.pending.get(externalId);
|
|
828
837
|
if (existingPending) return existingPending;
|
|
829
838
|
const resolver = this.config.userResolver;
|
|
830
839
|
if (!resolver) {
|
|
831
|
-
this.cache.set(
|
|
832
|
-
this.notify(
|
|
840
|
+
this.cache.set(externalId, null);
|
|
841
|
+
this.notify(externalId);
|
|
833
842
|
return null;
|
|
834
843
|
}
|
|
835
|
-
const promise = Promise.resolve().then(() => resolver(
|
|
844
|
+
const promise = Promise.resolve().then(() => resolver(externalId)).then(
|
|
836
845
|
(profile) => {
|
|
837
|
-
this.cache.set(
|
|
838
|
-
this.pending.delete(
|
|
839
|
-
this.notify(
|
|
846
|
+
this.cache.set(externalId, profile ?? null);
|
|
847
|
+
this.pending.delete(externalId);
|
|
848
|
+
this.notify(externalId);
|
|
840
849
|
return profile ?? null;
|
|
841
850
|
},
|
|
842
851
|
(err) => {
|
|
843
|
-
console.error("[poolse] userResolver failed for",
|
|
844
|
-
this.cache.set(
|
|
845
|
-
this.pending.delete(
|
|
846
|
-
this.notify(
|
|
852
|
+
console.error("[poolse] userResolver failed for", externalId, err);
|
|
853
|
+
this.cache.set(externalId, null);
|
|
854
|
+
this.pending.delete(externalId);
|
|
855
|
+
this.notify(externalId);
|
|
847
856
|
return null;
|
|
848
857
|
}
|
|
849
858
|
);
|
|
850
|
-
this.pending.set(
|
|
859
|
+
this.pending.set(externalId, promise);
|
|
851
860
|
return promise;
|
|
852
861
|
}
|
|
853
862
|
/**
|
|
854
|
-
* Subscribe to changes for a single
|
|
863
|
+
* Subscribe to changes for a single external_id. The listener fires
|
|
855
864
|
* when the resolver lands (or when the entry is invalidated).
|
|
856
865
|
* Returns an unsubscribe.
|
|
857
866
|
*
|
|
858
867
|
* `useUser` in @poolse/react uses this with `useSyncExternalStore`.
|
|
859
868
|
*/
|
|
860
|
-
subscribe(
|
|
861
|
-
let set = this.listeners.get(
|
|
869
|
+
subscribe(externalId, listener) {
|
|
870
|
+
let set = this.listeners.get(externalId);
|
|
862
871
|
if (!set) {
|
|
863
872
|
set = /* @__PURE__ */ new Set();
|
|
864
|
-
this.listeners.set(
|
|
873
|
+
this.listeners.set(externalId, set);
|
|
865
874
|
}
|
|
866
875
|
set.add(listener);
|
|
867
876
|
return () => {
|
|
@@ -869,10 +878,10 @@ var UsersResource = class {
|
|
|
869
878
|
};
|
|
870
879
|
}
|
|
871
880
|
/** Drop a single cached entry — next `get` re-fetches via the resolver. */
|
|
872
|
-
invalidate(
|
|
873
|
-
this.cache.delete(
|
|
874
|
-
this.pending.delete(
|
|
875
|
-
this.notify(
|
|
881
|
+
invalidate(externalId) {
|
|
882
|
+
this.cache.delete(externalId);
|
|
883
|
+
this.pending.delete(externalId);
|
|
884
|
+
this.notify(externalId);
|
|
876
885
|
}
|
|
877
886
|
/**
|
|
878
887
|
* Drop the entire cache. Use after a sign-out, tenant swap, or any
|
|
@@ -882,12 +891,12 @@ var UsersResource = class {
|
|
|
882
891
|
invalidateAll() {
|
|
883
892
|
this.cache.clear();
|
|
884
893
|
this.pending.clear();
|
|
885
|
-
for (const
|
|
886
|
-
this.notify(
|
|
894
|
+
for (const externalId of this.listeners.keys()) {
|
|
895
|
+
this.notify(externalId);
|
|
887
896
|
}
|
|
888
897
|
}
|
|
889
|
-
notify(
|
|
890
|
-
const set = this.listeners.get(
|
|
898
|
+
notify(externalId) {
|
|
899
|
+
const set = this.listeners.get(externalId);
|
|
891
900
|
if (!set) return;
|
|
892
901
|
for (const l of set) l();
|
|
893
902
|
}
|
|
@@ -1170,8 +1179,8 @@ var Poolse = class {
|
|
|
1170
1179
|
};
|
|
1171
1180
|
|
|
1172
1181
|
// src/version.ts
|
|
1173
|
-
var version = "
|
|
1182
|
+
var version = "2.0.1";
|
|
1174
1183
|
|
|
1175
|
-
export { ApiError, AttachmentHandle, AttachmentsResource, AuthError, ConversationChannel, ConversationHandle, ConversationMessages, ConversationsResource, MeResource, MessageHandle, MessagesResource, NetworkError, POOLSE_API_URL, Poolse, PoolseError, PoolseRealtime, RateLimitedError, UserChannel, UsersResource, version };
|
|
1184
|
+
export { ApiError, AttachmentHandle, AttachmentsResource, AuthError, ConversationChannel, ConversationHandle, ConversationMessages, ConversationsResource, MeResource, MessageHandle, MessagesResource, NetworkError, POOLSE_API_URL, Poolse, PoolseError, PoolseRealtime, RateLimitedError, UserChannel, UsersResource, safeUuid, version };
|
|
1176
1185
|
//# sourceMappingURL=index.js.map
|
|
1177
1186
|
//# sourceMappingURL=index.js.map
|