New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

stream-chat

Package Overview
Dependencies
Maintainers
10
Versions
322
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

stream-chat - npm Package Compare versions

Comparing version 8.55.0 to 8.56.0

dist/types/channel_manager.d.ts

1

dist/types/index.d.ts

@@ -23,3 +23,4 @@ export * from './base64';

export * from './types';
export * from './channel_manager';
export { isOwnUser, chatCodes, logChatPromiseExecution, formatMessage } from './utils';
//# sourceMappingURL=index.d.ts.map

4

dist/types/insights.d.ts

@@ -28,3 +28,3 @@ /// <reference types="ws" />

user_id: string | undefined;
user_details: import("./types").OwnUserResponse<import("./types").DefaultGenerics> | import("./types").UserResponse<import("./types").DefaultGenerics> | undefined;
user_details: import("./types").UserResponse<import("./types").DefaultGenerics> | import("./types").OwnUserResponse<import("./types").DefaultGenerics> | undefined;
device: import("./types").BaseDeviceFields | undefined;

@@ -49,3 +49,3 @@ client_id: string | undefined;

user_id: string | undefined;
user_details: import("./types").OwnUserResponse<import("./types").DefaultGenerics> | import("./types").UserResponse<import("./types").DefaultGenerics> | undefined;
user_details: import("./types").UserResponse<import("./types").DefaultGenerics> | import("./types").OwnUserResponse<import("./types").DefaultGenerics> | undefined;
device: import("./types").BaseDeviceFields | undefined;

@@ -52,0 +52,0 @@ client_id: string | undefined;

