From 935b79cbc53df2de0c944bf41674fbeaf3e5425a Mon Sep 17 00:00:00 2001 From: activitysmith-bot Date: Fri, 10 Jul 2026 11:58:37 +0000 Subject: [PATCH 01/11] chore: regenerate SDK --- generated/apis/AppIconBadgesApi.ts | 81 +++++++++++++++++++++++ generated/apis/index.ts | 1 + generated/models/index.ts | 103 +++++++++++++++++++---------- 3 files changed, 150 insertions(+), 35 deletions(-) create mode 100644 generated/apis/AppIconBadgesApi.ts diff --git a/generated/apis/AppIconBadgesApi.ts b/generated/apis/AppIconBadgesApi.ts new file mode 100644 index 0000000..f78cbe1 --- /dev/null +++ b/generated/apis/AppIconBadgesApi.ts @@ -0,0 +1,81 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * ActivitySmith API + * Send push notifications and Live Activities to your own devices via a single API key. + * + * The version of the OpenAPI document: 1.0.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +import * as runtime from '../runtime'; +import type { + AppIconBadgeCountUpdateRequest, + AppIconBadgeCountUpdateResponse, + BadRequestError, + ForbiddenError, + NoRecipientsError, + RateLimitError, +} from '../models/index'; + +export interface UpdateAppIconBadgeCountRequest { + appIconBadgeCountUpdateRequest: AppIconBadgeCountUpdateRequest; +} + +/** + * + */ +export class AppIconBadgesApi extends runtime.BaseAPI { + + /** + * Updates the App Icon Badge Count on devices matched by API key scope and optional target channels. Send `badge: 0` to clear the count. Badge updates are independent of push notifications and do not create a push notification history item. + * Update App Icon Badge Count + */ + async updateAppIconBadgeCountRaw(requestParameters: UpdateAppIconBadgeCountRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + if (requestParameters['appIconBadgeCountUpdateRequest'] == null) { + throw new runtime.RequiredError( + 'appIconBadgeCountUpdateRequest', + 'Required parameter "appIconBadgeCountUpdateRequest" was null or undefined when calling updateAppIconBadgeCount().' + ); + } + + const queryParameters: any = {}; + + const headerParameters: runtime.HTTPHeaders = {}; + + headerParameters['Content-Type'] = 'application/json'; + + if (this.configuration && this.configuration.accessToken) { + const token = this.configuration.accessToken; + const tokenString = await token("apiKeyAuth", []); + + if (tokenString) { + headerParameters["Authorization"] = `Bearer ${tokenString}`; + } + } + const response = await this.request({ + path: `/badge`, + method: 'POST', + headers: headerParameters, + query: queryParameters, + body: requestParameters['appIconBadgeCountUpdateRequest'], + }, initOverrides); + + return new runtime.JSONApiResponse(response); + } + + /** + * Updates the App Icon Badge Count on devices matched by API key scope and optional target channels. Send `badge: 0` to clear the count. Badge updates are independent of push notifications and do not create a push notification history item. + * Update App Icon Badge Count + */ + async updateAppIconBadgeCount(requestParameters: UpdateAppIconBadgeCountRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise { + const response = await this.updateAppIconBadgeCountRaw(requestParameters, initOverrides); + return await response.value(); + } + +} diff --git a/generated/apis/index.ts b/generated/apis/index.ts index f269477..ecb06b5 100644 --- a/generated/apis/index.ts +++ b/generated/apis/index.ts @@ -1,5 +1,6 @@ /* tslint:disable */ /* eslint-disable */ +export * from './AppIconBadgesApi'; export * from './LiveActivitiesApi'; export * from './MetricsApi'; export * from './PushNotificationsApi'; diff --git a/generated/models/index.ts b/generated/models/index.ts index 69b9e93..3d12627 100644 --- a/generated/models/index.ts +++ b/generated/models/index.ts @@ -6,7 +6,6 @@ * @interface ActivityMetric */ export interface ActivityMetric { - [key: string]: any | any; /** * * @type {string} @@ -63,7 +62,6 @@ export type ActivityMetricValue = number | string; * @interface AlertPayload */ export interface AlertPayload { - [key: string]: any | any; /** * * @type {string} @@ -77,13 +75,74 @@ export interface AlertPayload { */ body?: string; } +/** + * App Icon Badge Count update. Send badge 0 to clear the count. + * @export + * @interface AppIconBadgeCountUpdateRequest + */ +export interface AppIconBadgeCountUpdateRequest { + /** + * The count to show on the ActivitySmith app icon. Send 0 to clear it. + * @type {number} + * @memberof AppIconBadgeCountUpdateRequest + */ + badge: number; + /** + * + * @type {ChannelTarget} + * @memberof AppIconBadgeCountUpdateRequest + */ + target?: ChannelTarget; +} +/** + * + * @export + * @interface AppIconBadgeCountUpdateResponse + */ +export interface AppIconBadgeCountUpdateResponse { + /** + * + * @type {boolean} + * @memberof AppIconBadgeCountUpdateResponse + */ + success: boolean; + /** + * + * @type {number} + * @memberof AppIconBadgeCountUpdateResponse + */ + badge: number; + /** + * + * @type {number} + * @memberof AppIconBadgeCountUpdateResponse + */ + devices_notified: number; + /** + * + * @type {number} + * @memberof AppIconBadgeCountUpdateResponse + */ + users_notified: number; + /** + * + * @type {Array} + * @memberof AppIconBadgeCountUpdateResponse + */ + effective_channel_slugs: Array; + /** + * + * @type {string} + * @memberof AppIconBadgeCountUpdateResponse + */ + timestamp: string; +} /** * * @export * @interface BadRequestError */ export interface BadRequestError { - [key: string]: any | any; /** * * @type {string} @@ -103,7 +162,6 @@ export interface BadRequestError { * @interface ChannelTarget */ export interface ChannelTarget { - [key: string]: any | any; /** * Channel slugs. When omitted, API key scope determines recipients. * @type {Array} @@ -117,7 +175,6 @@ export interface ChannelTarget { * @interface ContentStateEnd */ export interface ContentStateEnd { - [key: string]: any | any; /** * * @type {string} @@ -305,7 +362,6 @@ export type ContentStateEndStepColorsEnum = typeof ContentStateEndStepColorsEnum * @interface ContentStateStart */ export interface ContentStateStart { - [key: string]: any | any; /** * * @type {string} @@ -487,7 +543,6 @@ export type ContentStateStartStepColorsEnum = typeof ContentStateStartStepColors * @interface ContentStateUpdate */ export interface ContentStateUpdate { - [key: string]: any | any; /** * * @type {string} @@ -669,7 +724,6 @@ export type ContentStateUpdateStepColorsEnum = typeof ContentStateUpdateStepColo * @interface ForbiddenError */ export interface ForbiddenError { - [key: string]: any | any; /** * * @type {string} @@ -716,10 +770,10 @@ export interface LiveActivityAction { method?: LiveActivityWebhookMethod; /** * Optional webhook payload body. Used only when type=webhook. - * @type {{ [key: string]: any; }} + * @type {object} * @memberof LiveActivityAction */ - body?: { [key: string]: any; }; + body?: object; } /** @@ -738,7 +792,6 @@ export type LiveActivityActionType = typeof LiveActivityActionType[keyof typeof * @interface LiveActivityAlertBadge */ export interface LiveActivityAlertBadge { - [key: string]: any | any; /** * * @type {string} @@ -758,7 +811,6 @@ export interface LiveActivityAlertBadge { * @interface LiveActivityAlertIcon */ export interface LiveActivityAlertIcon { - [key: string]: any | any; /** * Apple SF Symbol name. * @type {string} @@ -797,7 +849,6 @@ export type LiveActivityColor = typeof LiveActivityColor[keyof typeof LiveActivi * @interface LiveActivityEndRequest */ export interface LiveActivityEndRequest { - [key: string]: any | any; /** * * @type {string} @@ -829,7 +880,6 @@ export interface LiveActivityEndRequest { * @interface LiveActivityEndResponse */ export interface LiveActivityEndResponse { - [key: string]: any | any; /** * * @type {boolean} @@ -867,7 +917,6 @@ export interface LiveActivityEndResponse { * @interface LiveActivityLimitError */ export interface LiveActivityLimitError { - [key: string]: any | any; /** * * @type {string} @@ -899,7 +948,6 @@ export interface LiveActivityLimitError { * @interface LiveActivityStartRequest */ export interface LiveActivityStartRequest { - [key: string]: any | any; /** * * @type {ContentStateStart} @@ -937,7 +985,6 @@ export interface LiveActivityStartRequest { * @interface LiveActivityStartResponse */ export interface LiveActivityStartResponse { - [key: string]: any | any; /** * * @type {boolean} @@ -981,7 +1028,6 @@ export interface LiveActivityStartResponse { * @interface LiveActivityStreamDeleteRequest */ export interface LiveActivityStreamDeleteRequest { - [key: string]: any | any; /** * * @type {StreamContentState} @@ -1013,7 +1059,6 @@ export interface LiveActivityStreamDeleteRequest { * @interface LiveActivityStreamDeleteResponse */ export interface LiveActivityStreamDeleteResponse { - [key: string]: any | any; /** * * @type {boolean} @@ -1073,7 +1118,6 @@ export type LiveActivityStreamDeleteResponseOperationEnum = typeof LiveActivityS * @interface LiveActivityStreamPutResponse */ export interface LiveActivityStreamPutResponse { - [key: string]: any | any; /** * * @type {boolean} @@ -1155,7 +1199,6 @@ export type LiveActivityStreamPutResponseOperationEnum = typeof LiveActivityStre * @interface LiveActivityStreamRequest */ export interface LiveActivityStreamRequest { - [key: string]: any | any; /** * * @type {StreamContentState} @@ -1199,7 +1242,6 @@ export interface LiveActivityStreamRequest { * @interface LiveActivityUpdateRequest */ export interface LiveActivityUpdateRequest { - [key: string]: any | any; /** * * @type {string} @@ -1231,7 +1273,6 @@ export interface LiveActivityUpdateRequest { * @interface LiveActivityUpdateResponse */ export interface LiveActivityUpdateResponse { - [key: string]: any | any; /** * * @type {boolean} @@ -1280,7 +1321,6 @@ export type LiveActivityWebhookMethod = typeof LiveActivityWebhookMethod[keyof t * @interface MetricError */ export interface MetricError { - [key: string]: any | any; /** * * @type {string} @@ -1300,7 +1340,6 @@ export interface MetricError { * @interface MetricValueUpdateRequest */ export interface MetricValueUpdateRequest { - [key: string]: any | any; /** * * @type {MetricValueUpdateRequestValue} @@ -1326,7 +1365,6 @@ export type MetricValueUpdateRequestValue = number | string; * @interface MetricValueUpdateResponse */ export interface MetricValueUpdateResponse { - [key: string]: any | any; /** * * @type {boolean} @@ -1340,7 +1378,6 @@ export interface MetricValueUpdateResponse { * @interface NoRecipientsError */ export interface NoRecipientsError { - [key: string]: any | any; /** * * @type {string} @@ -1366,7 +1403,6 @@ export interface NoRecipientsError { * @interface NotFoundError */ export interface NotFoundError { - [key: string]: any | any; /** * * @type {string} @@ -1413,10 +1449,10 @@ export interface PushNotificationAction { method?: PushNotificationWebhookMethod; /** * Optional webhook payload body. Used only when type=webhook. - * @type {{ [key: string]: any; }} + * @type {object} * @memberof PushNotificationAction */ - body?: { [key: string]: any; }; + body?: object; } /** @@ -1474,10 +1510,10 @@ export interface PushNotificationRequest { actions?: Array; /** * - * @type {{ [key: string]: any; }} + * @type {object} * @memberof PushNotificationRequest */ - payload?: { [key: string]: any; }; + payload?: object; /** * * @type {number} @@ -1503,7 +1539,6 @@ export interface PushNotificationRequest { * @interface PushNotificationResponse */ export interface PushNotificationResponse { - [key: string]: any | any; /** * * @type {boolean} @@ -1552,7 +1587,6 @@ export type PushNotificationWebhookMethod = typeof PushNotificationWebhookMethod * @interface RateLimitError */ export interface RateLimitError { - [key: string]: any | any; /** * * @type {string} @@ -1578,7 +1612,6 @@ export type SendPushNotification429Response = LiveActivityLimitError | RateLimit * @interface StreamContentState */ export interface StreamContentState { - [key: string]: any | any; /** * * @type {string} From 5a57b90e5818ab5e0d9417a66a1ccab0c8f38992 Mon Sep 17 00:00:00 2001 From: bardonadam Date: Fri, 10 Jul 2026 19:02:44 +0700 Subject: [PATCH 02/11] feat: add app icon badge resource --- README.md | 26 ++++++++++++++++++++ src/ActivitySmith.ts | 54 ++++++++++++++++++++++++++++++++++++++++- tests/resources.test.js | 40 ++++++++++++++++++++++++++++++ 3 files changed, 119 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index bf604c2..3e72d1b 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,8 @@ See [API reference](https://activitysmith.com/docs/api-reference/introduction) - [Send a Push Notification](#send-a-push-notification) - [Rich Push Notifications with Media](#rich-push-notifications-with-media) - [Actionable Push Notifications](#actionable-push-notifications) +- [App Icon Badge Count](#app-icon-badge-count) + - [Update App Icon Badge Count](#update-app-icon-badge-count) - [Live Activities](#live-activities) - [Start & Update Live Activity](#start--update-live-activity) - [End Live Activity](#end-live-activity) @@ -131,6 +133,30 @@ await activitysmith.notifications.send({ }); ``` +## App Icon Badge Count + +Set the number shown on the ActivitySmith app icon across devices in your API key's account scope. This is separate from push notifications. + +### Update App Icon Badge Count + +```ts +await activitysmith.appIconBadge.update(12); +``` + +Pass `0` to clear the count: + +```ts +await activitysmith.appIconBadge.update(0); +``` + +Use `channels` to update only devices in selected channels: + +```ts +await activitysmith.appIconBadge.update(3, { + channels: ["sales", "customer-success"], +}); +``` + ## Live Activities There are six types of Live Activities: diff --git a/src/ActivitySmith.ts b/src/ActivitySmith.ts index f2aaffe..dac93e5 100644 --- a/src/ActivitySmith.ts +++ b/src/ActivitySmith.ts @@ -1,4 +1,10 @@ -import { Configuration, PushNotificationsApi, LiveActivitiesApi, MetricsApi } from "../generated/index"; +import { + AppIconBadgesApi, + Configuration, + LiveActivitiesApi, + MetricsApi, + PushNotificationsApi, +} from "../generated/index"; const SDK_VERSION = "1.8.0"; const SDK_HEADER_NAME = "X-ActivitySmith-SDK"; @@ -26,6 +32,11 @@ type MetricUpdateRequestBody = MetricUpdateParameters["metricValueUpdateRequest" type MetricValue = MetricUpdateRequestBody["value"]; type MetricUpdateOptions = Omit; type MetricInitOverrides = Parameters[1]; +type AppIconBadgeUpdateParameters = Parameters[0]; +type AppIconBadgeRawParameters = Parameters[0]; +type AppIconBadgeRequestBody = AppIconBadgeUpdateParameters["appIconBadgeCountUpdateRequest"]; +type AppIconBadgeUpdateOptions = Omit & { channels?: string[] }; +type AppIconBadgeInitOverrides = Parameters[1]; type ChannelTargetInput = { channels?: string[] }; type PushSendRequest = PushRequestBody & { channels?: string[] }; @@ -346,6 +357,45 @@ export class MetricsResource { } } +export class AppIconBadgeResource { + private readonly api: AppIconBadgesApi; + + constructor(api: AppIconBadgesApi) { + this.api = api; + } + + update( + badge: number, + options: AppIconBadgeUpdateOptions = {}, + initOverrides?: AppIconBadgeInitOverrides, + ) { + return this.api.updateAppIconBadgeCount( + { + appIconBadgeCountUpdateRequest: withTargetChannels({ + badge, + ...options, + }) as AppIconBadgeRequestBody, + }, + initOverrides, + ); + } + + // Backward-compatible generated-style aliases. + updateAppIconBadgeCount( + requestParameters: AppIconBadgeUpdateParameters, + initOverrides?: AppIconBadgeInitOverrides, + ) { + return this.api.updateAppIconBadgeCount(requestParameters, initOverrides); + } + + updateAppIconBadgeCountRaw( + requestParameters: AppIconBadgeRawParameters, + initOverrides?: AppIconBadgeInitOverrides, + ) { + return this.api.updateAppIconBadgeCountRaw(requestParameters, initOverrides); + } +} + export class ActivitySmith { public static readonly liveActivityTypes = LiveActivityTypes; public static readonly contentState = contentState; @@ -355,6 +405,7 @@ export class ActivitySmith { public readonly notifications: NotificationsResource; public readonly liveActivities: LiveActivitiesResource; public readonly metrics: MetricsResource; + public readonly appIconBadge: AppIconBadgeResource; constructor(opts: ActivitySmithOptions) { if (!opts?.apiKey) { @@ -372,5 +423,6 @@ export class ActivitySmith { this.notifications = new NotificationsResource(new PushNotificationsApi(config)); this.liveActivities = new LiveActivitiesResource(new LiveActivitiesApi(config)); this.metrics = new MetricsResource(new MetricsApi(config)); + this.appIconBadge = new AppIconBadgeResource(new AppIconBadgesApi(config)); } } diff --git a/tests/resources.test.js b/tests/resources.test.js index 4d88e81..f53a76c 100644 --- a/tests/resources.test.js +++ b/tests/resources.test.js @@ -158,6 +158,46 @@ describe("resource wrappers", () => { ).toThrow("ActivitySmith: media cannot be combined with actions"); }); + it("passes zero through to clear the app icon badge count", async () => { + const ActivitySmith = require("../dist/src/index.js"); + const generated = require("../dist/generated/index.js"); + + const updateSpy = vi + .spyOn(generated.AppIconBadgesApi.prototype, "updateAppIconBadgeCount") + .mockResolvedValue({ success: true, badge: 0 }); + + const client = new ActivitySmith({ apiKey: "test" }); + const result = await client.appIconBadge.update(0); + + expect(result).toEqual({ success: true, badge: 0 }); + expect(updateSpy).toHaveBeenCalledWith( + { appIconBadgeCountUpdateRequest: { badge: 0 } }, + undefined, + ); + }); + + it("maps top-level channels to target.channels for appIconBadge.update", async () => { + const ActivitySmith = require("../dist/src/index.js"); + const generated = require("../dist/generated/index.js"); + + const updateSpy = vi + .spyOn(generated.AppIconBadgesApi.prototype, "updateAppIconBadgeCount") + .mockResolvedValue({ success: true, badge: 3 }); + + const client = new ActivitySmith({ apiKey: "test" }); + await client.appIconBadge.update(3, { channels: ["sales", "customer-success"] }); + + expect(updateSpy).toHaveBeenCalledWith( + { + appIconBadgeCountUpdateRequest: { + badge: 3, + target: { channels: ["sales", "customer-success"] }, + }, + }, + undefined, + ); + }); + it("wraps live activity payloads for short methods", async () => { const ActivitySmith = require("../dist/src/index.js"); const generated = require("../dist/generated/index.js"); From 661f434ae13d277ca92f1eae04b561ef69dc7149 Mon Sep 17 00:00:00 2001 From: bardonadam Date: Fri, 10 Jul 2026 20:36:16 +0700 Subject: [PATCH 03/11] feat: simplify badge count setter --- README.md | 53 +++++++++++++++---------------- src/ActivitySmith.ts | 69 ++++++++++++++--------------------------- tests/resources.test.js | 6 ++-- 3 files changed, 54 insertions(+), 74 deletions(-) diff --git a/README.md b/README.md index 3e72d1b..128071b 100644 --- a/README.md +++ b/README.md @@ -14,8 +14,6 @@ See [API reference](https://activitysmith.com/docs/api-reference/introduction) - [Send a Push Notification](#send-a-push-notification) - [Rich Push Notifications with Media](#rich-push-notifications-with-media) - [Actionable Push Notifications](#actionable-push-notifications) -- [App Icon Badge Count](#app-icon-badge-count) - - [Update App Icon Badge Count](#update-app-icon-badge-count) - [Live Activities](#live-activities) - [Start & Update Live Activity](#start--update-live-activity) - [End Live Activity](#end-live-activity) @@ -24,6 +22,7 @@ See [API reference](https://activitysmith.com/docs/api-reference/introduction) - [Live Activity Colors](#live-activity-colors) - [Channels](#channels) - [Widgets](#widgets) +- [App Icon Badge Count](#app-icon-badge-count) ## Installation @@ -133,30 +132,6 @@ await activitysmith.notifications.send({ }); ``` -## App Icon Badge Count - -Set the number shown on the ActivitySmith app icon across devices in your API key's account scope. This is separate from push notifications. - -### Update App Icon Badge Count - -```ts -await activitysmith.appIconBadge.update(12); -``` - -Pass `0` to clear the count: - -```ts -await activitysmith.appIconBadge.update(0); -``` - -Use `channels` to update only devices in selected channels: - -```ts -await activitysmith.appIconBadge.update(3, { - channels: ["sales", "customer-success"], -}); -``` - ## Live Activities There are six types of Live Activities: @@ -530,6 +505,32 @@ String metric values work too. await activitysmith.metrics.update("prod.status", "healthy"); ``` +## App Icon Badge Count + +

+ ActivitySmith app icon with an App Icon Badge Count +

+ +Keep the numbers you care about on your ActivitySmith app icon. Show MRR, a customer count, a stock price, or any other value you want to keep in view. + +```ts +await activitysmith.badgeCount(12); +``` + +Pass `0` to clear the badge. + +```ts +await activitysmith.badgeCount(0); +``` + +To target specific devices, pass their channel slugs in `channels`. + +```ts +await activitysmith.badgeCount(3, { + channels: ["sales", "customer-success"], +}); +``` + ## Error Handling ```ts diff --git a/src/ActivitySmith.ts b/src/ActivitySmith.ts index dac93e5..adcd1c1 100644 --- a/src/ActivitySmith.ts +++ b/src/ActivitySmith.ts @@ -32,14 +32,16 @@ type MetricUpdateRequestBody = MetricUpdateParameters["metricValueUpdateRequest" type MetricValue = MetricUpdateRequestBody["value"]; type MetricUpdateOptions = Omit; type MetricInitOverrides = Parameters[1]; -type AppIconBadgeUpdateParameters = Parameters[0]; -type AppIconBadgeRawParameters = Parameters[0]; -type AppIconBadgeRequestBody = AppIconBadgeUpdateParameters["appIconBadgeCountUpdateRequest"]; -type AppIconBadgeUpdateOptions = Omit & { channels?: string[] }; +type AppIconBadgeRequestBody = + Parameters[0]["appIconBadgeCountUpdateRequest"]; type AppIconBadgeInitOverrides = Parameters[1]; type ChannelTargetInput = { channels?: string[] }; type PushSendRequest = PushRequestBody & { channels?: string[] }; +export type BadgeCountOptions = { + channels?: string[]; +}; + const LiveActivityTypes = { segmentedProgress: "segmented_progress", progress: "progress", @@ -357,45 +359,6 @@ export class MetricsResource { } } -export class AppIconBadgeResource { - private readonly api: AppIconBadgesApi; - - constructor(api: AppIconBadgesApi) { - this.api = api; - } - - update( - badge: number, - options: AppIconBadgeUpdateOptions = {}, - initOverrides?: AppIconBadgeInitOverrides, - ) { - return this.api.updateAppIconBadgeCount( - { - appIconBadgeCountUpdateRequest: withTargetChannels({ - badge, - ...options, - }) as AppIconBadgeRequestBody, - }, - initOverrides, - ); - } - - // Backward-compatible generated-style aliases. - updateAppIconBadgeCount( - requestParameters: AppIconBadgeUpdateParameters, - initOverrides?: AppIconBadgeInitOverrides, - ) { - return this.api.updateAppIconBadgeCount(requestParameters, initOverrides); - } - - updateAppIconBadgeCountRaw( - requestParameters: AppIconBadgeRawParameters, - initOverrides?: AppIconBadgeInitOverrides, - ) { - return this.api.updateAppIconBadgeCountRaw(requestParameters, initOverrides); - } -} - export class ActivitySmith { public static readonly liveActivityTypes = LiveActivityTypes; public static readonly contentState = contentState; @@ -405,7 +368,7 @@ export class ActivitySmith { public readonly notifications: NotificationsResource; public readonly liveActivities: LiveActivitiesResource; public readonly metrics: MetricsResource; - public readonly appIconBadge: AppIconBadgeResource; + private readonly appIconBadgesApi: AppIconBadgesApi; constructor(opts: ActivitySmithOptions) { if (!opts?.apiKey) { @@ -423,6 +386,22 @@ export class ActivitySmith { this.notifications = new NotificationsResource(new PushNotificationsApi(config)); this.liveActivities = new LiveActivitiesResource(new LiveActivitiesApi(config)); this.metrics = new MetricsResource(new MetricsApi(config)); - this.appIconBadge = new AppIconBadgeResource(new AppIconBadgesApi(config)); + this.appIconBadgesApi = new AppIconBadgesApi(config); + } + + badgeCount( + badge: number, + options: BadgeCountOptions = {}, + initOverrides?: AppIconBadgeInitOverrides, + ) { + return this.appIconBadgesApi.updateAppIconBadgeCount( + { + appIconBadgeCountUpdateRequest: withTargetChannels({ + badge, + ...options, + }) as AppIconBadgeRequestBody, + }, + initOverrides, + ); } } diff --git a/tests/resources.test.js b/tests/resources.test.js index f53a76c..87f1499 100644 --- a/tests/resources.test.js +++ b/tests/resources.test.js @@ -167,7 +167,7 @@ describe("resource wrappers", () => { .mockResolvedValue({ success: true, badge: 0 }); const client = new ActivitySmith({ apiKey: "test" }); - const result = await client.appIconBadge.update(0); + const result = await client.badgeCount(0); expect(result).toEqual({ success: true, badge: 0 }); expect(updateSpy).toHaveBeenCalledWith( @@ -176,7 +176,7 @@ describe("resource wrappers", () => { ); }); - it("maps top-level channels to target.channels for appIconBadge.update", async () => { + it("maps channels to target.channels for badgeCount", async () => { const ActivitySmith = require("../dist/src/index.js"); const generated = require("../dist/generated/index.js"); @@ -185,7 +185,7 @@ describe("resource wrappers", () => { .mockResolvedValue({ success: true, badge: 3 }); const client = new ActivitySmith({ apiKey: "test" }); - await client.appIconBadge.update(3, { channels: ["sales", "customer-success"] }); + await client.badgeCount(3, { channels: ["sales", "customer-success"] }); expect(updateSpy).toHaveBeenCalledWith( { From 5ec54c0b64119eba40c581dbe09944e965401a0f Mon Sep 17 00:00:00 2001 From: bardonadam Date: Fri, 10 Jul 2026 20:43:02 +0700 Subject: [PATCH 04/11] docs: refine badge count copy --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 128071b..bfc3440 100644 --- a/README.md +++ b/README.md @@ -511,7 +511,7 @@ await activitysmith.metrics.update("prod.status", "healthy"); ActivitySmith app icon with an App Icon Badge Count

-Keep the numbers you care about on your ActivitySmith app icon. Show MRR, a customer count, a stock price, or any other value you want to keep in view. +Show the number you care about on your ActivitySmith app icon. Track MRR, a customer count, a stock price, or any other value you want to keep in view. ```ts await activitysmith.badgeCount(12); From 0cba4aada430cdc1e5a2c65be55d981c3d74eee5 Mon Sep 17 00:00:00 2001 From: bardonadam Date: Fri, 10 Jul 2026 20:46:24 +0700 Subject: [PATCH 05/11] docs: simplify badge count examples --- README.md | 8 -------- 1 file changed, 8 deletions(-) diff --git a/README.md b/README.md index bfc3440..dcb1459 100644 --- a/README.md +++ b/README.md @@ -523,14 +523,6 @@ Pass `0` to clear the badge. await activitysmith.badgeCount(0); ``` -To target specific devices, pass their channel slugs in `channels`. - -```ts -await activitysmith.badgeCount(3, { - channels: ["sales", "customer-success"], -}); -``` - ## Error Handling ```ts From 131bce34a330bfa97723c950acc19bb6aaefd676 Mon Sep 17 00:00:00 2001 From: bardonadam Date: Fri, 10 Jul 2026 20:50:26 +0700 Subject: [PATCH 06/11] docs: clarify channel targeting --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index dcb1459..8faeab0 100644 --- a/README.md +++ b/README.md @@ -471,7 +471,7 @@ Choose from these colors for the Live Activity accent, including progress bars a ## Channels -Channels are used to target specific team members or devices. Can be used for both push notifications and live activities. +Use `channels` to target specific team members or devices. ```ts await activitysmith.notifications.send({ From dec88fb54de3de9400c902ace36eea23da351246 Mon Sep 17 00:00:00 2001 From: bardonadam Date: Fri, 10 Jul 2026 20:56:47 +0700 Subject: [PATCH 07/11] docs: restore badge channel example --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index 8faeab0..1b413a9 100644 --- a/README.md +++ b/README.md @@ -523,6 +523,14 @@ Pass `0` to clear the badge. await activitysmith.badgeCount(0); ``` +Use `channels` to target specific team members or devices. + +```ts +await activitysmith.badgeCount(3, { + channels: ["sales", "customer-success"], +}); +``` + ## Error Handling ```ts From 1f1410685abdbe2d4ea3366aab27a31e2d90d256 Mon Sep 17 00:00:00 2001 From: bardonadam Date: Fri, 10 Jul 2026 20:58:50 +0700 Subject: [PATCH 08/11] docs: refine channel targeting copy --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 1b413a9..c8c6331 100644 --- a/README.md +++ b/README.md @@ -471,7 +471,7 @@ Choose from these colors for the Live Activity accent, including progress bars a ## Channels -Use `channels` to target specific team members or devices. +Use `channels` to target specific team members or devices ```ts await activitysmith.notifications.send({ @@ -523,7 +523,7 @@ Pass `0` to clear the badge. await activitysmith.badgeCount(0); ``` -Use `channels` to target specific team members or devices. +Use `channels` to target specific team members or devices ```ts await activitysmith.badgeCount(3, { From e1e97efc62789e62826754dab1eb35fa04c3f8ff Mon Sep 17 00:00:00 2001 From: bardonadam Date: Fri, 10 Jul 2026 21:11:25 +0700 Subject: [PATCH 09/11] docs: use badge count example --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c8c6331..dfeac02 100644 --- a/README.md +++ b/README.md @@ -514,7 +514,7 @@ await activitysmith.metrics.update("prod.status", "healthy"); Show the number you care about on your ActivitySmith app icon. Track MRR, a customer count, a stock price, or any other value you want to keep in view. ```ts -await activitysmith.badgeCount(12); +await activitysmith.badgeCount(8333); ``` Pass `0` to clear the badge. From e7bab3912221257877ab0c01c5514bf6aac01054 Mon Sep 17 00:00:00 2001 From: bardonadam Date: Sat, 11 Jul 2026 14:47:55 +0700 Subject: [PATCH 10/11] docs: align Node README with SDK landing page Why:\n- Keep the Node README consistent with the approved SDK landing-page structure.\n\nHow:\n- Move Channels below App Icon Badge Count.\n- Add channel examples for Push Notifications, Live Activities, and badges.\n- Update badge clearing guidance.\n\nVerification:\n- git diff --cached --check\n\nInitiated-by: user\nImplemented-by: codex --- README.md | 46 ++++++++++++++++++++++++++++++++-------------- 1 file changed, 32 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index dfeac02..7dc1631 100644 --- a/README.md +++ b/README.md @@ -20,9 +20,9 @@ See [API reference](https://activitysmith.com/docs/api-reference/introduction) - [Live Activity Action](#live-activity-action) - [Icons and Badges](#icons-and-badges) - [Live Activity Colors](#live-activity-colors) -- [Channels](#channels) - [Widgets](#widgets) - [App Icon Badge Count](#app-icon-badge-count) +- [Channels](#channels) ## Installation @@ -469,18 +469,6 @@ Choose from these colors for the Live Activity accent, including progress bars a `lime`, `green`, `cyan`, `blue`, `purple`, `magenta`, `red`, `orange`, `yellow`, `gray` -## Channels - -Use `channels` to target specific team members or devices - -```ts -await activitysmith.notifications.send({ - title: "New subscription 💸", - message: "Customer upgraded to Pro plan", - channels: ["sales", "customer-success"], // Optional -}); -``` - ## Widgets

@@ -513,18 +501,48 @@ await activitysmith.metrics.update("prod.status", "healthy"); Show the number you care about on your ActivitySmith app icon. Track MRR, a customer count, a stock price, or any other value you want to keep in view. +Set or update the badge value. + ```ts await activitysmith.badgeCount(8333); ``` -Pass `0` to clear the badge. +To clear the badge, set its value to 0. ```ts await activitysmith.badgeCount(0); ``` +## Channels + Use `channels` to target specific team members or devices +### Push Notifications + +```ts +await activitysmith.notifications.send({ + title: "New subscription 💸", + message: "Customer upgraded to Pro plan", + channels: ["sales", "customer-success"], +}); +``` + +### Live Activities + +```ts +await activitysmith.liveActivities.start({ + content_state: { + title: "Nightly Database Backup", + subtitle: "verify restore", + type: "progress", + percentage: 62, + }, + channels: ["sales", "customer-success"], +}); +``` + +### App Icon Badge Count + ```ts await activitysmith.badgeCount(3, { channels: ["sales", "customer-success"], From a61f976f4d1fce0aaf5106d0528fffecf3e9a5e6 Mon Sep 17 00:00:00 2001 From: bardonadam Date: Sat, 11 Jul 2026 15:08:10 +0700 Subject: [PATCH 11/11] chore: release 1.9.0 Why:\n- Prepare the Node SDK release for the new App Icon Badge Count feature.\n\nHow:\n- Bump package and SDK header versions from 1.8.0 to 1.9.0.\n- Add the focused 1.9.0 changelog entry.\n\nVerification:\n- npm test\n- 25 tests passed\n\nInitiated-by: user\nImplemented-by: codex --- CHANGELOG.md | 5 +++++ package-lock.json | 4 ++-- package.json | 2 +- src/ActivitySmith.ts | 2 +- 4 files changed, 9 insertions(+), 4 deletions(-) create mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..9485214 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,5 @@ +## 1.9.0 + +### New Features + +- **New Feature: App Icon Badge Count** - Show MRR, user counts, stock prices, and more on your ActivitySmith app icon. diff --git a/package-lock.json b/package-lock.json index 518baed..713333d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "activitysmith", - "version": "1.8.0", + "version": "1.9.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "activitysmith", - "version": "1.8.0", + "version": "1.9.0", "license": "MIT", "devDependencies": { "typescript": "^5.3.3", diff --git a/package.json b/package.json index ea282fc..9a1241e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "activitysmith", - "version": "1.8.0", + "version": "1.9.0", "description": "Official ActivitySmith Node.js SDK", "keywords": [ "activitysmith", diff --git a/src/ActivitySmith.ts b/src/ActivitySmith.ts index adcd1c1..1222797 100644 --- a/src/ActivitySmith.ts +++ b/src/ActivitySmith.ts @@ -6,7 +6,7 @@ import { PushNotificationsApi, } from "../generated/index"; -const SDK_VERSION = "1.8.0"; +const SDK_VERSION = "1.9.0"; const SDK_HEADER_NAME = "X-ActivitySmith-SDK"; const SDK_HEADER_VALUE = `node-v${SDK_VERSION}`;