@growth-labs/ops-digest 0.1.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.
Files changed (76) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/README.md +129 -0
  3. package/SPEC.md +25 -0
  4. package/dist/anomaly.d.ts +3 -0
  5. package/dist/anomaly.d.ts.map +1 -0
  6. package/dist/anomaly.js +50 -0
  7. package/dist/anomaly.js.map +1 -0
  8. package/dist/engine.d.ts +4 -0
  9. package/dist/engine.d.ts.map +1 -0
  10. package/dist/engine.js +149 -0
  11. package/dist/engine.js.map +1 -0
  12. package/dist/handlers/common.d.ts +12 -0
  13. package/dist/handlers/common.d.ts.map +1 -0
  14. package/dist/handlers/common.js +68 -0
  15. package/dist/handlers/common.js.map +1 -0
  16. package/dist/handlers/composite-ratio.d.ts +7 -0
  17. package/dist/handlers/composite-ratio.d.ts.map +1 -0
  18. package/dist/handlers/composite-ratio.js +9 -0
  19. package/dist/handlers/composite-ratio.js.map +1 -0
  20. package/dist/handlers/d1-row-count-by-event.d.ts +7 -0
  21. package/dist/handlers/d1-row-count-by-event.d.ts.map +1 -0
  22. package/dist/handlers/d1-row-count-by-event.js +21 -0
  23. package/dist/handlers/d1-row-count-by-event.js.map +1 -0
  24. package/dist/handlers/d1-row-count.d.ts +7 -0
  25. package/dist/handlers/d1-row-count.d.ts.map +1 -0
  26. package/dist/handlers/d1-row-count.js +12 -0
  27. package/dist/handlers/d1-row-count.js.map +1 -0
  28. package/dist/handlers/index.d.ts +29 -0
  29. package/dist/handlers/index.d.ts.map +1 -0
  30. package/dist/handlers/index.js +60 -0
  31. package/dist/handlers/index.js.map +1 -0
  32. package/dist/handlers/wae-avg-double.d.ts +7 -0
  33. package/dist/handlers/wae-avg-double.d.ts.map +1 -0
  34. package/dist/handlers/wae-avg-double.js +12 -0
  35. package/dist/handlers/wae-avg-double.js.map +1 -0
  36. package/dist/handlers/wae-event-count-by-blob.d.ts +7 -0
  37. package/dist/handlers/wae-event-count-by-blob.d.ts.map +1 -0
  38. package/dist/handlers/wae-event-count-by-blob.js +14 -0
  39. package/dist/handlers/wae-event-count-by-blob.js.map +1 -0
  40. package/dist/handlers/wae-event-count.d.ts +7 -0
  41. package/dist/handlers/wae-event-count.d.ts.map +1 -0
  42. package/dist/handlers/wae-event-count.js +11 -0
  43. package/dist/handlers/wae-event-count.js.map +1 -0
  44. package/dist/handlers/wae-top-n-by-blob.d.ts +7 -0
  45. package/dist/handlers/wae-top-n-by-blob.d.ts.map +1 -0
  46. package/dist/handlers/wae-top-n-by-blob.js +18 -0
  47. package/dist/handlers/wae-top-n-by-blob.js.map +1 -0
  48. package/dist/handlers/wae-unique-count.d.ts +7 -0
  49. package/dist/handlers/wae-unique-count.d.ts.map +1 -0
  50. package/dist/handlers/wae-unique-count.js +12 -0
  51. package/dist/handlers/wae-unique-count.js.map +1 -0
  52. package/dist/idempotency.d.ts +6 -0
  53. package/dist/idempotency.d.ts.map +1 -0
  54. package/dist/idempotency.js +25 -0
  55. package/dist/idempotency.js.map +1 -0
  56. package/dist/index.d.ts +5 -0
  57. package/dist/index.d.ts.map +1 -0
  58. package/dist/index.js +29 -0
  59. package/dist/index.js.map +1 -0
  60. package/dist/render.d.ts +4 -0
  61. package/dist/render.d.ts.map +1 -0
  62. package/dist/render.js +73 -0
  63. package/dist/render.js.map +1 -0
  64. package/dist/schema.d.ts +264 -0
  65. package/dist/schema.d.ts.map +1 -0
  66. package/dist/schema.js +102 -0
  67. package/dist/schema.js.map +1 -0
  68. package/dist/types.d.ts +146 -0
  69. package/dist/types.d.ts.map +1 -0
  70. package/dist/types.js +2 -0
  71. package/dist/types.js.map +1 -0
  72. package/dist/window.d.ts +7 -0
  73. package/dist/window.d.ts.map +1 -0
  74. package/dist/window.js +28 -0
  75. package/dist/window.js.map +1 -0
  76. package/package.json +40 -0