export declare type Patch<T> = (value: T) => T;
export declare type ValueOrPatch<T> = T | Patch<T>;
export declare type Handler<T> = (nextValue: T, previousValue: T | undefined) => void;
export declare type Unsubscribe = () => void;
export declare const isPatch: <T>(value: ValueOrPatch<T>) => value is Patch<T>;
export declare class StateStore<T extends Record<string, unknown>> {

@@ -9,3 +11,3 @@ private value;

constructor(value: T);
next: (newValueOrPatch: T | Patch<T>) => void;
next: (newValueOrPatch: ValueOrPatch<T>) => void;
partialNext: (partial: Partial<T>) => void;

@@ -12,0 +14,0 @@ getLatestValue: () => T;

/// <reference types="node" />
import FormData from 'form-data';
import { AscDesc, ExtendableGenerics, DefaultGenerics, Logger, OwnUserResponse, UserResponse, MessageResponse, FormatMessageResponse, MessageSet, MessagePaginationOptions } from './types';
import { AscDesc, ExtendableGenerics, DefaultGenerics, Logger, OwnUserResponse, UserResponse, MessageResponse, FormatMessageResponse, MessageSet, MessagePaginationOptions, ChannelQueryOptions, ChannelSort, ChannelFilters, ChannelSortBase, PromoteChannelParams } from './types';
import { StreamChat } from './client';
import { Channel } from './channel';
import { AxiosRequestConfig } from 'axios';

@@ -135,3 +137,90 @@ /**

};
declare type GetChannelParams<StreamChatGenerics extends ExtendableGenerics = DefaultGenerics> = {
client: StreamChat<StreamChatGenerics>;
channel?: Channel<StreamChatGenerics>;
id?: string;
members?: string[];
options?: ChannelQueryOptions<StreamChatGenerics>;
type?: string;
};
/**
* Calls channel.watch() if it was not already recently called. Waits for watch promise to resolve even if it was invoked previously.
* If the channel is not passed as a property, it will get it either by its channel.cid or by its members list and do the same.
* @param client
* @param members
* @param options
* @param type
* @param id
* @param channel
*/
export declare const getAndWatchChannel: <StreamChatGenerics extends ExtendableGenerics = DefaultGenerics>({ channel, client, id, members, options, type, }: GetChannelParams<StreamChatGenerics>) => Promise<Channel<StreamChatGenerics>>;
/**
* Generates a temporary channel.cid for channels created without ID, as they need to be referenced
* by an identifier until the back-end generates the final ID. The cid is generated by its member IDs
* which are sorted and can be recreated the same every time given the same arguments.
* @param channelType
* @param members
*/
export declare const generateChannelTempCid: (channelType: string, members: string[]) => string | undefined;
/**
* Checks if a channel is pinned or not. Will return true only if channel.state.membership.pinned_at exists.
* @param channel
*/
export declare const isChannelPinned: <StreamChatGenerics extends ExtendableGenerics = DefaultGenerics>(channel: Channel<StreamChatGenerics>) => boolean;
/**
* Checks if a channel is archived or not. Will return true only if channel.state.membership.archived_at exists.
* @param channel
*/
export declare const isChannelArchived: <StreamChatGenerics extends ExtendableGenerics = DefaultGenerics>(channel: Channel<StreamChatGenerics>) => boolean;
/**
* A utility that tells us whether we should consider archived channels or not based
* on filters. Will return true only if filters.archived exists and is a boolean value.
* @param filters
*/
export declare const shouldConsiderArchivedChannels: <StreamChatGenerics extends ExtendableGenerics = DefaultGenerics>(filters: ChannelFilters<StreamChatGenerics>) => boolean;
/**
* Extracts the value of the sort parameter at a given index, for a targeted key. Can
* handle both array and object versions of sort. Will return null if the index/key
* combination does not exist.
* @param atIndex - the index at which we'll examine the sort value, if it's an array one
* @param sort - the sort value - both array and object notations are accepted
* @param targetKey - the target key which needs to exist for the sort at a certain index
*/
export declare const extractSortValue: <StreamChatGenerics extends ExtendableGenerics = DefaultGenerics>({ atIndex, sort, targetKey, }: {
atIndex: number;
targetKey: "unread_count" | "created_at" | "pinned_at" | "updated_at" | "last_message_at" | "member_count" | keyof StreamChatGenerics["channelType"] | "has_unread" | "last_updated";
sort?: ChannelSort<StreamChatGenerics> | undefined;
}) => NonNullable<NonNullable<ChannelSortBase<StreamChatGenerics>>["unread_count" | "created_at" | "pinned_at" | "updated_at" | "last_message_at" | "member_count" | keyof StreamChatGenerics["channelType"] | "has_unread" | "last_updated"]> | null;
/**
* Returns true only if `{ pinned_at: -1 }` or `{ pinned_at: 1 }` option is first within the `sort` array.
*/
export declare const shouldConsiderPinnedChannels: <StreamChatGenerics extends ExtendableGenerics = DefaultGenerics>(sort: ChannelSort<StreamChatGenerics>) => boolean;
/**
* Checks whether the sort value of type object contains a pinned_at value or if
* an array sort value type has the first value be an object containing pinned_at.
* @param sort
*/
export declare const findPinnedAtSortOrder: <StreamChatGenerics extends ExtendableGenerics = DefaultGenerics>({ sort, }: {
sort: ChannelSort<StreamChatGenerics>;
}) => NonNullable<NonNullable<ChannelSortBase<StreamChatGenerics>>["unread_count" | "created_at" | "pinned_at" | "updated_at" | "last_message_at" | "member_count" | "has_unread" | "last_updated" | keyof StreamChatGenerics["channelType"]]> | null;
/**
* Finds the index of the last consecutively pinned channel, starting from the start of the
* array. Will not consider any pinned channels after the contiguous subsequence at the
* start of the array.
* @param channels
*/
export declare const findLastPinnedChannelIndex: <StreamChatGenerics extends ExtendableGenerics = DefaultGenerics>({ channels, }: {
channels: Channel<StreamChatGenerics>[];
}) => number | null;
/**
* A utility used to move a channel towards the beginning of a list of channels (promote it to a higher position). It
* considers pinned channels in the process if needed and makes sure to only update the list reference if the list
* should actually change. It will try to move the channel as high as it can within the list.
* @param channels - the list of channels we want to modify
* @param channelToMove - the channel we want to promote
* @param channelToMoveIndexWithinChannels - optionally, the index of the channel we want to move if we know it (will skip a manual check)
* @param sort - the sort value used to check for pinned channels
*/
export declare const promoteChannel: <StreamChatGenerics extends ExtendableGenerics = DefaultGenerics>({ channels, channelToMove, channelToMoveIndexWithinChannels, sort, }: PromoteChannelParams<StreamChatGenerics>) => Channel<StreamChatGenerics>[];
export {};
//# sourceMappingURL=utils.d.ts.map
{
"name": "stream-chat",
"version": "8.55.0",
"version": "8.56.0",
"description": "JS SDK for the Stream Chat API",

@@ -5,0 +5,0 @@ "author": "GetStream",

import { ChannelState } from './channel_state';
import { logChatPromiseExecution, messageSetPagination, normalizeQuerySort } from './utils';
import { generateChannelTempCid, logChatPromiseExecution, messageSetPagination, normalizeQuerySort } from './utils';
import { StreamChat } from './client';

@@ -1182,9 +1182,8 @@ import {

const membersStr = state.members
.map((member) => member.user_id || member.user?.id)
.sort()
.join(',');
const tempChannelCid = `${this.type}:!members-${membersStr}`;
const tempChannelCid = generateChannelTempCid(
this.type,
state.members.map((member) => member.user_id || member.user?.id || ''),
);
if (tempChannelCid in this.getClient().activeChannels) {
if (tempChannelCid && tempChannelCid in this.getClient().activeChannels) {
// This gets set in `client.channel()` function, when channel is created

@@ -1191,0 +1190,0 @@ // using members, not id.

@@ -23,2 +23,3 @@ export * from './base64';

export * from './types';
export * from './channel_manager';
export { isOwnUser, chatCodes, logChatPromiseExecution, formatMessage } from './utils';
export type Patch<T> = (value: T) => T;
export type ValueOrPatch<T> = T | Patch<T>;
export type Handler<T> = (nextValue: T, previousValue: T | undefined) => void;
export type Unsubscribe = () => void;
function isPatch<T>(value: T | Patch<T>): value is Patch<T> {
export const isPatch = <T>(value: ValueOrPatch<T>): value is Patch<T> => {
return typeof value === 'function';
}
};

@@ -16,3 +17,3 @@ export class StateStore<T extends Record<string, unknown>> {

public next = (newValueOrPatch: T | Patch<T>): void => {
public next = (newValueOrPatch: ValueOrPatch<T>): void => {
// newValue (or patch output) should never be mutated previous value

@@ -19,0 +20,0 @@ const newValue = isPatch(newValueOrPatch) ? newValueOrPatch(this.value) : newValueOrPatch;

@@ -15,3 +15,11 @@ import FormData from 'form-data';

MessagePaginationOptions,
ChannelQueryOptions,
QueryChannelAPIResponse,
ChannelSort,
ChannelFilters,
ChannelSortBase,
PromoteChannelParams,
} from './types';
import { StreamChat } from './client';
import { Channel } from './channel';
import { AxiosRequestConfig } from 'axios';

@@ -827,1 +835,273 @@

};
/**
* A utility object used to prevent duplicate invocation of channel.watch() to be triggered when
* 'notification.message_new' and 'notification.added_to_channel' events arrive at the same time.
*/
const WATCH_QUERY_IN_PROGRESS_FOR_CHANNEL: Record<string, Promise<QueryChannelAPIResponse> | undefined> = {};
type GetChannelParams<StreamChatGenerics extends ExtendableGenerics = DefaultGenerics> = {
client: StreamChat<StreamChatGenerics>;
channel?: Channel<StreamChatGenerics>;
id?: string;
members?: string[];
options?: ChannelQueryOptions<StreamChatGenerics>;
type?: string;
};
/**
* Calls channel.watch() if it was not already recently called. Waits for watch promise to resolve even if it was invoked previously.
* If the channel is not passed as a property, it will get it either by its channel.cid or by its members list and do the same.
* @param client
* @param members
* @param options
* @param type
* @param id
* @param channel
*/
export const getAndWatchChannel = async <StreamChatGenerics extends ExtendableGenerics = DefaultGenerics>({
channel,
client,
id,
members,
options,
type,
}: GetChannelParams<StreamChatGenerics>) => {
if (!channel && !type) {
throw new Error('Channel or channel type have to be provided to query a channel.');
}
// unfortunately typescript is not able to infer that if (!channel && !type) === false, then channel or type has to be truthy
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const channelToWatch = channel || client.channel(type!, id, { members });
// need to keep as with call to channel.watch the id can be changed from undefined to an actual ID generated server-side
const originalCid = channelToWatch.id
? channelToWatch.cid
: members && members.length
? generateChannelTempCid(channelToWatch.type, members)
: undefined;
if (!originalCid) {
throw new Error('Channel ID or channel members array have to be provided to query a channel.');
}
const queryPromise = WATCH_QUERY_IN_PROGRESS_FOR_CHANNEL[originalCid];
if (queryPromise) {
await queryPromise;
} else {
try {
WATCH_QUERY_IN_PROGRESS_FOR_CHANNEL[originalCid] = channelToWatch.watch(options);
await WATCH_QUERY_IN_PROGRESS_FOR_CHANNEL[originalCid];
} finally {
delete WATCH_QUERY_IN_PROGRESS_FOR_CHANNEL[originalCid];
}
}
return channelToWatch;
};
/**
* Generates a temporary channel.cid for channels created without ID, as they need to be referenced
* by an identifier until the back-end generates the final ID. The cid is generated by its member IDs
* which are sorted and can be recreated the same every time given the same arguments.
* @param channelType
* @param members
*/
export const generateChannelTempCid = (channelType: string, members: string[]) => {
if (!members) return;
const membersStr = [...members].sort().join(',');
if (!membersStr) return;
return `${channelType}:!members-${membersStr}`;
};
/**
* Checks if a channel is pinned or not. Will return true only if channel.state.membership.pinned_at exists.
* @param channel
*/
export const isChannelPinned = <StreamChatGenerics extends ExtendableGenerics = DefaultGenerics>(
channel: Channel<StreamChatGenerics>,
) => {
if (!channel) return false;
const member = channel.state.membership;
return !!member?.pinned_at;
};
/**
* Checks if a channel is archived or not. Will return true only if channel.state.membership.archived_at exists.
* @param channel
*/
export const isChannelArchived = <StreamChatGenerics extends ExtendableGenerics = DefaultGenerics>(
channel: Channel<StreamChatGenerics>,
) => {
if (!channel) return false;
const member = channel.state.membership;
return !!member?.archived_at;
};
/**
* A utility that tells us whether we should consider archived channels or not based
* on filters. Will return true only if filters.archived exists and is a boolean value.
* @param filters
*/
export const shouldConsiderArchivedChannels = <StreamChatGenerics extends ExtendableGenerics = DefaultGenerics>(
filters: ChannelFilters<StreamChatGenerics>,
) => {
if (!filters) return false;
return typeof filters.archived === 'boolean';
};
/**
* Extracts the value of the sort parameter at a given index, for a targeted key. Can
* handle both array and object versions of sort. Will return null if the index/key
* combination does not exist.
* @param atIndex - the index at which we'll examine the sort value, if it's an array one
* @param sort - the sort value - both array and object notations are accepted
* @param targetKey - the target key which needs to exist for the sort at a certain index
*/
export const extractSortValue = <StreamChatGenerics extends ExtendableGenerics = DefaultGenerics>({
atIndex,
sort,
targetKey,
}: {
atIndex: number;
targetKey: keyof ChannelSortBase<StreamChatGenerics>;
sort?: ChannelSort<StreamChatGenerics>;
}) => {
if (!sort) return null;
let option: null | ChannelSortBase<StreamChatGenerics> = null;
if (Array.isArray(sort)) {
option = sort[atIndex] ?? null;
} else {
let index = 0;
for (const key in sort) {
if (index !== atIndex) {
index++;
continue;
}
if (key !== targetKey) {
return null;
}
option = sort;
break;
}
}
return option?.[targetKey] ?? null;
};
/**
* Returns true only if `{ pinned_at: -1 }` or `{ pinned_at: 1 }` option is first within the `sort` array.
*/
export const shouldConsiderPinnedChannels = <StreamChatGenerics extends ExtendableGenerics = DefaultGenerics>(
sort: ChannelSort<StreamChatGenerics>,
) => {
const value = findPinnedAtSortOrder({ sort });
if (typeof value !== 'number') return false;
return Math.abs(value) === 1;
};
/**
* Checks whether the sort value of type object contains a pinned_at value or if
* an array sort value type has the first value be an object containing pinned_at.
* @param sort
*/
export const findPinnedAtSortOrder = <StreamChatGenerics extends ExtendableGenerics = DefaultGenerics>({
sort,
}: {
sort: ChannelSort<StreamChatGenerics>;
}) =>
extractSortValue({
atIndex: 0,
sort,
targetKey: 'pinned_at',
});
/**
* Finds the index of the last consecutively pinned channel, starting from the start of the
* array. Will not consider any pinned channels after the contiguous subsequence at the
* start of the array.
* @param channels
*/
export const findLastPinnedChannelIndex = <StreamChatGenerics extends ExtendableGenerics = DefaultGenerics>({
channels,
}: {
channels: Channel<StreamChatGenerics>[];
}) => {
let lastPinnedChannelIndex: number | null = null;
for (const channel of channels) {
if (!isChannelPinned(channel)) break;
if (typeof lastPinnedChannelIndex === 'number') {
lastPinnedChannelIndex++;
} else {
lastPinnedChannelIndex = 0;
}
}
return lastPinnedChannelIndex;
};
/**
* A utility used to move a channel towards the beginning of a list of channels (promote it to a higher position). It
* considers pinned channels in the process if needed and makes sure to only update the list reference if the list
* should actually change. It will try to move the channel as high as it can within the list.
* @param channels - the list of channels we want to modify
* @param channelToMove - the channel we want to promote
* @param channelToMoveIndexWithinChannels - optionally, the index of the channel we want to move if we know it (will skip a manual check)
* @param sort - the sort value used to check for pinned channels
*/
export const promoteChannel = <StreamChatGenerics extends ExtendableGenerics = DefaultGenerics>({
channels,
channelToMove,
channelToMoveIndexWithinChannels,
sort,
}: PromoteChannelParams<StreamChatGenerics>) => {
// get index of channel to move up
const targetChannelIndex =
channelToMoveIndexWithinChannels ?? channels.findIndex((channel) => channel.cid === channelToMove.cid);
const targetChannelExistsWithinList = targetChannelIndex >= 0;
const targetChannelAlreadyAtTheTop = targetChannelIndex === 0;
// pinned channels should not move within the list based on recent activity, channels which
// receive messages and are not pinned should move upwards but only under the last pinned channel
// in the list
const considerPinnedChannels = shouldConsiderPinnedChannels(sort);
const isTargetChannelPinned = isChannelPinned<StreamChatGenerics>(channelToMove);
if (targetChannelAlreadyAtTheTop || (considerPinnedChannels && isTargetChannelPinned)) {
return channels;
}
const newChannels = [...channels];
// target channel index is known, remove it from the list
if (targetChannelExistsWithinList) {
newChannels.splice(targetChannelIndex, 1);
}
// as position of pinned channels has to stay unchanged, we need to
// find last pinned channel in the list to move the target channel after
let lastPinnedChannelIndex: number | null = null;
if (considerPinnedChannels) {
lastPinnedChannelIndex = findLastPinnedChannelIndex({ channels: newChannels });
}
// re-insert it at the new place (to specific index if pinned channels are considered)
newChannels.splice(typeof lastPinnedChannelIndex === 'number' ? lastPinnedChannelIndex + 1 : 0, 0, channelToMove);
return newChannels;
};

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc