diff --git a/src/client.ts b/src/client.ts index 78295737..4f7225c7 100644 --- a/src/client.ts +++ b/src/client.ts @@ -31,7 +31,8 @@ import { // eslint-disable-next-line @typescript-eslint/no-var-requires const pkg = require('../package.json'); -export type UnknownRecord = Record; +export type UR = Record; +export type UnknownRecord = UR; // alias to avoid breaking change export type APIResponse = { duration?: string }; @@ -98,8 +99,8 @@ type AxiosConfig = { url: string; axiosOptions?: axios.AxiosRequestConfig; body?: unknown; - headers?: UnknownRecord; - qs?: UnknownRecord; + headers?: UR; + qs?: UR; serviceName?: string; }; @@ -107,23 +108,34 @@ export type HandlerCallback = (...args: unknown[]) => unknown; export type ForeignIDTimes = { foreignID: string; time: Date | string }; -export type ActivityPartialChanges = Partial & { +export type ActivityPartialChanges = Partial & { id?: string; set?: Partial; unset?: Array>; }; +export type RealTimeMessage = { + deleted: Array; + deleted_foreign_ids: Array<[id: string, time: string]>; + new: Array, 'actor'> & { actor: string | UserType }>; + app_id?: string; + feed?: string; + mark_read?: 'all' | 'current' | Array; + mark_seen?: 'all' | 'current' | Array; + published_at?: string; +}; + /** * Client to connect to Stream api * @class StreamClient */ export class StreamClient< - UserType extends UnknownRecord = UnknownRecord, - ActivityType extends UnknownRecord = UnknownRecord, - CollectionType extends UnknownRecord = UnknownRecord, - ReactionType extends UnknownRecord = UnknownRecord, - ChildReactionType extends UnknownRecord = UnknownRecord, - PersonalizationType extends UnknownRecord = UnknownRecord + UserType extends UR = UR, + ActivityType extends UR = UR, + CollectionType extends UR = UR, + ReactionType extends UR = UR, + ChildReactionType extends UR = UR, + PersonalizationType extends UR = UR > { baseUrl: string; baseAnalyticsUrl: string; @@ -141,7 +153,7 @@ export class StreamClient< group: string; expireTokens: boolean; location: string; - fayeClient: Faye.Client | null; + fayeClient: Faye.Client> | null; browser: boolean; node: boolean; nodeOptions?: { httpAgent: http.Agent; httpsAgent: https.Agent }; @@ -153,9 +165,30 @@ export class StreamClient< >; handlers: Record; - currentUser?: StreamUser; - personalization: Personalization; - collections: Collections; + currentUser?: StreamUser< + UserType, + ActivityType, + CollectionType, + ReactionType, + ChildReactionType, + PersonalizationType + >; + personalization: Personalization< + UserType, + ActivityType, + CollectionType, + ReactionType, + ChildReactionType, + PersonalizationType + >; + collections: Collections< + UserType, + ActivityType, + CollectionType, + ReactionType, + ChildReactionType, + PersonalizationType + >; files: StreamFileStore; images: StreamImageStore; reactions: StreamReaction; @@ -243,20 +276,38 @@ export class StreamClient< ...(this.nodeOptions || {}), }); - this.personalization = new Personalization(this); + this.personalization = new Personalization< + UserType, + ActivityType, + CollectionType, + ReactionType, + ChildReactionType, + PersonalizationType + >(this); if (this.browser && this.usingApiSecret) { throw new FeedError( 'You are publicly sharing your App Secret. Do not expose the App Secret in browsers, "native" mobile apps, or other non-trusted environments.', ); } - this.collections = new Collections(this, this.getOrCreateToken()); - this.files = new StreamFileStore(this, this.getOrCreateToken()); - this.images = new StreamImageStore(this, this.getOrCreateToken()); - this.reactions = new StreamReaction( - this, - this.getOrCreateToken(), - ); + this.collections = new Collections< + UserType, + ActivityType, + CollectionType, + ReactionType, + ChildReactionType, + PersonalizationType + >(this, this.getOrCreateToken()); + this.files = new StreamFileStore(this as StreamClient, this.getOrCreateToken()); + this.images = new StreamImageStore(this as StreamClient, this.getOrCreateToken()); + this.reactions = new StreamReaction< + UserType, + ActivityType, + CollectionType, + ReactionType, + ChildReactionType, + PersonalizationType + >(this, this.getOrCreateToken()); // If we are in a node environment and batchOperations/createRedirectUrl is available add the methods to the prototype of StreamClient if (BatchOperations && !!createRedirectUrl) { @@ -436,9 +487,11 @@ export class StreamClient< */ feed( feedSlug: string, - userId?: string | StreamUser, + userId?: + | string + | StreamUser, token?: string, - ): StreamFeed { + ): StreamFeed { if (userId instanceof StreamUser) userId = userId.id; if (token === undefined) { @@ -449,7 +502,7 @@ export class StreamClient< } } - return new StreamFeed( + return new StreamFeed( this, feedSlug, userId || (this.userId as string), @@ -554,10 +607,16 @@ export class StreamClient< * @private * @return {Faye.Middleware} Faye authorization middleware */ - getFayeAuthorization(): Faye.Middleware { + getFayeAuthorization() { return { - incoming: (message: Faye.Message, callback: Faye.Callback) => callback(message), - outgoing: (message: Faye.Message, callback: Faye.Callback) => { + incoming: ( + message: Faye.Message>, + callback: Faye.Callback>, + ) => callback(message), + outgoing: ( + message: Faye.Message>, + callback: Faye.Callback>, + ) => { if (message.subscription && this.subscriptions[message.subscription]) { const subscription = this.subscriptions[message.subscription]; @@ -583,7 +642,7 @@ export class StreamClient< */ getFayeClient(timeout = 10) { if (this.fayeClient === null) { - this.fayeClient = new Faye.Client(this.fayeUrl, { timeout }); + this.fayeClient = new Faye.Client>(this.fayeUrl, { timeout }); const authExtension = this.getFayeAuthorization(); this.fayeClient.addExtension(authExtension); } @@ -807,8 +866,12 @@ export class StreamClient< return this._getOrCreateToken; } - user(userId: string): StreamUser { - return new StreamUser(this, userId, this.getOrCreateToken()); + user(userId: string) { + return new StreamUser( + this, + userId, + this.getOrCreateToken(), + ); } async setUser(data: UserType) { @@ -819,7 +882,14 @@ export class StreamClient< const body = { ...data }; delete body.id; - const user = await (this.currentUser as StreamUser).getOrCreate(body); + const user = await (this.currentUser as StreamUser< + UserType, + ActivityType, + CollectionType, + ReactionType, + ChildReactionType, + PersonalizationType + >).getOrCreate(body); this.currentUser = user; return user; } diff --git a/src/collections.ts b/src/collections.ts index 6c6b24f4..90a8d2eb 100644 --- a/src/collections.ts +++ b/src/collections.ts @@ -1,4 +1,4 @@ -import { StreamClient, APIResponse, UnknownRecord } from './client'; +import { StreamClient, APIResponse, UR } from './client'; import { SiteError } from './errors'; type BaseCollection = { @@ -7,30 +7,25 @@ type BaseCollection = { id: string; }; -export type CollectionResponse< - CollectionType extends UnknownRecord = UnknownRecord -> = BaseCollection & { +export type CollectionResponse = BaseCollection & { created_at: string; foreign_id: string; updated_at: string; }; -export type NewCollectionEntry< - CollectionType extends UnknownRecord = UnknownRecord -> = BaseCollection & { +export type NewCollectionEntry = BaseCollection & { user_id?: string; }; -export type CollectionAPIResponse = APIResponse & - CollectionResponse; +export type CollectionAPIResponse = APIResponse & CollectionResponse; -export type SelectCollectionAPIResponse = APIResponse & { +export type SelectCollectionAPIResponse = APIResponse & { response: { data: CollectionResponse[]; }; }; -export type UpsertCollectionAPIResponse = APIResponse & { +export type UpsertCollectionAPIResponse = APIResponse & { data: { [key: string]: { data: CollectionType; @@ -39,15 +34,27 @@ export type UpsertCollectionAPIResponse { +export class CollectionEntry< + UserType extends UR = UR, + ActivityType extends UR = UR, + CollectionType extends UR = UR, + ReactionType extends UR = UR, + ChildReactionType extends UR = UR, + PersonalizationType extends UR = UR +> { id: string; collection: string; - store: Collections; // eslint-disable-line no-use-before-define + store: Collections; // eslint-disable-line no-use-before-define data: CollectionType | null; full?: unknown; - // eslint-disable-next-line no-use-before-define - constructor(store: Collections, collection: string, id: string, data: CollectionType) { + constructor( + // eslint-disable-next-line no-use-before-define + store: Collections, + collection: string, + id: string, + data: CollectionType, + ) { this.collection = collection; this.store = store; this.id = id; @@ -119,8 +126,15 @@ export class CollectionEntry { - client: StreamClient; +export class Collections< + UserType extends UR = UR, + ActivityType extends UR = UR, + CollectionType extends UR = UR, + ReactionType extends UR = UR, + ChildReactionType extends UR = UR, + PersonalizationType extends UR = UR +> { + client: StreamClient; token: string; /** @@ -130,7 +144,10 @@ export class Collections { * @param {StreamCloudClient} client Stream client this collection is constructed from * @param {string} token JWT token */ - constructor(client: StreamClient, token: string) { + constructor( + client: StreamClient, + token: string, + ) { this.client = client; this.token = token; } @@ -141,7 +158,14 @@ export class Collections { }; entry(collection: string, itemId: string, itemData: CollectionType) { - return new CollectionEntry(this, collection, itemId, itemData); + return new CollectionEntry< + UserType, + ActivityType, + CollectionType, + ReactionType, + ChildReactionType, + PersonalizationType + >(this, collection, itemId, itemData); } /** diff --git a/src/connect.ts b/src/connect.ts index f5b7ec90..8f1911b3 100644 --- a/src/connect.ts +++ b/src/connect.ts @@ -1,4 +1,4 @@ -import { StreamClient, UnknownRecord, ClientOptions } from './client'; +import { StreamClient, UR, ClientOptions } from './client'; /** * Create StreamClient @@ -24,12 +24,12 @@ import { StreamClient, UnknownRecord, ClientOptions } from './client'; * "https://thierry:pass@gestream.io/?app=1" */ export function connect< - UserType extends UnknownRecord = UnknownRecord, - ActivityType extends UnknownRecord = UnknownRecord, - CollectionType extends UnknownRecord = UnknownRecord, - ReactionType extends UnknownRecord = UnknownRecord, - ChildReactionType extends UnknownRecord = UnknownRecord, - PersonalizationType extends UnknownRecord = UnknownRecord + UserType extends UR = UR, + ActivityType extends UR = UR, + CollectionType extends UR = UR, + ReactionType extends UR = UR, + ChildReactionType extends UR = UR, + PersonalizationType extends UR = UR >(apiKey: string, apiSecret: string | null, appId?: string, options?: ClientOptions) { if (typeof process !== 'undefined' && process.env?.STREAM_URL && !apiKey) { const parts = /https:\/\/(\w+):(\w+)@([\w-]*).*\?app_id=(\d+)/.exec(process.env.STREAM_URL) || []; diff --git a/src/feed.ts b/src/feed.ts index 2c54385d..e27375ee 100644 --- a/src/feed.ts +++ b/src/feed.ts @@ -1,13 +1,18 @@ /// import * as Faye from 'faye'; -import { StreamClient, APIResponse, UnknownRecord } from './client'; +import { StreamClient, APIResponse, UR, RealTimeMessage } from './client'; import { StreamUser } from './user'; import { FeedError, SiteError } from './errors'; import utils from './utils'; import { EnrichedReaction } from './reaction'; import { CollectionResponse } from './collections'; +export type FollowStatsOptions = { + followerSlugs?: string[]; + followingSlugs?: string[]; +}; + export type EnrichOptions = { enrich?: boolean; ownReactions?: boolean; // best not to use it, will be removed by client.replaceReactionOptions() @@ -65,38 +70,38 @@ type BaseActivity = ActivityType & { to?: string[]; }; -export type NewActivity = BaseActivity & { +export type NewActivity = BaseActivity & { foreign_id?: string; time?: string; }; -export type UpdateActivity = BaseActivity & { +export type UpdateActivity = BaseActivity & { foreign_id: string; time: string; }; -export type Activity = BaseActivity & { +export type Activity = BaseActivity & { foreign_id: string; id: string; time: string; analytics?: Record; // ranked feeds only - extra_context?: UnknownRecord; + extra_context?: UR; origin?: string; score?: number; // ranked feeds only }; export type ReactionsRecords< - ReactionType extends UnknownRecord = UnknownRecord, - ChildReactionType extends UnknownRecord = UnknownRecord, - UserType extends UnknownRecord = UnknownRecord + ReactionType extends UR = UR, + ChildReactionType extends UR = UR, + UserType extends UR = UR > = Record[]>; export type EnrichedActivity< - UserType extends UnknownRecord = UnknownRecord, - ActivityType extends UnknownRecord = UnknownRecord, - CollectionType extends UnknownRecord = UnknownRecord, - ReactionType extends UnknownRecord = UnknownRecord, - ChildReactionType extends UnknownRecord = UnknownRecord + UserType extends UR = UR, + ActivityType extends UR = UR, + CollectionType extends UR = UR, + ReactionType extends UR = UR, + ChildReactionType extends UR = UR > = Activity & { actor: UserType | string; object: @@ -116,14 +121,14 @@ export type EnrichedActivity< reaction_counts?: Record; }; -export type FlatActivity = Activity; +export type FlatActivity = Activity; export type FlatActivityEnriched< - UserType extends UnknownRecord = UnknownRecord, - ActivityType extends UnknownRecord = UnknownRecord, - CollectionType extends UnknownRecord = UnknownRecord, - ReactionType extends UnknownRecord = UnknownRecord, - ChildReactionType extends UnknownRecord = UnknownRecord + UserType extends UR = UR, + ActivityType extends UR = UR, + CollectionType extends UR = UR, + ReactionType extends UR = UR, + ChildReactionType extends UR = UR > = EnrichedActivity; type BaseAggregatedActivity = { @@ -137,41 +142,40 @@ type BaseAggregatedActivity = { score?: number; }; -export type AggregatedActivity = BaseAggregatedActivity & { +export type AggregatedActivity = BaseAggregatedActivity & { activities: Activity[]; }; export type AggregatedActivityEnriched< - UserType extends UnknownRecord = UnknownRecord, - ActivityType extends UnknownRecord = UnknownRecord, - CollectionType extends UnknownRecord = UnknownRecord, - ReactionType extends UnknownRecord = UnknownRecord, - ChildReactionType extends UnknownRecord = UnknownRecord + UserType extends UR = UR, + ActivityType extends UR = UR, + CollectionType extends UR = UR, + ReactionType extends UR = UR, + ChildReactionType extends UR = UR > = BaseAggregatedActivity & { activities: EnrichedActivity[]; }; type BaseNotificationActivity = { is_read: boolean; is_seen: boolean }; -export type NotificationActivity< - ActivityType extends UnknownRecord = UnknownRecord -> = AggregatedActivity & BaseNotificationActivity; +export type NotificationActivity = AggregatedActivity & + BaseNotificationActivity; export type NotificationActivityEnriched< - UserType extends UnknownRecord = UnknownRecord, - ActivityType extends UnknownRecord = UnknownRecord, - CollectionType extends UnknownRecord = UnknownRecord, - ReactionType extends UnknownRecord = UnknownRecord, - ChildReactionType extends UnknownRecord = UnknownRecord + UserType extends UR = UR, + ActivityType extends UR = UR, + CollectionType extends UR = UR, + ReactionType extends UR = UR, + ChildReactionType extends UR = UR > = BaseNotificationActivity & AggregatedActivityEnriched; export type FeedAPIResponse< - UserType extends UnknownRecord = UnknownRecord, - ActivityType extends UnknownRecord = UnknownRecord, - CollectionType extends UnknownRecord = UnknownRecord, - ReactionType extends UnknownRecord = UnknownRecord, - ChildReactionType extends UnknownRecord = UnknownRecord + UserType extends UR = UR, + ActivityType extends UR = UR, + CollectionType extends UR = UR, + ReactionType extends UR = UR, + ChildReactionType extends UR = UR > = APIResponse & { next: string; results: @@ -188,11 +192,11 @@ export type FeedAPIResponse< }; export type PersonalizationFeedAPIResponse< - UserType extends UnknownRecord = UnknownRecord, - ActivityType extends UnknownRecord = UnknownRecord, - CollectionType extends UnknownRecord = UnknownRecord, - ReactionType extends UnknownRecord = UnknownRecord, - ChildReactionType extends UnknownRecord = UnknownRecord + UserType extends UR = UR, + ActivityType extends UR = UR, + CollectionType extends UR = UR, + ReactionType extends UR = UR, + ChildReactionType extends UR = UR > = APIResponse & { limit: number; next: string; @@ -202,11 +206,11 @@ export type PersonalizationFeedAPIResponse< }; export type GetActivitiesAPIResponse< - UserType extends UnknownRecord = UnknownRecord, - ActivityType extends UnknownRecord = UnknownRecord, - CollectionType extends UnknownRecord = UnknownRecord, - ReactionType extends UnknownRecord = UnknownRecord, - ChildReactionType extends UnknownRecord = UnknownRecord + UserType extends UR = UR, + ActivityType extends UR = UR, + CollectionType extends UR = UR, + ReactionType extends UR = UR, + ChildReactionType extends UR = UR > = APIResponse & { results: | FlatActivity[] @@ -219,13 +223,14 @@ export type GetActivitiesAPIResponse< * @class StreamFeed */ export class StreamFeed< - UserType extends UnknownRecord = UnknownRecord, - ActivityType extends UnknownRecord = UnknownRecord, - CollectionType extends UnknownRecord = UnknownRecord, - ReactionType extends UnknownRecord = UnknownRecord, - ChildReactionType extends UnknownRecord = UnknownRecord + UserType extends UR = UR, + ActivityType extends UR = UR, + CollectionType extends UR = UR, + ReactionType extends UR = UR, + ChildReactionType extends UR = UR, + PersonalizationType extends UR = UR > { - client: StreamClient; + client: StreamClient; token: string; id: string; slug: string; @@ -244,7 +249,12 @@ export class StreamFeed< * @param {string} userId - The user id * @param {string} [token] - The authentication token */ - constructor(client: StreamClient, feedSlug: string, userId: string, token: string) { + constructor( + client: StreamClient, + feedSlug: string, + userId: string, + token: string, + ) { if (!feedSlug || !userId) { throw new FeedError('Please provide a feed slug and user id, ie client.feed("user", "1")'); } @@ -445,7 +455,7 @@ export class StreamFeed< * @example feed.followStats(); * @example feed.followStats({ followerSlugs:['user', 'news'], followingSlugs:['timeline'] }); */ - followStats(options: { followerSlugs?: string[]; followingSlugs?: string[] } = {}) { + followStats(options: FollowStatsOptions = {}) { const qs: { followers: string; following: string; followers_slugs?: string; following_slugs?: string } = { followers: this.id, following: this.id, @@ -531,14 +541,14 @@ export class StreamFeed< * @link https://getstream.io/activity-feeds/docs/node/web_and_mobile/?language=js#subscribe-to-realtime-updates-via-api-client * @method subscribe * @memberof StreamFeed.prototype - * @param {function} callback Callback to call on completion + * @param {function} Faye.Callback> Callback to call on completion * @return {Promise} * @example * feed.subscribe(callback).then(function(){ * console.log('we are now listening to changes'); * }); */ - subscribe(callback: Faye.Callback) { + subscribe(callback: Faye.Callback>) { if (!this.client.appId) { throw new SiteError( 'Missing app id, which is needed to subscribe, use var client = stream.connect(key, secret, appId);', diff --git a/src/personalization.ts b/src/personalization.ts index acb6c94d..6fbb70e0 100644 --- a/src/personalization.ts +++ b/src/personalization.ts @@ -1,4 +1,4 @@ -import { StreamClient, APIResponse, UnknownRecord } from './client'; +import { StreamClient, APIResponse, UR } from './client'; /** * Manage api calls for personalization @@ -6,7 +6,7 @@ import { StreamClient, APIResponse, UnknownRecord } from './client'; * @class Personalization */ -export type PersonalizationAPIResponse = APIResponse & { +export type PersonalizationAPIResponse = APIResponse & { app_id: string; next: string; results: PersonalizationType[]; @@ -15,8 +15,15 @@ export type PersonalizationAPIResponse { - client: StreamClient; +export class Personalization< + UserType extends UR = UR, + ActivityType extends UR = UR, + CollectionType extends UR = UR, + ReactionType extends UR = UR, + ChildReactionType extends UR = UR, + PersonalizationType extends UR = UR +> { + client: StreamClient; /** * Initialize the Personalization class @@ -25,7 +32,9 @@ export class Personalization, + ) { this.client = client; } @@ -59,7 +68,7 @@ export class Personalization>} Promise object. Data that was posted if successful, or an error. * @example client.personalization.post('follow_recommendations', {foo: 'bar', baz: 'qux'}) */ - post(resource: string, options: Record = {}, data: UnknownRecord = {}) { + post(resource: string, options: Record = {}, data: UR = {}) { return this.client.post>({ url: `${resource}/`, serviceName: 'personalization', diff --git a/src/reaction.ts b/src/reaction.ts index d5738188..457beda2 100644 --- a/src/reaction.ts +++ b/src/reaction.ts @@ -1,4 +1,4 @@ -import { StreamClient, APIResponse, UnknownRecord } from './client'; +import { StreamClient, APIResponse, UR } from './client'; import { StreamFeed } from './feed'; import { SiteError } from './errors'; @@ -10,7 +10,7 @@ export type TargetFeedsExtraData = Record; type ReactionBody = { activity_id?: string; // only required for reactions - data?: T | UnknownRecord; + data?: T | UR; id?: string; // api will generate an id if it's missing kind?: string; // required only for add/addChile, not update parent?: string; // only required for child reactions @@ -19,7 +19,7 @@ type ReactionBody = { user_id?: string; // optional when using client tokens }; -export type Reaction = { +export type Reaction = { activity_id: string; created_at: string; data: T; @@ -32,12 +32,12 @@ export type Reaction = { target_feeds_extra_data?: TargetFeedsExtraData; }; -export type ReactionAPIResponse = APIResponse & Reaction; +export type ReactionAPIResponse = APIResponse & Reaction; export type EnrichedReaction< - ReactionType extends UnknownRecord = UnknownRecord, - ChildReactionType extends UnknownRecord = UnknownRecord, - UserType extends UnknownRecord = UnknownRecord + ReactionType extends UR = UR, + ChildReactionType extends UR = UR, + UserType extends UR = UR > = Reaction & { children_counts: Record; latest_children: Record; @@ -47,16 +47,16 @@ export type EnrichedReaction< }; export type EnrichedReactionAPIResponse< - ReactionType extends UnknownRecord = UnknownRecord, - ChildReactionType extends UnknownRecord = UnknownRecord, - UserType extends UnknownRecord = UnknownRecord + ReactionType extends UR = UR, + ChildReactionType extends UR = UR, + UserType extends UR = UR > = APIResponse & EnrichedReaction; export type ReactionFilterAPIResponse< - ReactionType extends UnknownRecord = UnknownRecord, - ChildReactionType extends UnknownRecord = UnknownRecord, - ActivityType extends UnknownRecord = UnknownRecord, - UserType extends UnknownRecord = UnknownRecord + ReactionType extends UR = UR, + ChildReactionType extends UR = UR, + ActivityType extends UR = UR, + UserType extends UR = UR > = APIResponse & { next: string; results: @@ -65,14 +65,42 @@ export type ReactionFilterAPIResponse< activity?: ActivityType; }; +export type ReactionFilterConditions = { + activity_id?: string; + id_gt?: string; + id_gte?: string; + id_lt?: string; + id_lte?: string; + kind?: string; + limit?: number; + reaction_id?: string; + user_id?: string; + with_activity_data?: boolean; +}; + +export type ReactionUpdateOptions = { + targetFeeds?: TargetFeeds; + targetFeedsExtraData?: TargetFeedsExtraData; +}; + +export type ReactionAddOptions = ReactionUpdateOptions & { + id?: string; + userId?: string; +}; + +export type ReactionAddChildOptions = ReactionUpdateOptions & { + userId?: string; +}; + export class StreamReaction< - UserType extends UnknownRecord = UnknownRecord, - ActivityType extends UnknownRecord = UnknownRecord, - CollectionType extends UnknownRecord = UnknownRecord, // eslint-disable-line @typescript-eslint/no-unused-vars - ReactionType extends UnknownRecord = UnknownRecord, - ChildReactionType extends UnknownRecord = UnknownRecord + UserType extends UR = UR, + ActivityType extends UR = UR, + CollectionType extends UR = UR, + ReactionType extends UR = UR, + ChildReactionType extends UR = UR, + PersonalizationType extends UR = UR > { - client: StreamClient; + client: StreamClient; token: string; /** @@ -84,7 +112,10 @@ export class StreamReaction< * @param {string} token JWT token * @example new StreamReaction(client, "eyJhbGciOiJIUzI1...") */ - constructor(client: StreamClient, token: string) { + constructor( + client: StreamClient, + token: string, + ) { this.client = client; this.token = token; } @@ -93,7 +124,7 @@ export class StreamReaction< return `${['reaction', ...args].join('/')}/`; }; - _convertTargetFeeds = (targetFeeds: TargetFeeds = []) => { + _convertTargetFeeds = (targetFeeds: TargetFeeds = []): string[] => { return targetFeeds.map((elem: TargetFeed) => (typeof elem === 'string' ? elem : (elem as StreamFeed).id)); }; @@ -105,7 +136,7 @@ export class StreamReaction< * @param {string} kind kind of reaction * @param {string} activity Activity or an ActivityID * @param {ReactionType} data data related to reaction - * @param {object} [options] + * @param {ReactionAddOptions} [options] * @param {string} [options.id] id associated with reaction * @param {string[]} [options.targetFeeds] an array of feeds to which to send an activity with the reaction * @param {string} [options.userId] useful for adding reaction with server token @@ -118,12 +149,7 @@ export class StreamReaction< kind: string, activity: string | { id: string }, data: ReactionType, - { - id, - targetFeeds = [], - userId, - targetFeedsExtraData, - }: { id?: string; targetFeeds?: TargetFeeds; targetFeedsExtraData?: TargetFeedsExtraData; userId?: string } = {}, + { id, targetFeeds = [], userId, targetFeedsExtraData }: ReactionAddOptions = {}, ) { const body: ReactionBody = { id, @@ -151,7 +177,7 @@ export class StreamReaction< * @param {string} kind kind of reaction * @param {string} reaction Reaction or a ReactionID * @param {ChildReactionType} data data related to reaction - * @param {object} [options] + * @param {ReactionAddChildOptions} [options] * @param {string[]} [options.targetFeeds] an array of feeds to which to send an activity with the reaction * @param {string} [options.userId] useful for adding reaction with server token * @param {object} [options.targetFeedsExtraData] extra data related to target feeds @@ -163,15 +189,7 @@ export class StreamReaction< kind: string, reaction: string | { id: string }, data: ChildReactionType, - { - targetFeeds = [], - userId, - targetFeedsExtraData, - }: { - targetFeeds?: TargetFeeds; - targetFeedsExtraData?: TargetFeedsExtraData; - userId?: string; - } = {}, + { targetFeeds = [], userId, targetFeedsExtraData }: ReactionAddChildOptions = {}, ) { const body: ReactionBody = { parent: reaction instanceof Object ? (reaction as { id: string }).id : reaction, @@ -216,23 +234,12 @@ export class StreamReaction< * @link https://getstream.io/activity-feeds/docs/node/reactions_introduction/?language=js#retrieving-reactions * @method filter * @memberof StreamReaction.prototype - * @param {object} conditions Reaction Id {activity_id|user_id|reaction_id:string, kind:string, limit:integer} + * @param {ReactionFilterConditions} conditions Reaction Id {activity_id|user_id|reaction_id:string, kind:string, limit:integer} * @return {Promise>} * @example reactions.filter({activity_id: "0c7db91c-67f9-11e8-bcd9-fe00a9219401", kind:"like"}) * @example reactions.filter({user_id: "john", kinds:"like"}) */ - filter(conditions: { - activity_id?: string; - id_gt?: string; - id_gte?: string; - id_lt?: string; - id_lte?: string; - kind?: string; - limit?: number; - reaction_id?: string; - user_id?: string; - with_activity_data?: boolean; - }) { + filter(conditions: ReactionFilterConditions) { const { user_id: userId, activity_id: activityId, reaction_id: reactionId, ...qs } = conditions; if (!qs.limit) { qs.limit = 10; @@ -263,7 +270,7 @@ export class StreamReaction< * @memberof StreamReaction.prototype * @param {string} id Reaction Id * @param {ReactionType | ChildReactionType} data Data associated to reaction or childReaction - * @param {object} [options] + * @param {ReactionUpdateOptions} [options] * @param {string[]} [options.targetFeeds] Optional feeds to post the activity to. If you sent this before and don't set it here it will be removed. * @param {object} [options.targetFeedsExtraData] extra data related to target feeds * @return {Promise>} @@ -273,10 +280,7 @@ export class StreamReaction< update( id: string, data: ReactionType | ChildReactionType, - { - targetFeeds = [], - targetFeedsExtraData, - }: { targetFeeds?: string[] | StreamFeed[]; targetFeedsExtraData?: TargetFeedsExtraData } = {}, + { targetFeeds = [], targetFeedsExtraData }: ReactionUpdateOptions = {}, ) { const body: ReactionBody = { data, diff --git a/src/user.ts b/src/user.ts index 583d22e4..8bd24972 100644 --- a/src/user.ts +++ b/src/user.ts @@ -1,6 +1,6 @@ -import { StreamClient, APIResponse, UnknownRecord } from './client'; +import { StreamClient, APIResponse, UR } from './client'; -export type UserAPIResponse = APIResponse & { +export type UserAPIResponse = APIResponse & { created_at: string; data: UserType; id: string; @@ -10,8 +10,15 @@ export type UserAPIResponse = AP following_count?: number; }; -export class StreamUser { - client: StreamClient; +export class StreamUser< + UserType extends UR = UR, + ActivityType extends UR = UR, + CollectionType extends UR = UR, + ReactionType extends UR = UR, + ChildReactionType extends UR = UR, + PersonalizationType extends UR = UR +> { + client: StreamClient; token: string; id: string; data?: UserType; @@ -28,7 +35,11 @@ export class StreamUser { * @param {string} userAuthToken JWT token * @example new StreamUser(client, "123", "eyJhbGciOiJIUzI1...") */ - constructor(client: StreamClient, userId: string, userAuthToken: string) { + constructor( + client: StreamClient, + userId: string, + userAuthToken: string, + ) { this.client = client; this.id = userId; this.data = undefined; diff --git a/types/modules.d.ts b/types/modules.d.ts index a9aa07f1..5f1e4415 100644 --- a/types/modules.d.ts +++ b/types/modules.d.ts @@ -1,27 +1,29 @@ declare module 'faye' { - type Message = { - // TODO: generalize - [key: string]: unknown; + type UR = Record; + + type Message = UR & { + channel: string; + clientId?: string; + data?: T; subscription?: string; + successful?: boolean; }; type Subscription = { cancel: () => void; }; - type Callback = (message: Message) => unknown; + type Callback = (message: Message) => unknown; - interface Middleware { - incoming: (message: Message, callback: Callback) => unknown; - outgoing: (message: Message, callback: Callback) => unknown; - } + type Middleware = { + incoming: (message: Message, callback: Callback) => unknown; + outgoing: (message: Message, callback: Callback) => unknown; + }; - export class Client { + export class Client { constructor(url: string, options: { timeout: number }); - - addExtension(extension: Middleware): void; - - subscribe(channel: string, callback: Callback): Promise; + addExtension(extension: Middleware): void; + subscribe(channel: string, callback: Callback): Promise; disconnect(): void; }