@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/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 a poolse `user_id` to the customer's own user metadata
355
- * (display name + avatar). Called by `chat.users.get(userId)` and
356
- * the `useUser(userId)` React hook whenever a UI component needs
357
- * to render a participant.
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 typically hit their OWN backend here:
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 (userId) => {
366
- * const u = await fetch(`/api/users/by-poolse-id/${userId}`)
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 customer already has the user
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: (userId) => directory[userId] ?? null
394
+ * userResolver: (externalId) => directory[externalId] ?? null
375
395
  *
376
- * Return `null` when the user can't be found — components fall
377
- * back to a userId-derived label and an initials avatar.
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?: (userId: string) => Promise<PoolseUserProfile | null> | PoolseUserProfile | null;
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(userId: string): PoolseUserProfile | null | undefined;
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 id share one Promise.
909
+ * miss. Concurrent calls for the same external_id share one Promise.
887
910
  */
888
- get(userId: string): Promise<PoolseUserProfile | null>;
911
+ get(externalId: string): Promise<PoolseUserProfile | null>;
889
912
  /**
890
- * Subscribe to changes for a single user id. The listener fires
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(userId: string, listener: Listener): () => void;
919
+ subscribe(externalId: string, listener: Listener): () => void;
897
920
  /** Drop a single cached entry — next `get` re-fetches via the resolver. */
898
- invalidate(userId: string): void;
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 = "1.1.0";
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 a poolse `user_id` to the customer's own user metadata
355
- * (display name + avatar). Called by `chat.users.get(userId)` and
356
- * the `useUser(userId)` React hook whenever a UI component needs
357
- * to render a participant.
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 typically hit their OWN backend here:
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 (userId) => {
366
- * const u = await fetch(`/api/users/by-poolse-id/${userId}`)
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 customer already has the user
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: (userId) => directory[userId] ?? null
394
+ * userResolver: (externalId) => directory[externalId] ?? null
375
395
  *
376
- * Return `null` when the user can't be found — components fall
377
- * back to a userId-derived label and an initials avatar.
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?: (userId: string) => Promise<PoolseUserProfile | null> | PoolseUserProfile | null;
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(userId: string): PoolseUserProfile | null | undefined;
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 id share one Promise.
909
+ * miss. Concurrent calls for the same external_id share one Promise.
887
910
  */
888
- get(userId: string): Promise<PoolseUserProfile | null>;
911
+ get(externalId: string): Promise<PoolseUserProfile | null>;
889
912
  /**
890
- * Subscribe to changes for a single user id. The listener fires
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(userId: string, listener: Listener): () => void;
919
+ subscribe(externalId: string, listener: Listener): () => void;
897
920
  /** Drop a single cached entry — next `get` re-fetches via the resolver. */
898
- invalidate(userId: string): void;
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 = "1.1.0";
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
- const c = globalThis.crypto;
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
- const c = globalThis.crypto;
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(userId) {
817
- return this.cache.get(userId);
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 id share one Promise.
830
+ * miss. Concurrent calls for the same external_id share one Promise.
822
831
  */
823
- async get(userId) {
824
- if (this.cache.has(userId)) {
825
- return this.cache.get(userId) ?? null;
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(userId);
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(userId, null);
832
- this.notify(userId);
840
+ this.cache.set(externalId, null);
841
+ this.notify(externalId);
833
842
  return null;
834
843
  }
835
- const promise = Promise.resolve().then(() => resolver(userId)).then(
844
+ const promise = Promise.resolve().then(() => resolver(externalId)).then(
836
845
  (profile) => {
837
- this.cache.set(userId, profile ?? null);
838
- this.pending.delete(userId);
839
- this.notify(userId);
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", userId, err);
844
- this.cache.set(userId, null);
845
- this.pending.delete(userId);
846
- this.notify(userId);
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(userId, promise);
859
+ this.pending.set(externalId, promise);
851
860
  return promise;
852
861
  }
853
862
  /**
854
- * Subscribe to changes for a single user id. The listener fires
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(userId, listener) {
861
- let set = this.listeners.get(userId);
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(userId, 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(userId) {
873
- this.cache.delete(userId);
874
- this.pending.delete(userId);
875
- this.notify(userId);
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 userId of this.listeners.keys()) {
886
- this.notify(userId);
894
+ for (const externalId of this.listeners.keys()) {
895
+ this.notify(externalId);
887
896
  }
888
897
  }
889
- notify(userId) {
890
- const set = this.listeners.get(userId);
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 = "1.1.0";
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