@contractspec/lib.analytics 1.56.1 → 1.58.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 (87) hide show
  1. package/dist/browser/churn/index.js +77 -0
  2. package/dist/browser/churn/predictor.js +77 -0
  3. package/dist/browser/cohort/index.js +117 -0
  4. package/dist/browser/cohort/tracker.js +117 -0
  5. package/dist/browser/funnel/analyzer.js +68 -0
  6. package/dist/browser/funnel/index.js +68 -0
  7. package/dist/browser/growth/hypothesis-generator.js +46 -0
  8. package/dist/browser/growth/index.js +46 -0
  9. package/dist/browser/index.js +723 -0
  10. package/dist/browser/lifecycle/index.js +287 -0
  11. package/dist/browser/lifecycle/metric-collectors.js +58 -0
  12. package/dist/browser/lifecycle/posthog-bridge.js +79 -0
  13. package/dist/browser/lifecycle/posthog-metric-source.js +205 -0
  14. package/dist/browser/posthog/event-source.js +138 -0
  15. package/dist/browser/posthog/index.js +138 -0
  16. package/dist/browser/types.js +0 -0
  17. package/dist/churn/index.d.ts +2 -2
  18. package/dist/churn/index.d.ts.map +1 -0
  19. package/dist/churn/index.js +77 -2
  20. package/dist/churn/predictor.d.ts +15 -19
  21. package/dist/churn/predictor.d.ts.map +1 -1
  22. package/dist/churn/predictor.js +72 -68
  23. package/dist/cohort/index.d.ts +2 -2
  24. package/dist/cohort/index.d.ts.map +1 -0
  25. package/dist/cohort/index.js +117 -2
  26. package/dist/cohort/tracker.d.ts +3 -7
  27. package/dist/cohort/tracker.d.ts.map +1 -1
  28. package/dist/cohort/tracker.js +106 -90
  29. package/dist/funnel/analyzer.d.ts +4 -8
  30. package/dist/funnel/analyzer.d.ts.map +1 -1
  31. package/dist/funnel/analyzer.js +67 -62
  32. package/dist/funnel/index.d.ts +2 -2
  33. package/dist/funnel/index.d.ts.map +1 -0
  34. package/dist/funnel/index.js +69 -3
  35. package/dist/growth/hypothesis-generator.d.ts +11 -15
  36. package/dist/growth/hypothesis-generator.d.ts.map +1 -1
  37. package/dist/growth/hypothesis-generator.js +46 -39
  38. package/dist/growth/index.d.ts +2 -2
  39. package/dist/growth/index.d.ts.map +1 -0
  40. package/dist/growth/index.js +47 -3
  41. package/dist/index.d.ts +8 -8
  42. package/dist/index.d.ts.map +1 -0
  43. package/dist/index.js +724 -10
  44. package/dist/lifecycle/index.d.ts +4 -3
  45. package/dist/lifecycle/index.d.ts.map +1 -0
  46. package/dist/lifecycle/index.js +287 -3
  47. package/dist/lifecycle/metric-collectors.d.ts +22 -26
  48. package/dist/lifecycle/metric-collectors.d.ts.map +1 -1
  49. package/dist/lifecycle/metric-collectors.js +55 -44
  50. package/dist/lifecycle/posthog-bridge.d.ts +9 -13
  51. package/dist/lifecycle/posthog-bridge.d.ts.map +1 -1
  52. package/dist/lifecycle/posthog-bridge.js +77 -25
  53. package/dist/lifecycle/posthog-metric-source.d.ts +43 -0
  54. package/dist/lifecycle/posthog-metric-source.d.ts.map +1 -0
  55. package/dist/lifecycle/posthog-metric-source.js +206 -0
  56. package/dist/node/churn/index.js +77 -0
  57. package/dist/node/churn/predictor.js +77 -0
  58. package/dist/node/cohort/index.js +117 -0
  59. package/dist/node/cohort/tracker.js +117 -0
  60. package/dist/node/funnel/analyzer.js +68 -0
  61. package/dist/node/funnel/index.js +68 -0
  62. package/dist/node/growth/hypothesis-generator.js +46 -0
  63. package/dist/node/growth/index.js +46 -0
  64. package/dist/node/index.js +723 -0
  65. package/dist/node/lifecycle/index.js +287 -0
  66. package/dist/node/lifecycle/metric-collectors.js +58 -0
  67. package/dist/node/lifecycle/posthog-bridge.js +79 -0
  68. package/dist/node/lifecycle/posthog-metric-source.js +205 -0
  69. package/dist/node/posthog/event-source.js +138 -0
  70. package/dist/node/posthog/index.js +138 -0
  71. package/dist/node/types.js +0 -0
  72. package/dist/posthog/event-source.d.ts +21 -0
  73. package/dist/posthog/event-source.d.ts.map +1 -0
  74. package/dist/posthog/event-source.js +139 -0
  75. package/dist/posthog/index.d.ts +2 -0
  76. package/dist/posthog/index.d.ts.map +1 -0
  77. package/dist/posthog/index.js +139 -0
  78. package/dist/types.d.ts +52 -55
  79. package/dist/types.d.ts.map +1 -1
  80. package/dist/types.js +1 -0
  81. package/package.json +189 -39
  82. package/dist/churn/predictor.js.map +0 -1
  83. package/dist/cohort/tracker.js.map +0 -1
  84. package/dist/funnel/analyzer.js.map +0 -1
  85. package/dist/growth/hypothesis-generator.js.map +0 -1
  86. package/dist/lifecycle/metric-collectors.js.map +0 -1
  87. package/dist/lifecycle/posthog-bridge.js.map +0 -1
