@poolse/sdk 1.1.0 → 2.0.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.
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,6 @@ 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.0";
997
1020
 
998
1021
  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 };
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,6 @@ 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.0";
997
1020
 
998
1021
  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 };
package/dist/index.js CHANGED
@@ -813,55 +813,55 @@ var UsersResource = class {
813
813
  * "not in cache yet" (different from `null`, which means "resolver
814
814
  * ran and the user wasn't found").
815
815
  */
816
- peek(userId) {
817
- return this.cache.get(userId);
816
+ peek(externalId) {
817
+ return this.cache.get(externalId);
818
818
  }
819
819
  /**
820
820
  * Resolve a user, hitting the customer's `userResolver` on cache
821
- * miss. Concurrent calls for the same id share one Promise.
821
+ * miss. Concurrent calls for the same external_id share one Promise.
822
822
  */
823
- async get(userId) {
824
- if (this.cache.has(userId)) {
825
- return this.cache.get(userId) ?? null;
823
+ async get(externalId) {
824
+ if (this.cache.has(externalId)) {
825
+ return this.cache.get(externalId) ?? null;
826
826
  }
827
- const existingPending = this.pending.get(userId);
827
+ const existingPending = this.pending.get(externalId);
828
828
  if (existingPending) return existingPending;
829
829
  const resolver = this.config.userResolver;
830
830
  if (!resolver) {
831
- this.cache.set(userId, null);
832
- this.notify(userId);
831
+ this.cache.set(externalId, null);
832
+ this.notify(externalId);
833
833
  return null;
834
834
  }
835
- const promise = Promise.resolve().then(() => resolver(userId)).then(
835
+ const promise = Promise.resolve().then(() => resolver(externalId)).then(
836
836
  (profile) => {
837
- this.cache.set(userId, profile ?? null);
838
- this.pending.delete(userId);
839
- this.notify(userId);
837
+ this.cache.set(externalId, profile ?? null);
838
+ this.pending.delete(externalId);
839
+ this.notify(externalId);
840
840
  return profile ?? null;
841
841
  },
842
842
  (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);
843
+ console.error("[poolse] userResolver failed for", externalId, err);
844
+ this.cache.set(externalId, null);
845
+ this.pending.delete(externalId);
846
+ this.notify(externalId);
847
847
  return null;
848
848
  }
849
849
  );
850
- this.pending.set(userId, promise);
850
+ this.pending.set(externalId, promise);
851
851
  return promise;
852
852
  }
853
853
  /**
854
- * Subscribe to changes for a single user id. The listener fires
854
+ * Subscribe to changes for a single external_id. The listener fires
855
855
  * when the resolver lands (or when the entry is invalidated).
856
856
  * Returns an unsubscribe.
857
857
  *
858
858
  * `useUser` in @poolse/react uses this with `useSyncExternalStore`.
859
859
  */
860
- subscribe(userId, listener) {
861
- let set = this.listeners.get(userId);
860
+ subscribe(externalId, listener) {
861
+ let set = this.listeners.get(externalId);
862
862
  if (!set) {
863
863
  set = /* @__PURE__ */ new Set();
864
- this.listeners.set(userId, set);
864
+ this.listeners.set(externalId, set);
865
865
  }
866
866
  set.add(listener);
867
867
  return () => {
@@ -869,10 +869,10 @@ var UsersResource = class {
869
869
  };
870
870
  }
871
871
  /** 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);
872
+ invalidate(externalId) {
873
+ this.cache.delete(externalId);
874
+ this.pending.delete(externalId);
875
+ this.notify(externalId);
876
876
  }
877
877
  /**
878
878
  * Drop the entire cache. Use after a sign-out, tenant swap, or any
@@ -882,12 +882,12 @@ var UsersResource = class {
882
882
  invalidateAll() {
883
883
  this.cache.clear();
884
884
  this.pending.clear();
885
- for (const userId of this.listeners.keys()) {
886
- this.notify(userId);
885
+ for (const externalId of this.listeners.keys()) {
886
+ this.notify(externalId);
887
887
  }
888
888
  }
889
- notify(userId) {
890
- const set = this.listeners.get(userId);
889
+ notify(externalId) {
890
+ const set = this.listeners.get(externalId);
891
891
  if (!set) return;
892
892
  for (const l of set) l();
893
893
  }
@@ -1170,7 +1170,7 @@ var Poolse = class {
1170
1170
  };
1171
1171
 
1172
1172
  // src/version.ts
1173
- var version = "1.1.0";
1173
+ var version = "2.0.0";
1174
1174
 
1175
1175
  export { ApiError, AttachmentHandle, AttachmentsResource, AuthError, ConversationChannel, ConversationHandle, ConversationMessages, ConversationsResource, MeResource, MessageHandle, MessagesResource, NetworkError, POOLSE_API_URL, Poolse, PoolseError, PoolseRealtime, RateLimitedError, UserChannel, UsersResource, version };
1176
1176
  //# sourceMappingURL=index.js.map