ad2app-lib 1.10.0 → 1.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ad2app-lib",
3
- "version": "1.10.0",
3
+ "version": "1.11.0",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "type": "commonjs",
@@ -0,0 +1,39 @@
1
+ import { test } from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import {
4
+ ANALYTICS_SOURCES,
5
+ SchedulingAnalyticsKpiDTO,
6
+ } from './I_SchedulingAnalytics';
7
+
8
+ // AD2-1045 — the analytics partial-failure signal: a KPI response can name
9
+ // which sources were unavailable so a swallowed Zernio failure is never
10
+ // presented as real zeros.
11
+
12
+ test('ANALYTICS_SOURCES names the four analytics sources', () => {
13
+ assert.deepEqual(
14
+ [...ANALYTICS_SOURCES],
15
+ ['daily-metrics', 'follower-stats', 'content-decay', 'top-posts'],
16
+ );
17
+ });
18
+
19
+ test('SchedulingAnalyticsKpiDTO carries failedSources when provided', () => {
20
+ const kpi = new SchedulingAnalyticsKpiDTO({
21
+ impressions: 10,
22
+ reach: 5,
23
+ engagementRate: 1.2,
24
+ followerGrowth: 3,
25
+ failedSources: ['follower-stats'],
26
+ });
27
+ assert.deepEqual(kpi.failedSources, ['follower-stats']);
28
+ });
29
+
30
+ test('failedSources is optional and absent by default (backward compatible)', () => {
31
+ const kpi = new SchedulingAnalyticsKpiDTO({
32
+ impressions: 10,
33
+ reach: 5,
34
+ engagementRate: 1.2,
35
+ followerGrowth: 3,
36
+ });
37
+ assert.equal(kpi.failedSources, undefined);
38
+ assert.equal('failedSources' in JSON.parse(JSON.stringify(kpi)), false);
39
+ });
@@ -5,6 +5,21 @@
5
5
  * per-post timeline snapshots, content decay windows, and follower stats.
6
6
  */
7
7
 
8
+ // ── Analytics sources (AD2-1045) ──────────────────────────────────────────────
9
+
10
+ /**
11
+ * The upstream sources an analytics response aggregates. Used by
12
+ * `failedSources` to name which of them were unavailable.
13
+ */
14
+ export const ANALYTICS_SOURCES = [
15
+ 'daily-metrics',
16
+ 'follower-stats',
17
+ 'content-decay',
18
+ 'top-posts',
19
+ ] as const;
20
+
21
+ export type AnalyticsSource = (typeof ANALYTICS_SOURCES)[number];
22
+
8
23
  // ── SchedulingAnalyticsKpiDTO ─────────────────────────────────────────────────
9
24
 
10
25
  /**
@@ -16,12 +31,22 @@ export class SchedulingAnalyticsKpiDTO {
16
31
  reach: number;
17
32
  engagementRate: number;
18
33
  followerGrowth: number;
34
+ /**
35
+ * Sources that were unavailable when this response was assembled
36
+ * (AD2-1045). Absent/empty = all sources healthy. When present, the
37
+ * numeric fields contain only data from the healthy sources — a partial
38
+ * outage must never read as real zeros.
39
+ */
40
+ failedSources?: AnalyticsSource[];
19
41
 
20
42
  constructor(data: SchedulingAnalyticsKpiDTO) {
21
43
  this.impressions = data.impressions;
22
44
  this.reach = data.reach;
23
45
  this.engagementRate = data.engagementRate;
24
46
  this.followerGrowth = data.followerGrowth;
47
+ if (data.failedSources !== undefined) {
48
+ this.failedSources = data.failedSources;
49
+ }
25
50
  }
26
51
  }
27
52
 
@@ -131,7 +156,11 @@ export class SchedulingPostTimelineEntryDTO {
131
156
  * Returned by GET /social/analytics/content-decay.
132
157
  */
133
158
  export class SchedulingContentDecayDTO {
134
- window: '1h' | '6h' | '24h' | '7d';
159
+ /**
160
+ * Zernio now returns aggregate bucket labels (e.g. "0-6h", "6-12h"), not
161
+ * the old fixed windows — widened accordingly (AD2-1061, 2026-07-03).
162
+ */
163
+ window: string;
135
164
  platform: string;
136
165
  /** Percentage of peak engagement remaining at this window */
137
166
  pct: number;