chore: prepare JavaScript SDK for npm publish

This commit is contained in:
Mo Elzubeir
2026-05-29 13:46:11 -05:00
parent c860cf6d88
commit d820a39223
4 changed files with 91 additions and 3 deletions
+32
View File
@@ -4,8 +4,11 @@ import { type Cache, MemoryCache, NoopCache } from './cache';
/** Sentiment label assigned to a mention by Socialhose. */
export type Sentiment = 'positive' | 'negative' | 'neutral';
/** Count distribution across positive, negative, and neutral sentiment labels. */
export type SentimentSplit = { positive: number; negative: number; neutral: number };
/** Primitive value accepted as a query-string parameter. Nullish and empty-string values are omitted. */
export type QueryValue = string | number | boolean | null | undefined;
/** Query-string parameter map used by low-level GET calls. */
export type QueryParams = Record<string, QueryValue>;
/** Configuration for {@link SocialhoseClient}. */
@@ -34,6 +37,7 @@ export interface RequestOptions {
headers?: Record<string, string>;
}
/** Campaign metadata returned by `/campaigns/`. */
export interface Campaign {
id: string;
name: string;
@@ -44,6 +48,7 @@ export interface Campaign {
tags: string[];
}
/** Aggregate metrics returned by `/analytics/overview/`. */
export interface Overview {
total_mentions: number;
total_authors: number;
@@ -66,6 +71,7 @@ export interface Overview {
};
}
/** One time bucket returned by `/analytics/timeline/`. */
export interface TimelinePoint {
date: string;
count: number;
@@ -73,6 +79,7 @@ export interface TimelinePoint {
engagement: number;
}
/** Campaign comparison row returned by `/analytics/share-of-voice/`. */
export interface ShareOfVoiceItem {
campaign_id: string;
name: string;
@@ -82,18 +89,21 @@ export interface ShareOfVoiceItem {
sentiment: SentimentSplit;
}
/** Mention and engagement totals for one platform. */
export interface PlatformStat {
platform: string;
count: number;
engagement: number;
}
/** Top-keyword row with mention count and sentiment split. */
export interface KeywordStat {
keyword: string;
count: number;
sentiment: SentimentSplit;
}
/** Trending-keyword row comparing current and previous mention volume. */
export interface TrendingItem {
keyword: string;
count: number;
@@ -101,6 +111,7 @@ export interface TrendingItem {
change_pct: number;
}
/** Compact high-impact mention returned by the analytics top-mentions endpoint. */
export interface TopMention {
id: string;
platform: string;
@@ -115,6 +126,7 @@ export interface TopMention {
content_preview: string;
}
/** Full mention record returned by `/mentions/`, including content, engagement, metadata, and author profile. */
export interface Mention {
id: string;
platform: string;
@@ -147,6 +159,7 @@ export interface Mention {
};
}
/** Mailing-list metadata returned by `/mailing-lists/`. */
export interface MailingList {
id: string;
campaign_id: string;
@@ -157,6 +170,7 @@ export interface MailingList {
email_template: string;
}
/** Invitation state returned when adding a mailing-list member. */
export interface MailingListInvitation {
id: string;
email: string;
@@ -169,14 +183,17 @@ export interface MailingListInvitation {
accepted_at: string | null;
}
/** Normalized mailing-list invite outcome. */
export type InviteOutcome = 'invited' | 'already' | 'error';
/** Normalized response from {@link SocialhoseClient.inviteMailingListMember}. */
export interface InviteResult {
outcome: InviteOutcome;
invitation?: MailingListInvitation;
detail?: string;
}
/** Standard paginated response envelope used by list endpoints. */
export interface Paginated<T> {
count: number;
next: string | null;
@@ -184,6 +201,7 @@ export interface Paginated<T> {
results: T[];
}
/** Common filters accepted by analytics endpoints. Values are passed through as query parameters. */
export interface AnalyticsFilters {
campaign_ids?: string;
date_from?: string;
@@ -192,6 +210,7 @@ export interface AnalyticsFilters {
sentiments?: string;
}
/** Filters accepted by `/mentions/`, extending common analytics filters with pagination, search, and ordering. */
export interface MentionFilters extends AnalyticsFilters {
page?: number;
content_search?: string;
@@ -207,11 +226,13 @@ export interface MentionFilters extends AnalyticsFilters {
// when count <= 20, which covers most entities at current volume); a few
// count-only requests add precise week-over-week momentum.
/** Platform count pair used by entity analytics. */
export interface PlatformShare {
platform: string;
count: number;
}
/** Compact analytics for one term from a single mention search. */
export interface EntityBrief {
term: string;
total: number;
@@ -221,6 +242,7 @@ export interface EntityBrief {
sample: Mention[]; // up to 20, ordered by engagement
}
/** Rich entity dashboard assembled from multiple mention-search facets. */
export interface EntityStats extends EntityBrief {
recent: Mention[]; // up to 20, newest first
recent7d: number;
@@ -391,6 +413,7 @@ export class SocialhoseClient {
return { ...d, total_mentions: num(d.total_mentions), total_authors: num(d.total_authors) };
}
/** Fetch analytics time-series buckets; defaults to daily interval. */
async getTimeline(
filters: AnalyticsFilters & { interval?: 'day' | 'week' | 'month' } = {},
options: RequestOptions = {},
@@ -403,6 +426,7 @@ export class SocialhoseClient {
return d.series ?? [];
}
/** Fetch overall and platform-specific sentiment distributions. */
getSentiment(
filters: AnalyticsFilters = {},
options: RequestOptions = {},
@@ -410,6 +434,7 @@ export class SocialhoseClient {
return this.get('/analytics/sentiment/', filters as QueryParams, options);
}
/** Fetch campaign share-of-voice comparison metrics. */
getShareOfVoice(
filters: AnalyticsFilters = {},
options: RequestOptions = {},
@@ -417,11 +442,13 @@ export class SocialhoseClient {
return this.get('/analytics/share-of-voice/', filters as QueryParams, options);
}
/** Fetch mention and engagement totals grouped by platform. */
async getPlatforms(filters: AnalyticsFilters = {}, options: RequestOptions = {}): Promise<PlatformStat[]> {
const d = await this.get<{ platforms?: PlatformStat[] }>('/analytics/platforms/', filters as QueryParams, options);
return d.platforms ?? [];
}
/** Fetch top keywords; defaults to 12 items. */
async getTopKeywords(
filters: AnalyticsFilters & { limit?: number } = {},
options: RequestOptions = {},
@@ -434,6 +461,7 @@ export class SocialhoseClient {
return d.keywords ?? [];
}
/** Fetch trending keywords; defaults to 8 items. */
async getTrending(
filters: AnalyticsFilters & { limit?: number } = {},
options: RequestOptions = {},
@@ -446,6 +474,7 @@ export class SocialhoseClient {
return d.trending ?? [];
}
/** Fetch top mentions by impact; defaults to 6 items. */
async getTopMentions(
filters: AnalyticsFilters & { limit?: number } = {},
options: RequestOptions = {},
@@ -458,6 +487,7 @@ export class SocialhoseClient {
return d.mentions ?? [];
}
/** Fetch a paginated mention page with campaign/date/platform/sentiment/search/order filters. */
getMentions(
filters: MentionFilters = {},
optionsOrRevalidate: RequestOptions | number = {},
@@ -466,11 +496,13 @@ export class SocialhoseClient {
return this.get<Paginated<Mention>>('/mentions/', { page: 1, ...filters }, options);
}
/** Fetch the first page of mailing lists. */
async getMailingLists(options: RequestOptions = {}): Promise<MailingList[]> {
const d = await this.get<Paginated<MailingList>>('/mailing-lists/', { page: 1 }, options);
return d.results;
}
/** Invite a recipient to a mailing list and normalize invited/already/error outcomes. */
async inviteMailingListMember(
listId: string,
invite: { email: string; first_name?: string; last_name?: string; invitation_message?: string },