@@ -0,0 +1,264 @@
1
+ import { z } from 'zod';
2
+ import type { OpsDigestConfig } from './types.js';
3
+ type MetricSchema = z.ZodType<OpsDigestConfig['digests'][number]['metrics'][number]>;
4
+ export declare const opsDigestConfigSchema: z.ZodObject<{
5
+ realmId: z.ZodString;
6
+ d1Binding: z.ZodString;
7
+ authWae: z.ZodOptional<z.ZodEffects<z.ZodObject<{
8
+ accountId: z.ZodString;
9
+ dataset: z.ZodString;
10
+ apiTokenSecret: z.ZodString;
11
+ realmFilter: z.ZodOptional<z.ZodString>;
12
+ siteFilter: z.ZodOptional<z.ZodString>;
13
+ }, "strip", z.ZodTypeAny, {
14
+ accountId: string;
15
+ dataset: string;
16
+ apiTokenSecret: string;
17
+ realmFilter?: string | undefined;
18
+ siteFilter?: string | undefined;
19
+ }, {
20
+ accountId: string;
21
+ dataset: string;
22
+ apiTokenSecret: string;
23
+ realmFilter?: string | undefined;
24
+ siteFilter?: string | undefined;
25
+ }>, {
26
+ accountId: string;
27
+ dataset: string;
28
+ apiTokenSecret: string;
29
+ realmFilter?: string | undefined;
30
+ siteFilter?: string | undefined;
31
+ }, {
32
+ accountId: string;
33
+ dataset: string;
34
+ apiTokenSecret: string;
35
+ realmFilter?: string | undefined;
36
+ siteFilter?: string | undefined;
37
+ }>>;
38
+ contentWae: z.ZodOptional<z.ZodEffects<z.ZodObject<{
39
+ accountId: z.ZodString;
40
+ dataset: z.ZodString;
41
+ apiTokenSecret: z.ZodString;
42
+ realmFilter: z.ZodOptional<z.ZodString>;
43
+ siteFilter: z.ZodOptional<z.ZodString>;
44
+ }, "strip", z.ZodTypeAny, {
45
+ accountId: string;
46
+ dataset: string;
47
+ apiTokenSecret: string;
48
+ realmFilter?: string | undefined;
49
+ siteFilter?: string | undefined;
50
+ }, {
51
+ accountId: string;
52
+ dataset: string;
53
+ apiTokenSecret: string;
54
+ realmFilter?: string | undefined;
55
+ siteFilter?: string | undefined;
56
+ }>, {
57
+ accountId: string;
58
+ dataset: string;
59
+ apiTokenSecret: string;
60
+ realmFilter?: string | undefined;
61
+ siteFilter?: string | undefined;
62
+ }, {
63
+ accountId: string;
64
+ dataset: string;
65
+ apiTokenSecret: string;
66
+ realmFilter?: string | undefined;
67
+ siteFilter?: string | undefined;
68
+ }>>;
69
+ extraWae: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodEffects<z.ZodObject<{
70
+ accountId: z.ZodString;
71
+ dataset: z.ZodString;
72
+ apiTokenSecret: z.ZodString;
73
+ realmFilter: z.ZodOptional<z.ZodString>;
74
+ siteFilter: z.ZodOptional<z.ZodString>;
75
+ }, "strip", z.ZodTypeAny, {
76
+ accountId: string;
77
+ dataset: string;
78
+ apiTokenSecret: string;
79
+ realmFilter?: string | undefined;
80
+ siteFilter?: string | undefined;
81
+ }, {
82
+ accountId: string;
83
+ dataset: string;
84
+ apiTokenSecret: string;
85
+ realmFilter?: string | undefined;
86
+ siteFilter?: string | undefined;
87
+ }>, {
88
+ accountId: string;
89
+ dataset: string;
90
+ apiTokenSecret: string;
91
+ realmFilter?: string | undefined;
92
+ siteFilter?: string | undefined;
93
+ }, {
94
+ accountId: string;
95
+ dataset: string;
96
+ apiTokenSecret: string;
97
+ realmFilter?: string | undefined;
98
+ siteFilter?: string | undefined;
99
+ }>>>;
100
+ idempotencyKv: z.ZodString;
101
+ notifyConfig: z.ZodObject<{}, "passthrough", z.ZodTypeAny, z.objectOutputType<{}, z.ZodTypeAny, "passthrough">, z.objectInputType<{}, z.ZodTypeAny, "passthrough">>;
102
+ digests: z.ZodArray<z.ZodObject<{
103
+ name: z.ZodString;
104
+ brandLabel: z.ZodString;
105
+ schedule: z.ZodString;
106
+ window: z.ZodUnion<[z.ZodLiteral<"previous-day-utc">, z.ZodLiteral<"previous-week-utc">, z.ZodLiteral<"previous-month-utc">, z.ZodObject<{
107
+ days: z.ZodNumber;
108
+ anchorTo: z.ZodLiteral<"utc-midnight">;
109
+ }, "strip", z.ZodTypeAny, {
110
+ days: number;
111
+ anchorTo: "utc-midnight";
112
+ }, {
113
+ days: number;
114
+ anchorTo: "utc-midnight";
115
+ }>]>;
116
+ metrics: z.ZodArray<MetricSchema, "many">;
117
+ anomaly: z.ZodObject<{
118
+ method: z.ZodEnum<["iqr", "none"]>;
119
+ medianFloor: z.ZodNumber;
120
+ iqrMultiplier: z.ZodOptional<z.ZodNumber>;
121
+ overrides: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{}, "passthrough", z.ZodTypeAny, z.objectOutputType<{}, z.ZodTypeAny, "passthrough">, z.objectInputType<{}, z.ZodTypeAny, "passthrough">>>>;
122
+ }, "strip", z.ZodTypeAny, {
123
+ method: "iqr" | "none";
124
+ medianFloor: number;
125
+ iqrMultiplier?: number | undefined;
126
+ overrides?: Record<string, z.objectOutputType<{}, z.ZodTypeAny, "passthrough">> | undefined;
127
+ }, {
128
+ method: "iqr" | "none";
129
+ medianFloor: number;
130
+ iqrMultiplier?: number | undefined;
131
+ overrides?: Record<string, z.objectInputType<{}, z.ZodTypeAny, "passthrough">> | undefined;
132
+ }>;
133
+ render: z.ZodString;
134
+ channels: z.ZodArray<z.ZodEnum<["slack", "email"]>, "many">;
135
+ }, "strip", z.ZodTypeAny, {
136
+ channels: ("slack" | "email")[];
137
+ name: string;
138
+ anomaly: {
139
+ method: "iqr" | "none";
140
+ medianFloor: number;
141
+ iqrMultiplier?: number | undefined;
142
+ overrides?: Record<string, z.objectOutputType<{}, z.ZodTypeAny, "passthrough">> | undefined;
143
+ };
144
+ metrics: import("./types.js").MetricDefinition[];
145
+ brandLabel: string;
146
+ schedule: string;
147
+ window: "previous-day-utc" | "previous-week-utc" | "previous-month-utc" | {
148
+ days: number;
149
+ anchorTo: "utc-midnight";
150
+ };
151
+ render: string;
152
+ }, {
153
+ channels: ("slack" | "email")[];
154
+ name: string;
155
+ anomaly: {
156
+ method: "iqr" | "none";
157
+ medianFloor: number;
158
+ iqrMultiplier?: number | undefined;
159
+ overrides?: Record<string, z.objectInputType<{}, z.ZodTypeAny, "passthrough">> | undefined;
160
+ };
161
+ metrics: import("./types.js").MetricDefinition[];
162
+ brandLabel: string;
163
+ schedule: string;
164
+ window: "previous-day-utc" | "previous-week-utc" | "previous-month-utc" | {
165
+ days: number;
166
+ anchorTo: "utc-midnight";
167
+ };
168
+ render: string;
169
+ }>, "many">;
170
+ }, "strip", z.ZodTypeAny, {
171
+ digests: {
172
+ channels: ("slack" | "email")[];
173
+ name: string;
174
+ anomaly: {
175
+ method: "iqr" | "none";
176
+ medianFloor: number;
177
+ iqrMultiplier?: number | undefined;
178
+ overrides?: Record<string, z.objectOutputType<{}, z.ZodTypeAny, "passthrough">> | undefined;
179
+ };
180
+ metrics: import("./types.js").MetricDefinition[];
181
+ brandLabel: string;
182
+ schedule: string;
183
+ window: "previous-day-utc" | "previous-week-utc" | "previous-month-utc" | {
184
+ days: number;
185
+ anchorTo: "utc-midnight";
186
+ };
187
+ render: string;
188
+ }[];
189
+ realmId: string;
190
+ d1Binding: string;
191
+ idempotencyKv: string;
192
+ notifyConfig: {} & {
193
+ [k: string]: unknown;
194
+ };
195
+ authWae?: {
196
+ accountId: string;
197
+ dataset: string;
198
+ apiTokenSecret: string;
199
+ realmFilter?: string | undefined;
200
+ siteFilter?: string | undefined;
201
+ } | undefined;
202
+ contentWae?: {
203
+ accountId: string;
204
+ dataset: string;
205
+ apiTokenSecret: string;
206
+ realmFilter?: string | undefined;
207
+ siteFilter?: string | undefined;
208
+ } | undefined;
209
+ extraWae?: Record<string, {
210
+ accountId: string;
211
+ dataset: string;
212
+ apiTokenSecret: string;
213
+ realmFilter?: string | undefined;
214
+ siteFilter?: string | undefined;
215
+ }> | undefined;
216
+ }, {
217
+ digests: {
218
+ channels: ("slack" | "email")[];
219
+ name: string;
220
+ anomaly: {
221
+ method: "iqr" | "none";
222
+ medianFloor: number;
223
+ iqrMultiplier?: number | undefined;
224
+ overrides?: Record<string, z.objectInputType<{}, z.ZodTypeAny, "passthrough">> | undefined;
225
+ };
226
+ metrics: import("./types.js").MetricDefinition[];
227
+ brandLabel: string;
228
+ schedule: string;
229
+ window: "previous-day-utc" | "previous-week-utc" | "previous-month-utc" | {
230
+ days: number;
231
+ anchorTo: "utc-midnight";
232
+ };
233
+ render: string;
234
+ }[];
235
+ realmId: string;
236
+ d1Binding: string;
237
+ idempotencyKv: string;
238
+ notifyConfig: {} & {
239
+ [k: string]: unknown;
240
+ };
241
+ authWae?: {
242
+ accountId: string;
243
+ dataset: string;
244
+ apiTokenSecret: string;
245
+ realmFilter?: string | undefined;
246
+ siteFilter?: string | undefined;
247
+ } | undefined;
248
+ contentWae?: {
249
+ accountId: string;
250
+ dataset: string;
251
+ apiTokenSecret: string;
252
+ realmFilter?: string | undefined;
253
+ siteFilter?: string | undefined;
254
+ } | undefined;
255
+ extraWae?: Record<string, {
256
+ accountId: string;
257
+ dataset: string;
258
+ apiTokenSecret: string;
259
+ realmFilter?: string | undefined;
260
+ siteFilter?: string | undefined;
261
+ }> | undefined;
262
+ }>;
263
+ export {};
264
+ //# sourceMappingURL=schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAmCjD,KAAK,YAAY,GAAG,CAAC,CAAC,OAAO,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC,CAAA;AAoEpF,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAShC,CAAA"}
package/dist/schema.js ADDED
@@ -0,0 +1,102 @@
1
+ import { z } from 'zod';
2
+ const waeSourceSchema = z
3
+ .object({
4
+ accountId: z.string().min(1),
5
+ dataset: z.string().min(1),
6
+ apiTokenSecret: z.string().min(1),
7
+ realmFilter: z.string().min(1).optional(),
8
+ siteFilter: z.string().min(1).optional(),
9
+ })
10
+ .refine((source) => !(source.realmFilter && source.siteFilter), {
11
+ message: 'Configure either realmFilter or siteFilter, not both',
12
+ });
13
+ const windowSpecSchema = z.union([
14
+ z.literal('previous-day-utc'),
15
+ z.literal('previous-week-utc'),
16
+ z.literal('previous-month-utc'),
17
+ z.object({ days: z.number().int().positive(), anchorTo: z.literal('utc-midnight') }),
18
+ ]);
19
+ const d1RowCountSchema = z.object({
20
+ handler: z.literal('d1.row-count'),
21
+ name: z.string().min(1),
22
+ table: z.string().min(1),
23
+ timeColumn: z.string().min(1).optional(),
24
+ timeColumnUnit: z.enum(['s', 'ms']).optional(),
25
+ });
26
+ const d1RowCountByEventSchema = d1RowCountSchema.extend({
27
+ handler: z.literal('d1.row-count-by-event'),
28
+ eventNames: z.array(z.string().min(1)).min(1),
29
+ eventColumn: z.string().min(1).optional(),
30
+ });
31
+ const metricSchema = z.lazy(() => z.discriminatedUnion('handler', [
32
+ d1RowCountSchema,
33
+ d1RowCountByEventSchema,
34
+ z.object({
35
+ handler: z.literal('wae.event-count'),
36
+ name: z.string().min(1),
37
+ source: z.string().min(1),
38
+ eventName: z.string().min(1),
39
+ }),
40
+ z.object({
41
+ handler: z.literal('wae.event-count-by-blob'),
42
+ name: z.string().min(1),
43
+ source: z.string().min(1),
44
+ eventName: z.string().min(1),
45
+ groupBy: z.string().min(1),
46
+ }),
47
+ z.object({
48
+ handler: z.literal('wae.unique-count'),
49
+ name: z.string().min(1),
50
+ source: z.string().min(1),
51
+ eventName: z.string().min(1).optional(),
52
+ uniqueBlob: z.string().min(1),
53
+ }),
54
+ z.object({
55
+ handler: z.literal('wae.avg-double'),
56
+ name: z.string().min(1),
57
+ source: z.string().min(1),
58
+ eventName: z.string().min(1).optional(),
59
+ doubleField: z.string().min(1),
60
+ }),
61
+ z.object({
62
+ handler: z.literal('wae.top-n-by-blob'),
63
+ name: z.string().min(1),
64
+ source: z.string().min(1),
65
+ eventName: z.string().min(1).optional(),
66
+ groupBy: z.string().min(1),
67
+ limit: z.number().int().positive(),
68
+ }),
69
+ z.object({
70
+ handler: z.literal('composite.ratio'),
71
+ name: z.string().min(1),
72
+ numerator: metricSchema,
73
+ denominator: metricSchema,
74
+ }),
75
+ ]));
76
+ const anomalySchema = z.object({
77
+ method: z.enum(['iqr', 'none']),
78
+ medianFloor: z.number().min(0),
79
+ iqrMultiplier: z.number().positive().optional(),
80
+ overrides: z.record(z.string(), z.object({}).passthrough()).optional(),
81
+ });
82
+ const digestSchema = z.object({
83
+ name: z.string().min(1),
84
+ brandLabel: z.string().min(1),
85
+ schedule: z.string().min(1),
86
+ window: windowSpecSchema,
87
+ metrics: z.array(metricSchema),
88
+ anomaly: anomalySchema,
89
+ render: z.string().min(1),
90
+ channels: z.array(z.enum(['slack', 'email'])).min(1),
91
+ });
92
+ export const opsDigestConfigSchema = z.object({
93
+ realmId: z.string().min(1),
94
+ d1Binding: z.string().min(1),
95
+ authWae: waeSourceSchema.optional(),
96
+ contentWae: waeSourceSchema.optional(),
97
+ extraWae: z.record(z.string(), waeSourceSchema).optional(),
98
+ idempotencyKv: z.string().min(1),
99
+ notifyConfig: z.object({}).passthrough(),
100
+ digests: z.array(digestSchema).min(1),
101
+ });
102
+ //# sourceMappingURL=schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,146 @@
1
+ import type { WindowSpec } from '@growth-labs/analytics/utils/time-windows';
2
+ import type { Channel, EmailProvider, NotifyEnv, NotifyInput, Severity } from '@growth-labs/notify';
3
+ export type { Channel, Severity, WindowSpec };
4
+ export type NotifyConfig = Partial<Pick<NotifyInput, 'blocks' | 'dedupFn' | 'onSent' | 'emailProvider'>> & {
5
+ channels?: Channel[];
6
+ severity?: Severity;
7
+ emailProvider?: EmailProvider;
8
+ };
9
+ export interface OpsDigestConfig {
10
+ realmId: string;
11
+ d1Binding: string;
12
+ authWae?: WaeSourceConfig;
13
+ contentWae?: WaeSourceConfig;
14
+ extraWae?: Record<string, WaeSourceConfig>;
15
+ idempotencyKv: string;
16
+ notifyConfig: NotifyConfig;
17
+ digests: DigestDefinition[];
18
+ }
19
+ export interface WaeSourceConfig {
20
+ accountId: string;
21
+ dataset: string;
22
+ apiTokenSecret: string;
23
+ realmFilter?: string;
24
+ siteFilter?: string;
25
+ }
26
+ export interface DigestDefinition {
27
+ name: string;
28
+ brandLabel: string;
29
+ schedule: string;
30
+ window: WindowSpec;
31
+ metrics: MetricDefinition[];
32
+ anomaly: AnomalyConfig;
33
+ render: 'standard' | string;
34
+ channels: Channel[];
35
+ }
36
+ interface D1MetricBase {
37
+ name: string;
38
+ table: string;
39
+ timeColumn?: string;
40
+ timeColumnUnit?: 's' | 'ms';
41
+ }
42
+ export type MetricDefinition = ({
43
+ handler: 'd1.row-count';
44
+ } & D1MetricBase) | ({
45
+ handler: 'd1.row-count-by-event';
46
+ eventNames: string[];
47
+ eventColumn?: string;
48
+ } & D1MetricBase) | {
49
+ handler: 'wae.event-count';
50
+ name: string;
51
+ source: string;
52
+ eventName: string;
53
+ } | {
54
+ handler: 'wae.event-count-by-blob';
55
+ name: string;
56
+ source: string;
57
+ eventName: string;
58
+ groupBy: string;
59
+ } | {
60
+ handler: 'wae.unique-count';
61
+ name: string;
62
+ source: string;
63
+ eventName?: string;
64
+ uniqueBlob: string;
65
+ } | {
66
+ handler: 'wae.avg-double';
67
+ name: string;
68
+ source: string;
69
+ eventName?: string;
70
+ doubleField: string;
71
+ } | {
72
+ handler: 'wae.top-n-by-blob';
73
+ name: string;
74
+ source: string;
75
+ eventName?: string;
76
+ groupBy: string;
77
+ limit: number;
78
+ } | {
79
+ handler: 'composite.ratio';
80
+ name: string;
81
+ numerator: MetricDefinition;
82
+ denominator: MetricDefinition;
83
+ };
84
+ export interface AnomalyConfig {
85
+ method: 'iqr' | 'none';
86
+ medianFloor: number;
87
+ iqrMultiplier?: number;
88
+ overrides?: Record<string, Partial<AnomalyConfig>>;
89
+ }
90
+ export interface AnomalyHit {
91
+ metric: string;
92
+ current: number;
93
+ median: number;
94
+ iqr: number;
95
+ lowerBand: number;
96
+ upperBand: number;
97
+ direction: 'above' | 'below';
98
+ }
99
+ export interface OpsDigestHandle {
100
+ scheduledHandler: (event: ScheduledEvent, env: OpsDigestEnv, ctx: ExecutionContext) => Promise<void>;
101
+ runDigest: (digestName: string, env: OpsDigestEnv, ctx: ExecutionContext) => Promise<DigestRunResult>;
102
+ }
103
+ export interface DigestRunResult {
104
+ digestName: string;
105
+ windowStart: number;
106
+ windowEnd: number;
107
+ rendered: string;
108
+ idempotencyKey: string;
109
+ posted: boolean;
110
+ metrics: MetricResult[];
111
+ errors: string[];
112
+ }
113
+ export interface PercentChange {
114
+ value: string;
115
+ direction: 'up' | 'down' | 'flat';
116
+ }
117
+ export type GroupedMetricResult = Record<string, number>;
118
+ export type TopNResult = {
119
+ group: string;
120
+ count: number;
121
+ }[];
122
+ export type MetricValue = number | GroupedMetricResult | TopNResult;
123
+ export interface MetricResult {
124
+ name: string;
125
+ current: MetricValue;
126
+ baseline: number;
127
+ delta: PercentChange;
128
+ anomaly?: AnomalyHit;
129
+ }
130
+ export interface ResolvedDigestWindow {
131
+ startMs: number;
132
+ endMs: number;
133
+ sqlStart: string;
134
+ sqlEnd: string;
135
+ }
136
+ export interface HandlerContext {
137
+ d1?: D1Database;
138
+ sources?: Record<string, WaeSourceConfig>;
139
+ env?: OpsDigestEnv;
140
+ }
141
+ export type MetricHandler<T extends MetricDefinition = MetricDefinition> = (metric: T, window: ResolvedDigestWindow, context: HandlerContext) => Promise<MetricValue>;
142
+ export interface OpsDigestEnv extends NotifyEnv {
143
+ fetch?: typeof fetch;
144
+ [key: string]: unknown;
145
+ }
146
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,2CAA2C,CAAA;AAC3E,OAAO,KAAK,EAAE,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAA;AAEnG,YAAY,EAAE,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,CAAA;AAE7C,MAAM,MAAM,YAAY,GAAG,OAAO,CACjC,IAAI,CAAC,WAAW,EAAE,QAAQ,GAAG,SAAS,GAAG,QAAQ,GAAG,eAAe,CAAC,CACpE,GAAG;IACH,QAAQ,CAAC,EAAE,OAAO,EAAE,CAAA;IACpB,QAAQ,CAAC,EAAE,QAAQ,CAAA;IACnB,aAAa,CAAC,EAAE,aAAa,CAAA;CAC7B,CAAA;AAED,MAAM,WAAW,eAAe;IAC/B,OAAO,EAAE,MAAM,CAAA;IACf,SAAS,EAAE,MAAM,CAAA;IACjB,OAAO,CAAC,EAAE,eAAe,CAAA;IACzB,UAAU,CAAC,EAAE,eAAe,CAAA;IAC5B,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAA;IAC1C,aAAa,EAAE,MAAM,CAAA;IACrB,YAAY,EAAE,YAAY,CAAA;IAC1B,OAAO,EAAE,gBAAgB,EAAE,CAAA;CAC3B;AAED,MAAM,WAAW,eAAe;IAC/B,SAAS,EAAE,MAAM,CAAA;IACjB,OAAO,EAAE,MAAM,CAAA;IACf,cAAc,EAAE,MAAM,CAAA;IACtB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,UAAU,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,MAAM,WAAW,gBAAgB;IAChC,IAAI,EAAE,MAAM,CAAA;IACZ,UAAU,EAAE,MAAM,CAAA;IAClB,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,EAAE,UAAU,CAAA;IAClB,OAAO,EAAE,gBAAgB,EAAE,CAAA;IAC3B,OAAO,EAAE,aAAa,CAAA;IACtB,MAAM,EAAE,UAAU,GAAG,MAAM,CAAA;IAC3B,QAAQ,EAAE,OAAO,EAAE,CAAA;CACnB;AAED,UAAU,YAAY;IACrB,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;IACb,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,cAAc,CAAC,EAAE,GAAG,GAAG,IAAI,CAAA;CAC3B;AAED,MAAM,MAAM,gBAAgB,GACzB,CAAC;IAAE,OAAO,EAAE,cAAc,CAAA;CAAE,GAAG,YAAY,CAAC,GAC5C,CAAC;IACD,OAAO,EAAE,uBAAuB,CAAA;IAChC,UAAU,EAAE,MAAM,EAAE,CAAA;IACpB,WAAW,CAAC,EAAE,MAAM,CAAA;CACnB,GAAG,YAAY,CAAC,GACjB;IAAE,OAAO,EAAE,iBAAiB,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GAC/E;IACA,OAAO,EAAE,yBAAyB,CAAA;IAClC,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;IACd,SAAS,EAAE,MAAM,CAAA;IACjB,OAAO,EAAE,MAAM,CAAA;CACd,GACD;IACA,OAAO,EAAE,kBAAkB,CAAA;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;IACd,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,UAAU,EAAE,MAAM,CAAA;CACjB,GACD;IACA,OAAO,EAAE,gBAAgB,CAAA;IACzB,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;IACd,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,WAAW,EAAE,MAAM,CAAA;CAClB,GACD;IACA,OAAO,EAAE,mBAAmB,CAAA;IAC5B,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;IACd,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,OAAO,EAAE,MAAM,CAAA;IACf,KAAK,EAAE,MAAM,CAAA;CACZ,GACD;IACA,OAAO,EAAE,iBAAiB,CAAA;IAC1B,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,EAAE,gBAAgB,CAAA;IAC3B,WAAW,EAAE,gBAAgB,CAAA;CAC5B,CAAA;AAEJ,MAAM,WAAW,aAAa;IAC7B,MAAM,EAAE,KAAK,GAAG,MAAM,CAAA;IACtB,WAAW,EAAE,MAAM,CAAA;IACnB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,aAAa,CAAC,CAAC,CAAA;CAClD;AAED,MAAM,WAAW,UAAU;IAC1B,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,MAAM,CAAA;IACd,GAAG,EAAE,MAAM,CAAA;IACX,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,OAAO,GAAG,OAAO,CAAA;CAC5B;AAED,MAAM,WAAW,eAAe;IAC/B,gBAAgB,EAAE,CACjB,KAAK,EAAE,cAAc,EACrB,GAAG,EAAE,YAAY,EACjB,GAAG,EAAE,gBAAgB,KACjB,OAAO,CAAC,IAAI,CAAC,CAAA;IAClB,SAAS,EAAE,CACV,UAAU,EAAE,MAAM,EAClB,GAAG,EAAE,YAAY,EACjB,GAAG,EAAE,gBAAgB,KACjB,OAAO,CAAC,eAAe,CAAC,CAAA;CAC7B;AAED,MAAM,WAAW,eAAe;IAC/B,UAAU,EAAE,MAAM,CAAA;IAClB,WAAW,EAAE,MAAM,CAAA;IACnB,SAAS,EAAE,MAAM,CAAA;IACjB,QAAQ,EAAE,MAAM,CAAA;IAChB,cAAc,EAAE,MAAM,CAAA;IACtB,MAAM,EAAE,OAAO,CAAA;IACf,OAAO,EAAE,YAAY,EAAE,CAAA;IACvB,MAAM,EAAE,MAAM,EAAE,CAAA;CAChB;AAED,MAAM,WAAW,aAAa;IAC7B,KAAK,EAAE,MAAM,CAAA;IACb,SAAS,EAAE,IAAI,GAAG,MAAM,GAAG,MAAM,CAAA;CACjC;AAED,MAAM,MAAM,mBAAmB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;AACxD,MAAM,MAAM,UAAU,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,EAAE,CAAA;AAC3D,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,mBAAmB,GAAG,UAAU,CAAA;AAEnE,MAAM,WAAW,YAAY;IAC5B,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,WAAW,CAAA;IACpB,QAAQ,EAAE,MAAM,CAAA;IAChB,KAAK,EAAE,aAAa,CAAA;IACpB,OAAO,CAAC,EAAE,UAAU,CAAA;CACpB;AAED,MAAM,WAAW,oBAAoB;IACpC,OAAO,EAAE,MAAM,CAAA;IACf,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,EAAE,MAAM,CAAA;CACd;AAED,MAAM,WAAW,cAAc;IAC9B,EAAE,CAAC,EAAE,UAAU,CAAA;IACf,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAA;IACzC,GAAG,CAAC,EAAE,YAAY,CAAA;CAClB;AAED,MAAM,MAAM,aAAa,CAAC,CAAC,SAAS,gBAAgB,GAAG,gBAAgB,IAAI,CAC1E,MAAM,EAAE,CAAC,EACT,MAAM,EAAE,oBAAoB,EAC5B,OAAO,EAAE,cAAc,KACnB,OAAO,CAAC,WAAW,CAAC,CAAA;AAEzB,MAAM,WAAW,YAAa,SAAQ,SAAS;IAC9C,KAAK,CAAC,EAAE,OAAO,KAAK,CAAA;IACpB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CACtB"}
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,7 @@
1
+ import { type WindowSpec } from '@growth-labs/analytics/utils/time-windows';
2
+ import type { ResolvedDigestWindow } from './types.js';
3
+ export declare function resolveDigestWindow(spec: WindowSpec, now?: number): ResolvedDigestWindow;
4
+ export declare function shiftWindowDays(window: ResolvedDigestWindow, daysBack: number): ResolvedDigestWindow;
5
+ export declare function splitTrailingDays(window: ResolvedDigestWindow, days: number): ResolvedDigestWindow[];
6
+ export declare function waeWindowSql(window: ResolvedDigestWindow, timestampColumn?: string): string;
7
+ //# sourceMappingURL=window.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"window.d.ts","sourceRoot":"","sources":["../src/window.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,KAAK,UAAU,EAAE,MAAM,2CAA2C,CAAA;AAC1F,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAA;AAItD,wBAAgB,mBAAmB,CAClC,IAAI,EAAE,UAAU,EAChB,GAAG,GAAE,MAAmB,GACtB,oBAAoB,CAEtB;AAED,wBAAgB,eAAe,CAC9B,MAAM,EAAE,oBAAoB,EAC5B,QAAQ,EAAE,MAAM,GACd,oBAAoB,CAGtB;AAED,wBAAgB,iBAAiB,CAChC,MAAM,EAAE,oBAAoB,EAC5B,IAAI,EAAE,MAAM,GACV,oBAAoB,EAAE,CAExB;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,oBAAoB,EAAE,eAAe,SAAc,GAAG,MAAM,CAEhG"}
package/dist/window.js ADDED
@@ -0,0 +1,28 @@
1
+ import { resolveWindow } from '@growth-labs/analytics/utils/time-windows';
2
+ const DAY_MS = 24 * 60 * 60 * 1000;
3
+ export function resolveDigestWindow(spec, now = Date.now()) {
4
+ return resolveWindow(spec, now);
5
+ }
6
+ export function shiftWindowDays(window, daysBack) {
7
+ const delta = daysBack * DAY_MS;
8
+ return literalWindow(window.startMs - delta, window.endMs - delta);
9
+ }
10
+ export function splitTrailingDays(window, days) {
11
+ return Array.from({ length: days }, (_, index) => shiftWindowDays(window, index + 1));
12
+ }
13
+ export function waeWindowSql(window, timestampColumn = 'timestamp') {
14
+ return `${timestampColumn} >= ${window.sqlStart} AND ${timestampColumn} < ${window.sqlEnd}`;
15
+ }
16
+ function literalWindow(startMs, endMs) {
17
+ return {
18
+ startMs,
19
+ endMs,
20
+ sqlStart: `toDateTime('${formatSqlDateTime(startMs)}')`,
21
+ sqlEnd: `toDateTime('${formatSqlDateTime(endMs)}')`,
22
+ };
23
+ }
24
+ function formatSqlDateTime(ms) {
25
+ const iso = new Date(ms).toISOString();
26
+ return iso.slice(0, 19).replace('T', ' ');
27
+ }
28
+ //# sourceMappingURL=window.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"window.js","sourceRoot":"","sources":["../src/window.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAmB,MAAM,2CAA2C,CAAA;AAG1F,MAAM,MAAM,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAA;AAElC,MAAM,UAAU,mBAAmB,CAClC,IAAgB,EAChB,MAAc,IAAI,CAAC,GAAG,EAAE;IAExB,OAAO,aAAa,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;AAChC,CAAC;AAED,MAAM,UAAU,eAAe,CAC9B,MAA4B,EAC5B,QAAgB;IAEhB,MAAM,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAA;IAC/B,OAAO,aAAa,CAAC,MAAM,CAAC,OAAO,GAAG,KAAK,EAAE,MAAM,CAAC,KAAK,GAAG,KAAK,CAAC,CAAA;AACnE,CAAC;AAED,MAAM,UAAU,iBAAiB,CAChC,MAA4B,EAC5B,IAAY;IAEZ,OAAO,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC,eAAe,CAAC,MAAM,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC,CAAA;AACtF,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,MAA4B,EAAE,eAAe,GAAG,WAAW;IACvF,OAAO,GAAG,eAAe,OAAO,MAAM,CAAC,QAAQ,QAAQ,eAAe,MAAM,MAAM,CAAC,MAAM,EAAE,CAAA;AAC5F,CAAC;AAED,SAAS,aAAa,CAAC,OAAe,EAAE,KAAa;IACpD,OAAO;QACN,OAAO;QACP,KAAK;QACL,QAAQ,EAAE,eAAe,iBAAiB,CAAC,OAAO,CAAC,IAAI;QACvD,MAAM,EAAE,eAAe,iBAAiB,CAAC,KAAK,CAAC,IAAI;KACnD,CAAA;AACF,CAAC;AAED,SAAS,iBAAiB,CAAC,EAAU;IACpC,MAAM,GAAG,GAAG,IAAI,IAAI,CAAC,EAAE,CAAC,CAAC,WAAW,EAAE,CAAA;IACtC,OAAO,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,CAAA;AAC1C,CAAC"}
package/package.json ADDED
@@ -0,0 +1,40 @@
1
+ {
2
+ "name": "@growth-labs/ops-digest",
3
+ "version": "0.1.0",
4
+ "description": "Worker-runtime digest engine for D1/WAE operational metrics, anomaly callouts, notify delivery, and KV idempotency.",
5
+ "type": "module",
6
+ "types": "./dist/index.d.ts",
7
+ "exports": {
8
+ ".": {
9
+ "types": "./dist/index.d.ts",
10
+ "import": "./dist/index.js"
11
+ }
12
+ },
13
+ "files": [
14
+ "dist",
15
+ "README.md",
16
+ "SPEC.md",
17
+ "CHANGELOG.md"
18
+ ],
19
+ "publishConfig": {
20
+ "access": "public",
21
+ "registry": "https://registry.npmjs.org/"
22
+ },
23
+ "dependencies": {
24
+ "@growth-labs/analytics": "^0.3.0",
25
+ "@growth-labs/notify": "^0.1.0",
26
+ "zod": "^3.23.0"
27
+ },
28
+ "devDependencies": {
29
+ "@cloudflare/workers-types": "^4.0.0",
30
+ "typescript": "^5.7.0",
31
+ "vitest": "^3.0.0"
32
+ },
33
+ "scripts": {
34
+ "build": "tsc",
35
+ "dev": "tsc --watch",
36
+ "test": "tsc --noEmit -p tsconfig.test.json && vitest run",
37
+ "test:watch": "vitest",
38
+ "check": "biome check src/ __tests__"
39
+ }
40
+ }