package/dist/types.d.ts CHANGED
@@ -1,68 +1,65 @@
1
- //#region src/types.d.ts
2
- interface AnalyticsEvent {
3
- name: string;
4
- userId: string;
5
- tenantId?: string;
6
- timestamp: string | Date;
7
- properties?: Record<string, unknown>;
1
+ export interface AnalyticsEvent {
2
+ name: string;
3
+ userId: string;
4
+ tenantId?: string;
5
+ timestamp: string | Date;
6
+ properties?: Record<string, unknown>;
8
7
  }
9
- interface FunnelStep {
10
- id: string;
11
- eventName: string;
12
- match?: (event: AnalyticsEvent) => boolean;
8
+ export interface FunnelStep {
9
+ id: string;
10
+ eventName: string;
11
+ match?: (event: AnalyticsEvent) => boolean;
13
12
  }
14
- interface FunnelDefinition {
15
- name: string;
16
- steps: FunnelStep[];
17
- windowHours?: number;
13
+ export interface FunnelDefinition {
14
+ name: string;
15
+ steps: FunnelStep[];
16
+ windowHours?: number;
18
17
  }
19
- interface FunnelStepResult {
20
- step: FunnelStep;
21
- count: number;
22
- conversionRate: number;
23
- dropOffRate: number;
18
+ export interface FunnelStepResult {
19
+ step: FunnelStep;
20
+ count: number;
21
+ conversionRate: number;
22
+ dropOffRate: number;
24
23
  }
25
- interface FunnelAnalysis {
26
- definition: FunnelDefinition;
27
- totalUsers: number;
28
- steps: FunnelStepResult[];
24
+ export interface FunnelAnalysis {
25
+ definition: FunnelDefinition;
26
+ totalUsers: number;
27
+ steps: FunnelStepResult[];
29
28
  }
30
- interface CohortEvent extends AnalyticsEvent {
31
- amount?: number;
29
+ export interface CohortEvent extends AnalyticsEvent {
30
+ amount?: number;
32
31
  }
33
- interface CohortDefinition {
34
- bucket: 'day' | 'week' | 'month';
35
- periods: number;
36
- startDate?: Date;
32
+ export interface CohortDefinition {
33
+ bucket: 'day' | 'week' | 'month';
34
+ periods: number;
35
+ startDate?: Date;
37
36
  }
38
- interface CohortStats {
39
- cohortKey: string;
40
- users: number;
41
- retention: number[];
42
- ltv: number;
37
+ export interface CohortStats {
38
+ cohortKey: string;
39
+ users: number;
40
+ retention: number[];
41
+ ltv: number;
43
42
  }
44
- interface CohortAnalysis {
45
- definition: CohortDefinition;
46
- cohorts: CohortStats[];
43
+ export interface CohortAnalysis {
44
+ definition: CohortDefinition;
45
+ cohorts: CohortStats[];
47
46
  }
48
- interface ChurnSignal {
49
- userId: string;
50
- score: number;
51
- bucket: 'low' | 'medium' | 'high';
52
- drivers: string[];
47
+ export interface ChurnSignal {
48
+ userId: string;
49
+ score: number;
50
+ bucket: 'low' | 'medium' | 'high';
51
+ drivers: string[];
53
52
  }
54
- interface GrowthMetric {
55
- name: string;
56
- current: number;
57
- previous?: number;
58
- target?: number;
53
+ export interface GrowthMetric {
54
+ name: string;
55
+ current: number;
56
+ previous?: number;
57
+ target?: number;
59
58
  }
60
- interface GrowthHypothesis {
61
- statement: string;
62
- metric: string;
63
- confidence: 'low' | 'medium' | 'high';
64
- impact: 'low' | 'medium' | 'high';
59
+ export interface GrowthHypothesis {
60
+ statement: string;
61
+ metric: string;
62
+ confidence: 'low' | 'medium' | 'high';
63
+ impact: 'low' | 'medium' | 'high';
65
64
  }
66
- //#endregion
67
- export { AnalyticsEvent, ChurnSignal, CohortAnalysis, CohortDefinition, CohortEvent, CohortStats, FunnelAnalysis, FunnelDefinition, FunnelStep, FunnelStepResult, GrowthHypothesis, GrowthMetric };
68
65
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","names":[],"sources":["../src/types.ts"],"sourcesContent":[],"mappings":";UAAiB,cAAA;EAAA,IAAA,EAAA,MAAA;EAQA,MAAA,EAAA,MAAU;EAMV,QAAA,CAAA,EAAA,MAAA;EAMA,SAAA,EAAA,MAAA,GAhBK,IAgBW;EAOhB,UAAA,CAAA,EAtBF,MAsBgB,CAAA,MAAA,EACjB,OAAA,CAAA;AAKd;AAIiB,UA7BA,UAAA,CA6BgB;EAMhB,EAAA,EAAA,MAAA;EAOA,SAAA,EAAA,MAAc;EAKd,KAAA,CAAA,EAAA,CAAA,KAAW,EA5CV,cA4CU,EAAA,GAAA,OAAA;AAO5B;AAOiB,UAvDA,gBAAA,CAuDgB;;SArDxB;;;UAIQ,gBAAA;QACT;;;;;UAMS,cAAA;cACH;;SAEL;;UAGQ,WAAA,SAAoB;;;UAIpB,gBAAA;;;cAGH;;UAGG,WAAA;;;;;;UAOA,cAAA;cACH;WACH;;UAGM,WAAA;;;;;;UAOA,YAAA;;;;;;UAOA,gBAAA"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACtC;AAED,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,OAAO,CAAC;CAC5C;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,UAAU,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,cAAc;IAC7B,UAAU,EAAE,gBAAgB,CAAC;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,gBAAgB,EAAE,CAAC;CAC3B;AAED,MAAM,WAAW,WAAY,SAAQ,cAAc;IACjD,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,KAAK,GAAG,MAAM,GAAG,OAAO,CAAC;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,IAAI,CAAC;CAClB;AAED,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,cAAc;IAC7B,UAAU,EAAE,gBAAgB,CAAC;IAC7B,OAAO,EAAE,WAAW,EAAE,CAAC;CACxB;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;IAClC,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;IACtC,MAAM,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;CACnC"}
package/dist/types.js CHANGED
@@ -0,0 +1 @@
1
+ // @bun
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contractspec/lib.analytics",
3
- "version": "1.56.1",
3
+ "version": "1.58.0",
4
4
  "description": "Product analytics and growth metrics",
5
5
  "keywords": [
6
6
  "contractspec",
@@ -19,59 +19,209 @@
19
19
  "scripts": {
20
20
  "publish:pkg": "bun publish --tolerate-republish --ignore-scripts --verbose",
21
21
  "publish:pkg:canary": "bun publish:pkg --tag canary",
22
- "build": "bun build:types && bun build:bundle",
23
- "build:bundle": "tsdown",
24
- "build:types": "tsc --noEmit",
25
- "dev": "bun build:bundle --watch",
22
+ "build": "bun run prebuild && bun run build:bundle && bun run build:types",
23
+ "build:bundle": "contractspec-bun-build transpile",
24
+ "build:types": "contractspec-bun-build types",
25
+ "dev": "contractspec-bun-build dev",
26
26
  "clean": "rimraf dist .turbo",
27
27
  "lint": "bun lint:fix",
28
28
  "lint:fix": "eslint src --fix",
29
29
  "lint:check": "eslint src",
30
- "test": "bun test"
30
+ "test": "bun test",
31
+ "prebuild": "contractspec-bun-build prebuild",
32
+ "typecheck": "tsc --noEmit"
31
33
  },
32
34
  "dependencies": {
33
- "@contractspec/lib.lifecycle": "1.56.1",
35
+ "@contractspec/lib.contracts": "1.58.0",
36
+ "@contractspec/lib.lifecycle": "1.58.0",
34
37
  "dayjs": "^1.11.13"
35
38
  },
36
39
  "devDependencies": {
37
- "@contractspec/tool.tsdown": "1.56.1",
38
- "@contractspec/tool.typescript": "1.56.1",
39
- "tsdown": "^0.19.0",
40
- "typescript": "^5.9.3"
40
+ "@contractspec/tool.typescript": "1.58.0",
41
+ "typescript": "^5.9.3",
42
+ "@contractspec/tool.bun": "1.57.0"
41
43
  },
42
44
  "exports": {
43
- ".": "./dist/index.js",
44
- "./churn": "./dist/churn/index.js",
45
- "./churn/predictor": "./dist/churn/predictor.js",
46
- "./cohort": "./dist/cohort/index.js",
47
- "./cohort/tracker": "./dist/cohort/tracker.js",
48
- "./funnel": "./dist/funnel/index.js",
49
- "./funnel/analyzer": "./dist/funnel/analyzer.js",
50
- "./growth": "./dist/growth/index.js",
51
- "./growth/hypothesis-generator": "./dist/growth/hypothesis-generator.js",
52
- "./lifecycle": "./dist/lifecycle/index.js",
53
- "./lifecycle/metric-collectors": "./dist/lifecycle/metric-collectors.js",
54
- "./lifecycle/posthog-bridge": "./dist/lifecycle/posthog-bridge.js",
55
- "./types": "./dist/types.js",
56
- "./*": "./*"
45
+ ".": "./src/index.ts",
46
+ "./churn": "./src/churn/index.ts",
47
+ "./churn/index": "./src/churn/index.ts",
48
+ "./churn/predictor": "./src/churn/predictor.ts",
49
+ "./cohort": "./src/cohort/index.ts",
50
+ "./cohort/index": "./src/cohort/index.ts",
51
+ "./cohort/tracker": "./src/cohort/tracker.ts",
52
+ "./funnel": "./src/funnel/index.ts",
53
+ "./funnel/analyzer": "./src/funnel/analyzer.ts",
54
+ "./funnel/index": "./src/funnel/index.ts",
55
+ "./growth": "./src/growth/index.ts",
56
+ "./growth/hypothesis-generator": "./src/growth/hypothesis-generator.ts",
57
+ "./growth/index": "./src/growth/index.ts",
58
+ "./lifecycle": "./src/lifecycle/index.ts",
59
+ "./lifecycle/index": "./src/lifecycle/index.ts",
60
+ "./lifecycle/metric-collectors": "./src/lifecycle/metric-collectors.ts",
61
+ "./lifecycle/posthog-bridge": "./src/lifecycle/posthog-bridge.ts",
62
+ "./lifecycle/posthog-metric-source": "./src/lifecycle/posthog-metric-source.ts",
63
+ "./posthog": "./src/posthog/index.ts",
64
+ "./posthog/event-source": "./src/posthog/event-source.ts",
65
+ "./posthog/index": "./src/posthog/index.ts",
66
+ "./types": "./src/types.ts"
57
67
  },
58
68
  "publishConfig": {
59
69
  "access": "public",
60
70
  "exports": {
61
- ".": "./dist/index.js",
62
- "./churn": "./dist/churn/index.js",
63
- "./churn/predictor": "./dist/churn/predictor.js",
64
- "./cohort": "./dist/cohort/index.js",
65
- "./cohort/tracker": "./dist/cohort/tracker.js",
66
- "./funnel": "./dist/funnel/index.js",
67
- "./funnel/analyzer": "./dist/funnel/analyzer.js",
68
- "./growth": "./dist/growth/index.js",
69
- "./growth/hypothesis-generator": "./dist/growth/hypothesis-generator.js",
70
- "./lifecycle": "./dist/lifecycle/index.js",
71
- "./lifecycle/metric-collectors": "./dist/lifecycle/metric-collectors.js",
72
- "./lifecycle/posthog-bridge": "./dist/lifecycle/posthog-bridge.js",
73
- "./types": "./dist/types.js",
74
- "./*": "./*"
71
+ ".": {
72
+ "types": "./dist/index.d.ts",
73
+ "bun": "./dist/index.js",
74
+ "node": "./dist/node/index.mjs",
75
+ "browser": "./dist/browser/index.js",
76
+ "default": "./dist/index.js"
77
+ },
78
+ "./churn": {
79
+ "types": "./dist/churn/index.d.ts",
80
+ "bun": "./dist/churn/index.js",
81
+ "node": "./dist/node/churn/index.mjs",
82
+ "browser": "./dist/browser/churn/index.js",
83
+ "default": "./dist/churn/index.js"
84
+ },
85
+ "./churn/index": {
86
+ "types": "./dist/churn/index.d.ts",
87
+ "bun": "./dist/churn/index.js",
88
+ "node": "./dist/node/churn/index.mjs",
89
+ "browser": "./dist/browser/churn/index.js",
90
+ "default": "./dist/churn/index.js"
91
+ },
92
+ "./churn/predictor": {
93
+ "types": "./dist/churn/predictor.d.ts",
94
+ "bun": "./dist/churn/predictor.js",
95
+ "node": "./dist/node/churn/predictor.mjs",
96
+ "browser": "./dist/browser/churn/predictor.js",
97
+ "default": "./dist/churn/predictor.js"
98
+ },
99
+ "./cohort": {
100
+ "types": "./dist/cohort/index.d.ts",
101
+ "bun": "./dist/cohort/index.js",
102
+ "node": "./dist/node/cohort/index.mjs",
103
+ "browser": "./dist/browser/cohort/index.js",
104
+ "default": "./dist/cohort/index.js"
105
+ },
106
+ "./cohort/index": {
107
+ "types": "./dist/cohort/index.d.ts",
108
+ "bun": "./dist/cohort/index.js",
109
+ "node": "./dist/node/cohort/index.mjs",
110
+ "browser": "./dist/browser/cohort/index.js",
111
+ "default": "./dist/cohort/index.js"
112
+ },
113
+ "./cohort/tracker": {
114
+ "types": "./dist/cohort/tracker.d.ts",
115
+ "bun": "./dist/cohort/tracker.js",
116
+ "node": "./dist/node/cohort/tracker.mjs",
117
+ "browser": "./dist/browser/cohort/tracker.js",
118
+ "default": "./dist/cohort/tracker.js"
119
+ },
120
+ "./funnel": {
121
+ "types": "./dist/funnel/index.d.ts",
122
+ "bun": "./dist/funnel/index.js",
123
+ "node": "./dist/node/funnel/index.mjs",
124
+ "browser": "./dist/browser/funnel/index.js",
125
+ "default": "./dist/funnel/index.js"
126
+ },
127
+ "./funnel/analyzer": {
128
+ "types": "./dist/funnel/analyzer.d.ts",
129
+ "bun": "./dist/funnel/analyzer.js",
130
+ "node": "./dist/node/funnel/analyzer.mjs",
131
+ "browser": "./dist/browser/funnel/analyzer.js",
132
+ "default": "./dist/funnel/analyzer.js"
133
+ },
134
+ "./funnel/index": {
135
+ "types": "./dist/funnel/index.d.ts",
136
+ "bun": "./dist/funnel/index.js",
137
+ "node": "./dist/node/funnel/index.mjs",
138
+ "browser": "./dist/browser/funnel/index.js",
139
+ "default": "./dist/funnel/index.js"
140
+ },
141
+ "./growth": {
142
+ "types": "./dist/growth/index.d.ts",
143
+ "bun": "./dist/growth/index.js",
144
+ "node": "./dist/node/growth/index.mjs",
145
+ "browser": "./dist/browser/growth/index.js",
146
+ "default": "./dist/growth/index.js"
147
+ },
148
+ "./growth/hypothesis-generator": {
149
+ "types": "./dist/growth/hypothesis-generator.d.ts",
150
+ "bun": "./dist/growth/hypothesis-generator.js",
151
+ "node": "./dist/node/growth/hypothesis-generator.mjs",
152
+ "browser": "./dist/browser/growth/hypothesis-generator.js",
153
+ "default": "./dist/growth/hypothesis-generator.js"
154
+ },
155
+ "./growth/index": {
156
+ "types": "./dist/growth/index.d.ts",
157
+ "bun": "./dist/growth/index.js",
158
+ "node": "./dist/node/growth/index.mjs",
159
+ "browser": "./dist/browser/growth/index.js",
160
+ "default": "./dist/growth/index.js"
161
+ },
162
+ "./lifecycle": {
163
+ "types": "./dist/lifecycle/index.d.ts",
164
+ "bun": "./dist/lifecycle/index.js",
165
+ "node": "./dist/node/lifecycle/index.mjs",
166
+ "browser": "./dist/browser/lifecycle/index.js",
167
+ "default": "./dist/lifecycle/index.js"
168
+ },
169
+ "./lifecycle/index": {
170
+ "types": "./dist/lifecycle/index.d.ts",
171
+ "bun": "./dist/lifecycle/index.js",
172
+ "node": "./dist/node/lifecycle/index.mjs",
173
+ "browser": "./dist/browser/lifecycle/index.js",
174
+ "default": "./dist/lifecycle/index.js"
175
+ },
176
+ "./lifecycle/metric-collectors": {
177
+ "types": "./dist/lifecycle/metric-collectors.d.ts",
178
+ "bun": "./dist/lifecycle/metric-collectors.js",
179
+ "node": "./dist/node/lifecycle/metric-collectors.mjs",
180
+ "browser": "./dist/browser/lifecycle/metric-collectors.js",
181
+ "default": "./dist/lifecycle/metric-collectors.js"
182
+ },
183
+ "./lifecycle/posthog-bridge": {
184
+ "types": "./dist/lifecycle/posthog-bridge.d.ts",
185
+ "bun": "./dist/lifecycle/posthog-bridge.js",
186
+ "node": "./dist/node/lifecycle/posthog-bridge.mjs",
187
+ "browser": "./dist/browser/lifecycle/posthog-bridge.js",
188
+ "default": "./dist/lifecycle/posthog-bridge.js"
189
+ },
190
+ "./lifecycle/posthog-metric-source": {
191
+ "types": "./dist/lifecycle/posthog-metric-source.d.ts",
192
+ "bun": "./dist/lifecycle/posthog-metric-source.js",
193
+ "node": "./dist/node/lifecycle/posthog-metric-source.mjs",
194
+ "browser": "./dist/browser/lifecycle/posthog-metric-source.js",
195
+ "default": "./dist/lifecycle/posthog-metric-source.js"
196
+ },
197
+ "./posthog": {
198
+ "types": "./dist/posthog/index.d.ts",
199
+ "bun": "./dist/posthog/index.js",
200
+ "node": "./dist/node/posthog/index.mjs",
201
+ "browser": "./dist/browser/posthog/index.js",
202
+ "default": "./dist/posthog/index.js"
203
+ },
204
+ "./posthog/event-source": {
205
+ "types": "./dist/posthog/event-source.d.ts",
206
+ "bun": "./dist/posthog/event-source.js",
207
+ "node": "./dist/node/posthog/event-source.mjs",
208
+ "browser": "./dist/browser/posthog/event-source.js",
209
+ "default": "./dist/posthog/event-source.js"
210
+ },
211
+ "./posthog/index": {
212
+ "types": "./dist/posthog/index.d.ts",
213
+ "bun": "./dist/posthog/index.js",
214
+ "node": "./dist/node/posthog/index.mjs",
215
+ "browser": "./dist/browser/posthog/index.js",
216
+ "default": "./dist/posthog/index.js"
217
+ },
218
+ "./types": {
219
+ "types": "./dist/types.d.ts",
220
+ "bun": "./dist/types.js",
221
+ "node": "./dist/node/types.mjs",
222
+ "browser": "./dist/browser/types.js",
223
+ "default": "./dist/types.js"
224
+ }
75
225
  },
76
226
  "registry": "https://registry.npmjs.org/"
77
227
  },
@@ -1 +0,0 @@
1
- {"version":3,"file":"predictor.js","names":[],"sources":["../../src/churn/predictor.ts"],"sourcesContent":["import dayjs from 'dayjs';\nimport type { AnalyticsEvent, ChurnSignal } from '../types';\n\nexport interface ChurnPredictorOptions {\n recencyWeight?: number;\n frequencyWeight?: number;\n errorWeight?: number;\n decayDays?: number;\n}\n\nexport class ChurnPredictor {\n private readonly recencyWeight: number;\n private readonly frequencyWeight: number;\n private readonly errorWeight: number;\n private readonly decayDays: number;\n\n constructor(options?: ChurnPredictorOptions) {\n this.recencyWeight = options?.recencyWeight ?? 0.5;\n this.frequencyWeight = options?.frequencyWeight ?? 0.3;\n this.errorWeight = options?.errorWeight ?? 0.2;\n this.decayDays = options?.decayDays ?? 14;\n }\n\n score(events: AnalyticsEvent[]): ChurnSignal[] {\n const grouped = groupBy(events, (event) => event.userId);\n const signals: ChurnSignal[] = [];\n for (const [userId, userEvents] of grouped.entries()) {\n const score = this.computeScore(userEvents);\n signals.push({\n userId,\n score,\n bucket: score >= 0.7 ? 'high' : score >= 0.4 ? 'medium' : 'low',\n drivers: this.drivers(userEvents),\n });\n }\n return signals.sort((a, b) => b.score - a.score);\n }\n\n private computeScore(events: AnalyticsEvent[]): number {\n if (!events.length) return 0;\n const sorted = events.sort((a, b) => dateMs(a) - dateMs(b));\n const lastEvent = sorted[sorted.length - 1];\n if (!lastEvent) return 0;\n const daysSinceLast = dayjs().diff(dayjs(lastEvent.timestamp), 'day');\n const recencyScore = Math.max(0, 1 - daysSinceLast / this.decayDays);\n\n const windowStart = dayjs().subtract(this.decayDays, 'day');\n const recentEvents = sorted.filter((event) =>\n dayjs(event.timestamp).isAfter(windowStart)\n );\n const averagePerDay = recentEvents.length / Math.max(this.decayDays, 1);\n const frequencyScore = Math.min(1, averagePerDay * 5);\n\n const errorEvents = recentEvents.filter(\n (event) =>\n typeof event.properties?.error !== 'undefined' ||\n /error|failed/i.test(event.name)\n ).length;\n const errorScore = Math.min(1, errorEvents / 3);\n\n const score =\n recencyScore * this.recencyWeight +\n frequencyScore * this.frequencyWeight +\n (1 - errorScore) * this.errorWeight;\n return Number(score.toFixed(3));\n }\n\n private drivers(events: AnalyticsEvent[]): string[] {\n const drivers: string[] = [];\n const sorted = events.sort((a, b) => dateMs(a) - dateMs(b));\n const lastEvent = sorted[sorted.length - 1];\n if (lastEvent) {\n const days = dayjs().diff(dayjs(lastEvent.timestamp), 'day');\n if (days > this.decayDays) drivers.push(`Inactive for ${days} days`);\n }\n const errorEvents = events.filter(\n (event) =>\n typeof event.properties?.error !== 'undefined' ||\n /error|failed/i.test(event.name)\n );\n if (errorEvents.length) drivers.push(`${errorEvents.length} errors logged`);\n return drivers;\n }\n}\n\nfunction groupBy<T>(\n items: T[],\n selector: (item: T) => string\n): Map<string, T[]> {\n const map = new Map<string, T[]>();\n for (const item of items) {\n const key = selector(item);\n const list = map.get(key) ?? [];\n list.push(item);\n map.set(key, list);\n }\n return map;\n}\n\nfunction dateMs(event: AnalyticsEvent) {\n return new Date(event.timestamp).getTime();\n}\n"],"mappings":";;;AAUA,IAAa,iBAAb,MAA4B;CAC1B,AAAiB;CACjB,AAAiB;CACjB,AAAiB;CACjB,AAAiB;CAEjB,YAAY,SAAiC;AAC3C,OAAK,gBAAgB,SAAS,iBAAiB;AAC/C,OAAK,kBAAkB,SAAS,mBAAmB;AACnD,OAAK,cAAc,SAAS,eAAe;AAC3C,OAAK,YAAY,SAAS,aAAa;;CAGzC,MAAM,QAAyC;EAC7C,MAAM,UAAU,QAAQ,SAAS,UAAU,MAAM,OAAO;EACxD,MAAM,UAAyB,EAAE;AACjC,OAAK,MAAM,CAAC,QAAQ,eAAe,QAAQ,SAAS,EAAE;GACpD,MAAM,QAAQ,KAAK,aAAa,WAAW;AAC3C,WAAQ,KAAK;IACX;IACA;IACA,QAAQ,SAAS,KAAM,SAAS,SAAS,KAAM,WAAW;IAC1D,SAAS,KAAK,QAAQ,WAAW;IAClC,CAAC;;AAEJ,SAAO,QAAQ,MAAM,GAAG,MAAM,EAAE,QAAQ,EAAE,MAAM;;CAGlD,AAAQ,aAAa,QAAkC;AACrD,MAAI,CAAC,OAAO,OAAQ,QAAO;EAC3B,MAAM,SAAS,OAAO,MAAM,GAAG,MAAM,OAAO,EAAE,GAAG,OAAO,EAAE,CAAC;EAC3D,MAAM,YAAY,OAAO,OAAO,SAAS;AACzC,MAAI,CAAC,UAAW,QAAO;EACvB,MAAM,gBAAgB,OAAO,CAAC,KAAK,MAAM,UAAU,UAAU,EAAE,MAAM;EACrE,MAAM,eAAe,KAAK,IAAI,GAAG,IAAI,gBAAgB,KAAK,UAAU;EAEpE,MAAM,cAAc,OAAO,CAAC,SAAS,KAAK,WAAW,MAAM;EAC3D,MAAM,eAAe,OAAO,QAAQ,UAClC,MAAM,MAAM,UAAU,CAAC,QAAQ,YAAY,CAC5C;EACD,MAAM,gBAAgB,aAAa,SAAS,KAAK,IAAI,KAAK,WAAW,EAAE;EACvE,MAAM,iBAAiB,KAAK,IAAI,GAAG,gBAAgB,EAAE;EAErD,MAAM,cAAc,aAAa,QAC9B,UACC,OAAO,MAAM,YAAY,UAAU,eACnC,gBAAgB,KAAK,MAAM,KAAK,CACnC,CAAC;EACF,MAAM,aAAa,KAAK,IAAI,GAAG,cAAc,EAAE;EAE/C,MAAM,QACJ,eAAe,KAAK,gBACpB,iBAAiB,KAAK,mBACrB,IAAI,cAAc,KAAK;AAC1B,SAAO,OAAO,MAAM,QAAQ,EAAE,CAAC;;CAGjC,AAAQ,QAAQ,QAAoC;EAClD,MAAM,UAAoB,EAAE;EAC5B,MAAM,SAAS,OAAO,MAAM,GAAG,MAAM,OAAO,EAAE,GAAG,OAAO,EAAE,CAAC;EAC3D,MAAM,YAAY,OAAO,OAAO,SAAS;AACzC,MAAI,WAAW;GACb,MAAM,OAAO,OAAO,CAAC,KAAK,MAAM,UAAU,UAAU,EAAE,MAAM;AAC5D,OAAI,OAAO,KAAK,UAAW,SAAQ,KAAK,gBAAgB,KAAK,OAAO;;EAEtE,MAAM,cAAc,OAAO,QACxB,UACC,OAAO,MAAM,YAAY,UAAU,eACnC,gBAAgB,KAAK,MAAM,KAAK,CACnC;AACD,MAAI,YAAY,OAAQ,SAAQ,KAAK,GAAG,YAAY,OAAO,gBAAgB;AAC3E,SAAO;;;AAIX,SAAS,QACP,OACA,UACkB;CAClB,MAAM,sBAAM,IAAI,KAAkB;AAClC,MAAK,MAAM,QAAQ,OAAO;EACxB,MAAM,MAAM,SAAS,KAAK;EAC1B,MAAM,OAAO,IAAI,IAAI,IAAI,IAAI,EAAE;AAC/B,OAAK,KAAK,KAAK;AACf,MAAI,IAAI,KAAK,KAAK;;AAEpB,QAAO;;AAGT,SAAS,OAAO,OAAuB;AACrC,QAAO,IAAI,KAAK,MAAM,UAAU,CAAC,SAAS"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"tracker.js","names":[],"sources":["../../src/cohort/tracker.ts"],"sourcesContent":["import dayjs from 'dayjs';\nimport type {\n AnalyticsEvent,\n CohortAnalysis,\n CohortDefinition,\n CohortStats,\n} from '../types';\n\nexport class CohortTracker {\n analyze(\n events: AnalyticsEvent[],\n definition: CohortDefinition\n ): CohortAnalysis {\n const groupedByUser = groupBy(events, (event) => event.userId);\n const cohorts = new Map<string, CohortStatsBuilder>();\n\n for (const [userId, userEvents] of groupedByUser.entries()) {\n userEvents.sort((a, b) => dateMs(a) - dateMs(b));\n const signup = userEvents[0];\n if (!signup) continue;\n const cohortKey = bucketKey(signup.timestamp, definition.bucket);\n const builder =\n cohorts.get(cohortKey) ?? new CohortStatsBuilder(cohortKey, definition);\n builder.addUser(userId);\n for (const event of userEvents) {\n builder.addEvent(userId, event);\n }\n cohorts.set(cohortKey, builder);\n }\n\n return {\n definition,\n cohorts: [...cohorts.values()].map((builder) => builder.build()),\n };\n }\n}\n\nclass CohortStatsBuilder {\n private readonly users = new Set<string>();\n private readonly retentionMap = new Map<number, Set<string>>();\n private ltv = 0;\n constructor(\n private readonly key: string,\n private readonly definition: CohortDefinition\n ) {}\n\n addUser(userId: string) {\n this.users.add(userId);\n }\n\n addEvent(userId: string, event: AnalyticsEvent) {\n const period = bucketDiff(\n this.key,\n event.timestamp,\n this.definition.bucket\n );\n if (period < 0 || period >= this.definition.periods) return;\n const bucket = this.retentionMap.get(period) ?? new Set<string>();\n bucket.add(userId);\n this.retentionMap.set(period, bucket);\n const amount =\n typeof event.properties?.amount === 'number'\n ? event.properties.amount\n : 0;\n this.ltv += amount;\n }\n\n build(): CohortStats {\n const totalUsers = this.users.size || 1;\n const retention: number[] = [];\n for (let period = 0; period < this.definition.periods; period++) {\n const active = this.retentionMap.get(period)?.size ?? 0;\n retention.push(Number((active / totalUsers).toFixed(3)));\n }\n return {\n cohortKey: this.key,\n users: this.users.size,\n retention,\n ltv: Number(this.ltv.toFixed(2)),\n };\n }\n}\n\nfunction groupBy<T>(\n items: T[],\n selector: (item: T) => string\n): Map<string, T[]> {\n const map = new Map<string, T[]>();\n for (const item of items) {\n const key = selector(item);\n const list = map.get(key) ?? [];\n list.push(item);\n map.set(key, list);\n }\n return map;\n}\n\nfunction bucketKey(\n timestamp: string | Date,\n bucket: CohortDefinition['bucket']\n): string {\n const dt = dayjs(timestamp);\n switch (bucket) {\n case 'day':\n return dt.startOf('day').format('YYYY-MM-DD');\n case 'week':\n return dt.startOf('week').format('YYYY-[W]WW');\n case 'month':\n default:\n return dt.startOf('month').format('YYYY-MM');\n }\n}\n\nfunction bucketDiff(\n cohortKey: string,\n timestamp: string | Date,\n bucket: CohortDefinition['bucket']\n): number {\n const start = parseBucketKey(cohortKey, bucket);\n const target = dayjs(timestamp);\n switch (bucket) {\n case 'day':\n return target.diff(start, 'day');\n case 'week':\n return target.diff(start, 'week');\n case 'month':\n default:\n return target.diff(start, 'month');\n }\n}\n\nfunction parseBucketKey(key: string, bucket: CohortDefinition['bucket']) {\n switch (bucket) {\n case 'day':\n return dayjs(key, 'YYYY-MM-DD');\n case 'week':\n return dayjs(key.replace('W', ''), 'YYYY-ww');\n case 'month':\n default:\n return dayjs(key, 'YYYY-MM');\n }\n}\n\nfunction dateMs(event: AnalyticsEvent) {\n return new Date(event.timestamp).getTime();\n}\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"analyzer.js","names":[],"sources":["../../src/funnel/analyzer.ts"],"sourcesContent":["import type {\n AnalyticsEvent,\n FunnelAnalysis,\n FunnelDefinition,\n FunnelStep,\n FunnelStepResult,\n} from '../types';\n\nexport class FunnelAnalyzer {\n analyze(\n events: AnalyticsEvent[],\n definition: FunnelDefinition\n ): FunnelAnalysis {\n const windowMs = (definition.windowHours ?? 72) * 60 * 60 * 1000;\n const eventsByUser = groupByUser(events);\n const stepCounts = definition.steps.map(() => 0);\n\n for (const userEvents of eventsByUser.values()) {\n const completionIndex = this.evaluateUser(\n userEvents,\n definition.steps,\n windowMs\n );\n completionIndex.forEach((hit, stepIdx) => {\n if (hit) {\n stepCounts[stepIdx] = (stepCounts[stepIdx] ?? 0) + 1;\n }\n });\n }\n\n const totalUsers = eventsByUser.size;\n const steps: FunnelStepResult[] = definition.steps.map((step, index) => {\n const prevCount = index === 0 ? totalUsers : stepCounts[index - 1] || 1;\n const count = stepCounts[index] ?? 0;\n const conversionRate =\n prevCount === 0 ? 0 : Number((count / prevCount).toFixed(3));\n const dropOffRate = Number((1 - conversionRate).toFixed(3));\n return { step, count, conversionRate, dropOffRate };\n });\n\n return {\n definition,\n totalUsers,\n steps,\n };\n }\n\n private evaluateUser(\n events: AnalyticsEvent[],\n steps: FunnelStep[],\n windowMs: number\n ) {\n const sorted = [...events].sort(\n (a, b) =>\n new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime()\n );\n const completion: boolean[] = Array(steps.length).fill(false);\n let cursor = 0;\n let anchorTime: number | undefined;\n\n for (const event of sorted) {\n const step = steps[cursor];\n if (!step) break;\n if (event.name !== step.eventName) continue;\n if (step.match && !step.match(event)) continue;\n\n const eventTime = new Date(event.timestamp).getTime();\n if (cursor === 0) {\n anchorTime = eventTime;\n completion[cursor] = true;\n cursor += 1;\n continue;\n }\n\n if (anchorTime && eventTime - anchorTime <= windowMs) {\n completion[cursor] = true;\n cursor += 1;\n }\n }\n\n return completion;\n }\n}\n\nfunction groupByUser(events: AnalyticsEvent[]): Map<string, AnalyticsEvent[]> {\n const map = new Map<string, AnalyticsEvent[]>();\n for (const event of events) {\n const list = map.get(event.userId) ?? [];\n list.push(event);\n map.set(event.userId, list);\n }\n return map;\n}\n"],"mappings":";AAQA,IAAa,iBAAb,MAA4B;CAC1B,QACE,QACA,YACgB;EAChB,MAAM,YAAY,WAAW,eAAe,MAAM,KAAK,KAAK;EAC5D,MAAM,eAAe,YAAY,OAAO;EACxC,MAAM,aAAa,WAAW,MAAM,UAAU,EAAE;AAEhD,OAAK,MAAM,cAAc,aAAa,QAAQ,CAM5C,CALwB,KAAK,aAC3B,YACA,WAAW,OACX,SACD,CACe,SAAS,KAAK,YAAY;AACxC,OAAI,IACF,YAAW,YAAY,WAAW,YAAY,KAAK;IAErD;EAGJ,MAAM,aAAa,aAAa;AAUhC,SAAO;GACL;GACA;GACA,OAZgC,WAAW,MAAM,KAAK,MAAM,UAAU;IACtE,MAAM,YAAY,UAAU,IAAI,aAAa,WAAW,QAAQ,MAAM;IACtE,MAAM,QAAQ,WAAW,UAAU;IACnC,MAAM,iBACJ,cAAc,IAAI,IAAI,QAAQ,QAAQ,WAAW,QAAQ,EAAE,CAAC;AAE9D,WAAO;KAAE;KAAM;KAAO;KAAgB,aADlB,QAAQ,IAAI,gBAAgB,QAAQ,EAAE,CAAC;KACR;KACnD;GAMD;;CAGH,AAAQ,aACN,QACA,OACA,UACA;EACA,MAAM,SAAS,CAAC,GAAG,OAAO,CAAC,MACxB,GAAG,MACF,IAAI,KAAK,EAAE,UAAU,CAAC,SAAS,GAAG,IAAI,KAAK,EAAE,UAAU,CAAC,SAAS,CACpE;EACD,MAAM,aAAwB,MAAM,MAAM,OAAO,CAAC,KAAK,MAAM;EAC7D,IAAI,SAAS;EACb,IAAI;AAEJ,OAAK,MAAM,SAAS,QAAQ;GAC1B,MAAM,OAAO,MAAM;AACnB,OAAI,CAAC,KAAM;AACX,OAAI,MAAM,SAAS,KAAK,UAAW;AACnC,OAAI,KAAK,SAAS,CAAC,KAAK,MAAM,MAAM,CAAE;GAEtC,MAAM,YAAY,IAAI,KAAK,MAAM,UAAU,CAAC,SAAS;AACrD,OAAI,WAAW,GAAG;AAChB,iBAAa;AACb,eAAW,UAAU;AACrB,cAAU;AACV;;AAGF,OAAI,cAAc,YAAY,cAAc,UAAU;AACpD,eAAW,UAAU;AACrB,cAAU;;;AAId,SAAO;;;AAIX,SAAS,YAAY,QAAyD;CAC5E,MAAM,sBAAM,IAAI,KAA+B;AAC/C,MAAK,MAAM,SAAS,QAAQ;EAC1B,MAAM,OAAO,IAAI,IAAI,MAAM,OAAO,IAAI,EAAE;AACxC,OAAK,KAAK,MAAM;AAChB,MAAI,IAAI,MAAM,QAAQ,KAAK;;AAE7B,QAAO"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"hypothesis-generator.js","names":[],"sources":["../../src/growth/hypothesis-generator.ts"],"sourcesContent":["import type { GrowthHypothesis, GrowthMetric } from '../types';\n\nexport interface HypothesisGeneratorOptions {\n minDelta?: number;\n}\n\nexport class GrowthHypothesisGenerator {\n private readonly minDelta: number;\n\n constructor(options?: HypothesisGeneratorOptions) {\n this.minDelta = options?.minDelta ?? 0.05;\n }\n\n generate(metrics: GrowthMetric[]): GrowthHypothesis[] {\n return metrics\n .map((metric) => this.fromMetric(metric))\n .filter((hypothesis): hypothesis is GrowthHypothesis =>\n Boolean(hypothesis)\n );\n }\n\n private fromMetric(metric: GrowthMetric): GrowthHypothesis | null {\n const change = this.delta(metric);\n if (Math.abs(change) < this.minDelta) return null;\n const direction = change > 0 ? 'rising' : 'declining';\n const statement = this.statement(metric, change, direction);\n return {\n statement,\n metric: metric.name,\n confidence: Math.abs(change) > 0.2 ? 'high' : 'medium',\n impact: this.impact(metric),\n };\n }\n\n private delta(metric: GrowthMetric): number {\n if (metric.previous == null) return 0;\n const prev = metric.previous || 1;\n return (metric.current - prev) / Math.abs(prev);\n }\n\n private impact(metric: GrowthMetric): GrowthHypothesis['impact'] {\n if (metric.target && metric.current < metric.target * 0.8) return 'high';\n if (metric.target && metric.current < metric.target) return 'medium';\n return 'low';\n }\n\n private statement(\n metric: GrowthMetric,\n change: number,\n direction: string\n ): string {\n const percent = Math.abs(parseFloat((change * 100).toFixed(1)));\n if (direction === 'declining') {\n return `${metric.name} is down ${percent}% vs last period; test new onboarding prompts to recover activation.`;\n }\n return `${metric.name} grew ${percent}% period-over-period; double down with expanded experiment or pricing test.`;\n }\n}\n"],"mappings":";AAMA,IAAa,4BAAb,MAAuC;CACrC,AAAiB;CAEjB,YAAY,SAAsC;AAChD,OAAK,WAAW,SAAS,YAAY;;CAGvC,SAAS,SAA6C;AACpD,SAAO,QACJ,KAAK,WAAW,KAAK,WAAW,OAAO,CAAC,CACxC,QAAQ,eACP,QAAQ,WAAW,CACpB;;CAGL,AAAQ,WAAW,QAA+C;EAChE,MAAM,SAAS,KAAK,MAAM,OAAO;AACjC,MAAI,KAAK,IAAI,OAAO,GAAG,KAAK,SAAU,QAAO;EAC7C,MAAM,YAAY,SAAS,IAAI,WAAW;AAE1C,SAAO;GACL,WAFgB,KAAK,UAAU,QAAQ,QAAQ,UAAU;GAGzD,QAAQ,OAAO;GACf,YAAY,KAAK,IAAI,OAAO,GAAG,KAAM,SAAS;GAC9C,QAAQ,KAAK,OAAO,OAAO;GAC5B;;CAGH,AAAQ,MAAM,QAA8B;AAC1C,MAAI,OAAO,YAAY,KAAM,QAAO;EACpC,MAAM,OAAO,OAAO,YAAY;AAChC,UAAQ,OAAO,UAAU,QAAQ,KAAK,IAAI,KAAK;;CAGjD,AAAQ,OAAO,QAAkD;AAC/D,MAAI,OAAO,UAAU,OAAO,UAAU,OAAO,SAAS,GAAK,QAAO;AAClE,MAAI,OAAO,UAAU,OAAO,UAAU,OAAO,OAAQ,QAAO;AAC5D,SAAO;;CAGT,AAAQ,UACN,QACA,QACA,WACQ;EACR,MAAM,UAAU,KAAK,IAAI,YAAY,SAAS,KAAK,QAAQ,EAAE,CAAC,CAAC;AAC/D,MAAI,cAAc,YAChB,QAAO,GAAG,OAAO,KAAK,WAAW,QAAQ;AAE3C,SAAO,GAAG,OAAO,KAAK,QAAQ,QAAQ"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"metric-collectors.js","names":[],"sources":["../../src/lifecycle/metric-collectors.ts"],"sourcesContent":["import type {\n LifecycleMetricSnapshot,\n LifecycleSignal,\n LifecycleStage,\n} from '@contractspec/lib.lifecycle';\nimport type { AnalyticsEvent } from '../types';\n\nexport interface LifecycleMetricSource {\n getActiveUsers(): Promise<number | undefined>;\n getWeeklyActiveUsers?(): Promise<number | undefined>;\n getRetentionRate?(): Promise<number | undefined>;\n getMonthlyRecurringRevenue?(): Promise<number | undefined>;\n getCustomerCount?(): Promise<number | undefined>;\n getTeamSize?(): Promise<number | undefined>;\n getBurnMultiple?(): Promise<number | undefined>;\n}\n\nexport const collectLifecycleMetrics = async (\n source: LifecycleMetricSource\n): Promise<LifecycleMetricSnapshot> => {\n const [\n activeUsers,\n weeklyActiveUsers,\n retentionRate,\n monthlyRecurringRevenue,\n customerCount,\n teamSize,\n burnMultiple,\n ] = await Promise.all([\n source.getActiveUsers(),\n source.getWeeklyActiveUsers?.(),\n source.getRetentionRate?.(),\n source.getMonthlyRecurringRevenue?.(),\n source.getCustomerCount?.(),\n source.getTeamSize?.(),\n source.getBurnMultiple?.(),\n ]);\n\n return {\n activeUsers,\n weeklyActiveUsers,\n retentionRate,\n monthlyRecurringRevenue,\n customerCount,\n teamSize,\n burnMultiple,\n };\n};\n\nexport const metricsToSignals = (\n metrics: LifecycleMetricSnapshot,\n tenantId?: string\n): LifecycleSignal[] =>\n Object.entries(metrics)\n .filter(([, value]) => value !== undefined && value !== null)\n .map(([metricKey, value]) => ({\n id: `lifecycle-metric:${metricKey}`,\n kind: 'metric',\n source: 'analytics',\n name: metricKey,\n value,\n weight: 1,\n confidence: 0.8,\n details: tenantId ? { tenantId } : undefined,\n capturedAt: new Date().toISOString(),\n }));\n\nexport const lifecycleEventNames = {\n assessmentRun: 'lifecycle_assessment_run',\n stageChanged: 'lifecycle_stage_changed',\n guidanceConsumed: 'lifecycle_guidance_consumed',\n} as const;\n\nexport interface LifecycleStageChangePayload {\n tenantId?: string;\n previousStage?: LifecycleStage;\n nextStage: LifecycleStage;\n confidence: number;\n}\n\nexport const createStageChangeEvent = (\n payload: LifecycleStageChangePayload\n): AnalyticsEvent => ({\n name: lifecycleEventNames.stageChanged,\n userId: 'system',\n tenantId: payload.tenantId,\n timestamp: new Date(),\n properties: { ...payload },\n});\n"],"mappings":";AAiBA,MAAa,0BAA0B,OACrC,WACqC;CACrC,MAAM,CACJ,aACA,mBACA,eACA,yBACA,eACA,UACA,gBACE,MAAM,QAAQ,IAAI;EACpB,OAAO,gBAAgB;EACvB,OAAO,wBAAwB;EAC/B,OAAO,oBAAoB;EAC3B,OAAO,8BAA8B;EACrC,OAAO,oBAAoB;EAC3B,OAAO,eAAe;EACtB,OAAO,mBAAmB;EAC3B,CAAC;AAEF,QAAO;EACL;EACA;EACA;EACA;EACA;EACA;EACA;EACD;;AAGH,MAAa,oBACX,SACA,aAEA,OAAO,QAAQ,QAAQ,CACpB,QAAQ,GAAG,WAAW,UAAU,UAAa,UAAU,KAAK,CAC5D,KAAK,CAAC,WAAW,YAAY;CAC5B,IAAI,oBAAoB;CACxB,MAAM;CACN,QAAQ;CACR,MAAM;CACN;CACA,QAAQ;CACR,YAAY;CACZ,SAAS,WAAW,EAAE,UAAU,GAAG;CACnC,6BAAY,IAAI,MAAM,EAAC,aAAa;CACrC,EAAE;AAEP,MAAa,sBAAsB;CACjC,eAAe;CACf,cAAc;CACd,kBAAkB;CACnB;AASD,MAAa,0BACX,aACoB;CACpB,MAAM,oBAAoB;CAC1B,QAAQ;CACR,UAAU,QAAQ;CAClB,2BAAW,IAAI,MAAM;CACrB,YAAY,EAAE,GAAG,SAAS;CAC3B"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"posthog-bridge.js","names":[],"sources":["../../src/lifecycle/posthog-bridge.ts"],"sourcesContent":["import type { LifecycleAssessment } from '@contractspec/lib.lifecycle';\nimport { lifecycleEventNames } from './metric-collectors';\n\nexport interface PostHogLikeClient {\n capture: (event: {\n distinctId: string;\n event: string;\n properties?: Record<string, unknown>;\n }) => Promise<void> | void;\n}\n\nexport const trackLifecycleAssessment = async (\n client: PostHogLikeClient,\n tenantId: string,\n assessment: LifecycleAssessment\n) => {\n await client.capture({\n distinctId: tenantId,\n event: lifecycleEventNames.assessmentRun,\n properties: {\n stage: assessment.stage,\n confidence: assessment.confidence,\n axes: assessment.axes,\n },\n });\n};\n\nexport const trackLifecycleStageChange = async (\n client: PostHogLikeClient,\n tenantId: string,\n previousStage: number | undefined,\n nextStage: number\n) => {\n await client.capture({\n distinctId: tenantId,\n event: lifecycleEventNames.stageChanged,\n properties: {\n previousStage,\n nextStage,\n },\n });\n};\n"],"mappings":";;;AAWA,MAAa,2BAA2B,OACtC,QACA,UACA,eACG;AACH,OAAM,OAAO,QAAQ;EACnB,YAAY;EACZ,OAAO,oBAAoB;EAC3B,YAAY;GACV,OAAO,WAAW;GAClB,YAAY,WAAW;GACvB,MAAM,WAAW;GAClB;EACF,CAAC;;AAGJ,MAAa,4BAA4B,OACvC,QACA,UACA,eACA,cACG;AACH,OAAM,OAAO,QAAQ;EACnB,YAAY;EACZ,OAAO,oBAAoB;EAC3B,YAAY;GACV;GACA;GACD;EACF,CAAC"}