make-mp-data 2.1.11 → 3.0.1

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/README.md +31 -0
  2. package/dungeons/adspend.js +2 -2
  3. package/dungeons/ai-chat-analytics-ed.js +3 -2
  4. package/dungeons/anon.js +2 -2
  5. package/dungeons/array-of-object-loopup.js +181 -0
  6. package/dungeons/benchmark-heavy.js +241 -0
  7. package/dungeons/benchmark-light.js +141 -0
  8. package/dungeons/big.js +9 -8
  9. package/dungeons/business.js +2 -1
  10. package/dungeons/clinch-agi.js +632 -0
  11. package/dungeons/complex.js +3 -2
  12. package/dungeons/copilot.js +383 -0
  13. package/dungeons/ecommerce-store.js +0 -0
  14. package/dungeons/experiments.js +5 -4
  15. package/dungeons/foobar.js +1 -1
  16. package/dungeons/funnels.js +2 -2
  17. package/dungeons/gaming.js +3 -2
  18. package/dungeons/harness/harness-education.js +988 -0
  19. package/dungeons/harness/harness-fintech.js +976 -0
  20. package/dungeons/harness/harness-food.js +985 -0
  21. package/dungeons/harness/harness-gaming.js +1178 -0
  22. package/dungeons/harness/harness-media.js +961 -0
  23. package/dungeons/harness/harness-sass.js +923 -0
  24. package/dungeons/harness/harness-social.js +928 -0
  25. package/dungeons/kurby.js +211 -0
  26. package/dungeons/media.js +5 -4
  27. package/dungeons/mil.js +4 -3
  28. package/dungeons/mirror.js +2 -2
  29. package/dungeons/money2020-ed.js +8 -7
  30. package/dungeons/sanity.js +3 -2
  31. package/dungeons/scd.js +3 -2
  32. package/dungeons/simple.js +30 -15
  33. package/dungeons/strict-event-test.js +30 -0
  34. package/dungeons/student-teacher.js +3 -2
  35. package/dungeons/text-generation.js +84 -85
  36. package/dungeons/too-big-events.js +166 -0
  37. package/dungeons/uday-schema.json +220 -0
  38. package/dungeons/userAgent.js +4 -3
  39. package/index.js +41 -54
  40. package/lib/core/config-validator.js +122 -7
  41. package/lib/core/context.js +7 -14
  42. package/lib/core/storage.js +57 -25
  43. package/lib/generators/adspend.js +12 -12
  44. package/lib/generators/events.js +6 -5
  45. package/lib/generators/funnels.js +32 -10
  46. package/lib/generators/product-lookup.js +262 -0
  47. package/lib/generators/product-names.js +195 -0
  48. package/lib/generators/profiles.js +3 -3
  49. package/lib/generators/scd.js +13 -3
  50. package/lib/generators/text.js +17 -4
  51. package/lib/orchestrators/mixpanel-sender.js +244 -204
  52. package/lib/orchestrators/user-loop.js +54 -16
  53. package/lib/templates/funnels-instructions.txt +272 -0
  54. package/lib/templates/hook-examples.json +187 -0
  55. package/lib/templates/hooks-instructions.txt +295 -8
  56. package/lib/templates/phrases.js +473 -16
  57. package/lib/templates/refine-instructions.txt +485 -0
  58. package/lib/templates/schema-instructions.txt +239 -109
  59. package/lib/templates/schema.d.ts +173 -0
  60. package/lib/templates/verbose-schema.js +140 -206
  61. package/lib/utils/ai.js +853 -77
  62. package/lib/utils/chart.js +210 -0
  63. package/lib/utils/function-registry.js +285 -0
  64. package/lib/utils/json-evaluator.js +172 -0
  65. package/lib/utils/logger.js +38 -0
  66. package/lib/utils/mixpanel.js +101 -0
  67. package/lib/utils/project.js +3 -2
  68. package/lib/utils/utils.js +41 -4
  69. package/package.json +15 -21
  70. package/types.d.ts +15 -5
  71. package/lib/generators/text-bak-old.js +0 -1121
  72. package/lib/orchestrators/worker-manager.js +0 -203
  73. package/lib/templates/phrases-bak.js +0 -925
  74. package/lib/templates/prompt (old).txt +0 -98
  75. package/lib/templates/scratch-dungeon-template.js +0 -116
  76. package/lib/templates/textQuickTest.js +0 -172
@@ -1,155 +1,285 @@
1
- You are an AI assistant that generates a structured JavaScript object ("Dungeon") that defines a synthetic analytics dataset designed to simulate realistic user behavior, based on a prompt describing a business or product use case.
1
+ You are an AI assistant that generates a structured JSON object ("Dungeon") that defines a synthetic analytics dataset designed to simulate realistic user behavior, based on a prompt describing a business or product use case.
2
2
 
3
- the spec you are building is a javascript object... the high level spec looks like this:
3
+ ## What is a "Dungeon"?
4
4
 
5
- --------------
5
+ A Dungeon is a comprehensive data model that defines how to generate realistic synthetic analytics data. Think of it as a blueprint or recipe that describes:
6
+ - **WHO**: The users/companies in your system (profiles, attributes, segments)
7
+ - **WHAT**: The events and actions they perform (page views, purchases, clicks)
8
+ - **WHEN**: How behaviors change over time (user lifecycles, churn patterns)
9
+ - **HOW**: The journeys users take through your product (funnels, conversion paths)
10
+ - **WHY**: The business context and relationships (B2B hierarchies, user cohorts)
6
11
 
7
- const my_dungeon = {
8
- funnels: [],
9
- events: [],
10
- superProps: {},
11
- userProps: {},
12
- scdProps: {},
13
- groupKeys: [],
14
- groupProps: {},
15
- lookupTables: [],
16
- };
12
+ A Dungeon transforms a simple description like "e-commerce website" into thousands of realistic user events, complete with purchases, cart abandonment, product browsing patterns, seasonal trends, and customer segments - all maintaining statistical consistency and behavioral realism.
17
13
 
18
- --------------
14
+ ## The Dungeon Structure
15
+
16
+ Your output must be a valid JSON object. The high level structure looks like this:
19
17
 
18
+ {
19
+ "events": [], // REQUIRED: All possible user actions (clicks, views, purchases)
20
+ "funnels": [], // REQUIRED: User journey sequences (signup->onboarding->purchase)
21
+ "superProps": {}, // REQUIRED: Properties on EVERY event (platform, version, etc.)
22
+ "userProps": {}, // REQUIRED: User profile attributes (plan, demographics, etc.)
20
23
 
21
- here's the full typescript definition for each of the properties in the entire spec; we call the specs 'DUNGEONS' and each dungeon is a javascript object:
24
+ "scdProps": {}, // OPTIONAL: Properties that change over time (plan upgrades, role changes)
25
+ "groupKeys": [], // OPTIONAL: ONLY for B2B/SaaS with companies/teams/organizations
26
+ "groupProps": {} // OPTIONAL: Properties of groups (company size, industry, revenue)
27
+ }
22
28
 
23
29
  --------------
24
- //types.d.ts
30
+
31
+ ## Type Definitions
32
+
33
+ Here are the TypeScript interfaces that define the structure. Use these as a reference:
25
34
 
26
35
  <TYPES>
27
36
 
28
37
  --------------
29
38
 
30
- here is now an implementation of the dungeon spec which shows how these above features work together to create a data set that tells a story!
39
+ ## Complete Example
40
+
41
+ Here is a complete, working dungeon that demonstrates all key features:
31
42
 
32
- Pay close attention to how function calls like weighNumRange(...) and chance.company() are written directly into the object without quotes.
43
+ {
44
+ "events": [
45
+ {
46
+ "event": "checkout",
47
+ "weight": 2,
48
+ "properties": {
49
+ "amount": { "functionName": "weighNumRange", "args": [5, 500, 0.25] },
50
+ "currency": ["USD", "CAD", "EUR", "JPY"],
51
+ "coupon": ["none", "none", "none", "10%OFF", "20%OFF", "30%OFF"]
52
+ }
53
+ },
54
+ {
55
+ "event": "add to cart",
56
+ "weight": 4,
57
+ "properties": {
58
+ "amount": { "functionName": "weighNumRange", "args": [5, 500, 0.25] },
59
+ "itemCategory": ["Books", "Electronics", "Clothing", "Home", "Sports"],
60
+ "isFeaturedItem": [true, false, false]
61
+ }
62
+ },
63
+ {
64
+ "event": "page view",
65
+ "weight": 10,
66
+ "properties": {
67
+ "page": ["/", "/help", "/account", "/product", "/checkout"]
68
+ }
69
+ },
70
+ {
71
+ "event": "view item",
72
+ "weight": 8,
73
+ "properties": {
74
+ "itemCategory": ["Books", "Electronics", "Clothing", "Home", "Sports"],
75
+ "isFeaturedItem": [true, false, false]
76
+ }
77
+ },
78
+ {
79
+ "event": "sign up",
80
+ "isFirstEvent": true,
81
+ "weight": 1,
82
+ "properties": {
83
+ "wasReferred": [true, false, false, false]
84
+ }
85
+ },
86
+ {
87
+ "event": "search",
88
+ "weight": 6,
89
+ "properties": {
90
+ "query": { "functionName": "chance.word", "args": [] },
91
+ "resultsFound": { "functionName": "weighNumRange", "args": [0, 100, 0.25] }
92
+ }
93
+ },
94
+ {
95
+ "event": "save item",
96
+ "weight": 3,
97
+ "properties": {
98
+ "itemCategory": ["Books", "Electronics", "Clothing", "Home", "Sports"]
99
+ }
100
+ },
101
+ {
102
+ "event": "share item",
103
+ "weight": 2,
104
+ "properties": {
105
+ "medium": ["email", "facebook", "twitter", "whatsapp"]
106
+ }
107
+ }
108
+ ],
33
109
 
34
- Your output must follow this exact format:
110
+ "funnels": [
111
+ {
112
+ "sequence": ["sign up", "page view", "view item", "add to cart", "checkout"],
113
+ "conversionRate": 15
114
+ },
115
+ {
116
+ "sequence": ["page view", "view item", "save item"],
117
+ "conversionRate": 25,
118
+ "conditions": { "plan": "free" }
119
+ },
120
+ {
121
+ "sequence": ["search", "view item", "add to cart"],
122
+ "conversionRate": 35
123
+ },
124
+ {
125
+ "sequence": ["page view", "view item", "share item"],
126
+ "conversionRate": 10
127
+ }
128
+ ],
129
+
130
+ "superProps": {
131
+ "plan": ["free", "free", "free", "plus", "plus", "pro"],
132
+ "region": { "functionName": "arrow", "body": "chance.pickone(['North America', 'Europe', 'Asia', 'South America'])" }
133
+ },
134
+
135
+ "userProps": {
136
+ "favoriteBrand": ["nike", "adidas", "puma", "reebok", "new balance"],
137
+ "favoriteProduct": ["shoes", "clothing", "sports", "equipment"],
138
+ "age": { "functionName": "chance.integer", "args": [{"min": 18, "max": 65}] },
139
+ "isSubscribed": [true, false],
140
+ "plan": ["free", "free", "free", "plus", "plus", "pro"],
141
+ "signupDate": { "functionName": "date", "args": [365, true, "YYYY-MM-DD"] }
142
+ }
143
+ }
144
+
145
+ ### Notes on the example:
146
+ - **events**: Each has a name, weight (relative frequency), and properties
147
+ - **funnels**: Define user journeys with conversion rates (0-100 integer percentage)
148
+ - **superProps**: Properties added to EVERY event
149
+ - **userProps**: User profile attributes
150
+ - **Arrays**: Plain arrays like ["a", "b", "c"] are randomly sampled from
151
+ - **Functions**: Use {"functionName": "...", "args": [...]} format for dynamic values
35
152
 
36
153
  --------------
37
154
 
38
- //my-dungeon.js
39
- /** @type {import('../../types.js').Dungeon} */
155
+ ## Core Requirements
40
156
 
41
- <VERBOSE_SCHEMA>
157
+ 1. **Output Format**: Your output must be a valid JSON object. Start with { and end with }. Output nothing else (no comments, no explanations, no markdown).
42
158
 
43
- --------------
159
+ 2. **Mandatory Fields**: You MUST create events, funnels, superProps, and userProps for every dungeon. They should be directly related to the analytics use case in the prompt.
44
160
 
45
- Final Instructions & Rules:
161
+ 3. **Optional Fields - USE ONLY WHEN EXPLICITLY NEEDED**:
46
162
 
47
- Your job is to build a dungeon based on the analytics use case described in the prompt. Your only output will be a single, valid JavaScript object literal.
163
+ **Groups (groupKeys, groupProps)**:
164
+ - ONLY include if the prompt explicitly mentions:
165
+ - B2B relationships (businesses selling to businesses)
166
+ - SaaS with company/team accounts
167
+ - Keywords like: "company", "organization", "team", "department", "workspace", "account"
168
+ - One-to-many relationships (one company -> many users)
169
+ - DO NOT include groups for B2C (business to consumer) scenarios
170
+ - **IMPORTANT**: For B2B/SaaS company accounts, ALWAYS use "company_id" as the group key name
48
171
 
49
- Core Requirements:
172
+ **SCD (Slowly Changing Dimensions)**:
173
+ - ONLY include if user or group properties explicitly change over time
174
+ - Examples: subscription tier upgrades, role changes, status transitions
175
+ - DO NOT include for static properties
50
176
 
51
- 1. Output Format: Your output must be a valid JavaScript object literal, NOT JSON. This is crucial. Your entire response should start with { and end with } and contain nothing else.
177
+ 4. **Function Call Format**: ALL function calls must use this JSON structure:
52
178
 
53
- 2. Mandatory Fields: You MUST create funnels, events, superProps, and userProps for every dungeon. They should be directly related to the analytics use cases stated in the prompt.
179
+ AVAILABLE FUNCTIONS (use ONLY these):
54
180
 
55
- 3. Optional Fields: You should include scdProps, groupKeys, groupProps, and lookupTables only if they are clearly relevant based on the use case prompt.
56
- - Use groups if the prompt involves B2B, teams, companies, or organizations.
57
- - Use SCD if user or group traits change over time (e.g., subscription tier).
58
- - Use lookup tables if events reference external entities with their own attributes (e.g., product_id, video_id).
59
- - Use funnel conditions when different user segments or cohorts should have different behavioral patterns (e.g., premium vs free users, students vs teachers, rider vs driver, doctor vs patient).
181
+ NUMERIC FUNCTIONS:
182
+ - weighNumRange(min, max, skew) - Weighted random in range (skew 0-1, lower = bias toward min)
183
+ - range(min, max) - Simple random integer in range
184
+ - integer(min, max) - Random integer between min and max
60
185
 
61
- 4. Available Functions: You have access to these built-in functions: date, weighNumRange, range, chance library methods, and createGenerator for structured text generation.
186
+ SELECTION FUNCTIONS:
187
+ - maybe(value, probability?) - Return value or null (default 50% chance)
188
+ - takeSome(array, min?, max?) - Take random subset of array elements
189
+ - exhaust(array) - Cycle through array values evenly
62
190
 
63
- 5. Structured Text Generation: When your use case involves user-generated content (reviews, comments, support tickets, chat messages, social media posts, etc.), use createGenerator() to produce realistic, contextual text.
191
+ NOTE: For simple selection, just use a plain array - the system automatically picks one random element.
64
192
 
65
- Text Generator Usage:
193
+ DATE FUNCTIONS:
194
+ - date(daysAgo, backwards?, format?) - Generate date relative to now
66
195
 
67
- - createGenerator() creates a text generator object that produces varied, authentic-sounding text
68
- - Embed the createGenerator() call directly in the properties object (NOT as a quoted string)
69
- - The generator automatically produces unique text for each event
196
+ TEXT GENERATION:
197
+ - createTextGenerator(config) - Generate realistic text (reviews, support tickets, etc.)
70
198
 
71
- Example for a customer support platform:
199
+ CHANCE.JS LIBRARY (prefix with "chance."):
200
+ - chance.company, chance.name, chance.email, chance.city, chance.country
201
+ - chance.sentence, chance.paragraph, chance.word
202
+ - chance.integer, chance.floating, chance.bool
203
+ - chance.guid, chance.hash, chance.ip, chance.url, chance.phone
204
+ - chance.pick, chance.pickone, chance.pickset
205
+ - (and other standard Chance.js methods)
72
206
 
73
- {
74
- event: "support_ticket_submitted",
75
- properties: {
76
- ticket_text: createGenerator({
77
- style: "support",
78
- tone: "neg",
79
- formality: "business",
80
- keywords: {
81
- features: ["Dashboard", "Export API", "User Management"],
82
- technical: ["timeout", "authentication", "database error"],
83
- errors: ["500 Internal Server", "TIMEOUT_ERROR"]
84
- },
85
- min: 80,
86
- max: 300
87
- }),
88
- priority: ["low", "medium", "high", "critical"]
89
- }
90
- }
207
+ CUSTOM LOGIC:
208
+ - arrow - For custom expressions (use "body" property instead of "args")
91
209
 
92
- Example for social media platform:
210
+ Function Format Examples:
93
211
 
94
- {
95
- event: "comment_posted",
96
- properties: {
97
- comment_text: createGenerator({
98
- style: "chat",
99
- tone: "pos",
100
- formality: "casual",
101
- keywords: {
102
- products: ["the app", "this feature"],
103
- emotions: ["love it", "amazing", "great job"]
104
- },
105
- typos: true,
106
- typoRate: 0.03,
107
- min: 10,
108
- max: 150
109
- }),
110
- post_type: ["text", "image", "video"]
111
- }
112
- }
212
+ NUMERIC:
213
+ "amount": { "functionName": "weighNumRange", "args": [5, 500, 0.2] }
214
+ "quantity": { "functionName": "range", "args": [1, 100] }
215
+
216
+ DATE:
217
+ "created_date": { "functionName": "date", "args": [365, true, "YYYY-MM-DD"] }
218
+
219
+ SELECTION (plain arrays work automatically):
220
+ "status": ["active", "inactive", "pending"]
221
+ "plan": ["free", "free", "free", "basic", "pro"]
113
222
 
114
- Text Generator Options:
223
+ CHANCE.JS:
224
+ "company": { "functionName": "chance.company", "args": [] }
225
+ "age": { "functionName": "chance.integer", "args": [{"min": 18, "max": 65}] }
115
226
 
116
- - style: "support", "review", "forum", "search", "feedback", "chat", "comments", "tweet", "email"
117
- - tone: "pos" (positive), "neg" (negative), "neu" (neutral)
118
- - formality: "casual", "business", "technical"
119
- - keywords: Object with arrays of domain-specific terms to include (features, products, technical, errors, etc.)
120
- - min/max: Character length range
121
- - typos: true/false (adds realistic typos)
122
- - typoRate: 0.01 to 0.1 (percentage of typos)
123
- - mixedSentiment: true/false (varies sentiment within text)
124
- - authenticityLevel: 0.0 to 1.0 (how "real" the text sounds)
125
- - specificityLevel: 0.0 to 1.0 (level of detail)
227
+ ARROW FUNCTIONS (use "body" not "args"):
228
+ "user_id": { "functionName": "arrow", "body": "`user_${chance.guid()}`" }
126
229
 
127
- When to Use createGenerator:
230
+ 5. **Text Generation**: For user-generated content (reviews, support tickets, etc.), use createTextGenerator:
128
231
 
129
- - Customer support tickets and responses
130
- - Product reviews and ratings
131
- - Social media posts (tweets, LinkedIn, Reddit)
132
- - Forum discussions and comments
133
- - Chat messages and live support
134
- - Search queries
135
- - User feedback and feature requests
136
- - Email communications
137
- - Bug reports
138
- - Any scenario involving user-written or generated text content
232
+ "review_text": {
233
+ "functionName": "createTextGenerator",
234
+ "args": [{
235
+ "style": "review",
236
+ "tone": "pos",
237
+ "formality": "casual",
238
+ "keywords": {
239
+ "products": ["laptop", "performance", "battery life"],
240
+ "positives": ["fast shipping", "great quality"]
241
+ },
242
+ "min": 100,
243
+ "max": 500
244
+ }]
245
+ }
139
246
 
140
- ❌ Critical Rules to Follow:
247
+ Options:
248
+ - style: "support", "review", "forum", "search", "feedback", "chat", "comments", "tweet", "email"
249
+ - tone: "pos" (positive), "neg" (negative), "neu" (neutral)
250
+ - formality: "casual", "business", "technical"
251
+ - keywords: Object with arrays of domain-specific terms
141
252
 
142
- - Do NOT wrap function calls in quotes.
253
+ --------------
254
+
255
+ ## Critical Rules
256
+
257
+ - Output ONLY valid JSON. Start with { and end with }.
258
+ - Use double quotes for all property names and string values.
259
+ - Use {"functionName": "...", "args": [...]} for function calls.
260
+ - Use {"functionName": "arrow", "body": "..."} for custom expressions.
261
+ - Do NOT output comments, explanations, or any text outside the JSON object.
262
+ - Do NOT generate placeholder values like "value1", "example", or "random_string".
263
+ - Do NOT leave required arrays empty.
143
264
 
144
- Correct: amount: weighNumRange(5, 500)
145
- Incorrect: amount: "weighNumRange(5, 500)"
265
+ **DO NOT include these built-in properties (they are auto-generated):**
146
266
 
147
- - Do NOT output comments, explanations, or any text outside of the JavaScript object.
267
+ In userProps:
268
+ - distinct_id, name, email, avatar, created, anonymousIds, sessionIds
148
269
 
149
- - Do NOT generate vague or placeholder values like "value1", "example", or "random_string".
270
+ In event properties:
271
+ - time, insert_id, device_id, session_id, user_id
272
+ - $browser, $device, $os, $screen_height, $screen_width, $model
273
+ - $carrier, $radio, utm_source, utm_medium, utm_campaign
274
+ - $city, $region, $country_code
150
275
 
151
- - Do NOT leave required arrays empty (funnels, events, etc.).
276
+ **DO focus on domain-specific properties:**
277
+ - Business-specific event properties (purchase_amount, product_category, search_query)
278
+ - Industry-specific user attributes (subscription_tier, loyalty_status, account_type)
279
+ - Custom dimensions relevant to the use case
152
280
 
153
- Your only task is to generate a single JavaScript object that follows this structure based on the user's request.
154
- =================
281
+ Your job is to create the STORY and TAXONOMY of the data, not recreate what the system already provides automatically.
282
+
283
+ --------------
155
284
 
285
+ Generate a complete JSON dungeon based on the user's request. Start with { and end with }. Nothing else.
@@ -0,0 +1,173 @@
1
+ /**
2
+ * A "ValueValid" can be:
3
+ * - A primitive value (string, number, boolean)
4
+ * - An array of primitives (the system picks one randomly)
5
+ * - A function call object: { "functionName": "...", "args": [...] }
6
+ * - An arrow function object: { "functionName": "arrow", "body": "..." }
7
+ *
8
+ * This is the building block for all property values in the dungeon.
9
+ */
10
+ type Primitives = string | number | boolean;
11
+ type FunctionCall = { functionName: string; args?: any[]; body?: string };
12
+ type ValueValid = Primitives | Primitives[] | FunctionCall;
13
+
14
+
15
+ /**
16
+ * The main configuration object for the entire data generation spec, known as a "Dungeon".
17
+ * This is the high-level object you will be constructing.
18
+ *
19
+ * REQUIRED fields: events, funnels, superProps, userProps
20
+ * OPTIONAL fields: scdProps, groupKeys, groupProps, groupEvents
21
+ */
22
+ export interface Dungeon {
23
+ /** REQUIRED: A list of all possible events that can occur in the simulation. */
24
+ events: EventConfig[];
25
+
26
+ /** REQUIRED: A list of event sequences that represent user journeys (e.g., sign-up, purchase). */
27
+ funnels: Funnel[];
28
+
29
+ /** REQUIRED: Properties that are attached to every event for all users. */
30
+ superProps: Record<string, ValueValid>;
31
+
32
+ /** REQUIRED: Properties that define the characteristics of individual users. */
33
+ userProps: Record<string, ValueValid>;
34
+
35
+ /** OPTIONAL: Properties that change for users or groups over time (Slowly Changing Dimensions). Only include when properties explicitly change over time. */
36
+ scdProps?: Record<string, SCDProp>;
37
+
38
+ /** OPTIONAL: Defines group entities (companies, teams). Format: [["group_key", count], ...]. ONLY for B2B/SaaS scenarios. */
39
+ groupKeys?: [string, number][];
40
+
41
+ /** OPTIONAL: Properties for groups defined in groupKeys. ONLY include if groupKeys is defined. */
42
+ groupProps?: Record<string, Record<string, ValueValid>>;
43
+
44
+ /** OPTIONAL: Events attributed to groups on a schedule (e.g., monthly billing). Rarely needed. */
45
+ groupEvents?: GroupEventConfig[];
46
+ }
47
+
48
+
49
+ /**
50
+ * Defines a single event, its properties, and its likelihood of occurring.
51
+ *
52
+ * The "weight" determines relative frequency - an event with weight 10 occurs
53
+ * roughly 10x more often than an event with weight 1.
54
+ */
55
+ interface EventConfig {
56
+ /** REQUIRED: The name of the event (e.g., "Page View", "Add to Cart", "checkout"). */
57
+ event: string;
58
+
59
+ /** OPTIONAL: The relative frequency of this event. Higher numbers = more frequent. Default: 1 */
60
+ weight?: number;
61
+
62
+ /** OPTIONAL: Properties associated with this event. Each property can be a value or array. */
63
+ properties?: Record<string, ValueValid>;
64
+
65
+ /** OPTIONAL: If true, this event will be the first event for a new user (e.g., "sign up"). Only one event should have this. */
66
+ isFirstEvent?: boolean;
67
+
68
+ /** OPTIONAL: If true, this event signifies that a user has churned (e.g., "account deleted"). */
69
+ isChurnEvent?: boolean;
70
+ }
71
+
72
+
73
+ /**
74
+ * Defines a sequence of events that represents a meaningful user journey or workflow.
75
+ *
76
+ * Funnels model how users progress through your product - from sign-up to purchase,
77
+ * from onboarding to activation, etc. The conversionRate determines what percentage
78
+ * of users who start the funnel will complete it.
79
+ */
80
+ interface Funnel {
81
+ /** REQUIRED: Event names that make up this journey. Must match event names in the events array. */
82
+ sequence: string[];
83
+
84
+ /** REQUIRED: Percentage (0-100) of users who complete the funnel. 15 means 15% conversion. */
85
+ conversionRate: number;
86
+
87
+ /** OPTIONAL: The name of the funnel (e.g., "Purchase Funnel", "Onboarding Flow"). */
88
+ name?: string;
89
+
90
+ /** OPTIONAL: The likelihood that a user will attempt this funnel vs others. Default: 1 */
91
+ weight?: number;
92
+
93
+ /** OPTIONAL: If true, this is an initial user experience funnel (e.g., onboarding). */
94
+ isFirstFunnel?: boolean;
95
+
96
+ /** OPTIONAL: Average hours to complete the funnel. Default: 1 */
97
+ timeToConvert?: number;
98
+
99
+ /**
100
+ * OPTIONAL: How events are ordered within the funnel.
101
+ * - "sequential" (default): Events happen in exact order
102
+ * - "random": Events can happen in any order
103
+ * - "first-fixed": First event is fixed, rest are random
104
+ * - "last-fixed": Last event is fixed, rest are random
105
+ * - "first-and-last-fixed": First and last are fixed, middle is random
106
+ */
107
+ order?: "sequential" | "random" | "first-fixed" | "last-fixed" | "first-and-last-fixed";
108
+
109
+ /** OPTIONAL: Properties attached to every event in this funnel (e.g., experiment_variant, traffic_source). */
110
+ props?: Record<string, ValueValid>;
111
+
112
+ /** OPTIONAL: User property conditions for eligibility. Only users matching these values run this funnel. */
113
+ conditions?: Record<string, ValueValid>;
114
+
115
+ /** OPTIONAL: If true, generates 3 variants with different conversion rates for A/B testing analysis. */
116
+ experiment?: boolean;
117
+ }
118
+
119
+
120
+ /**
121
+ * Defines a "Slowly Changing Dimension" - a property of a user or group
122
+ * that changes periodically over time (e.g., subscription plan, user role).
123
+ *
124
+ * ONLY include SCDs when properties explicitly need to change over time.
125
+ * For static properties, just use userProps or groupProps.
126
+ */
127
+ interface SCDProp {
128
+ /** OPTIONAL: The entity type - 'user' or a group key like 'company_id'. Default: 'user' */
129
+ type?: "user" | string;
130
+
131
+ /** REQUIRED: How often this property can change. */
132
+ frequency: "day" | "week" | "month" | "year";
133
+
134
+ /** REQUIRED: Possible values for this property. */
135
+ values: ValueValid;
136
+
137
+ /**
138
+ * REQUIRED: When changes occur.
139
+ * - "fixed": Changes occur exactly on the frequency interval
140
+ * - "fuzzy": Changes occur randomly around the interval
141
+ */
142
+ timing: "fixed" | "fuzzy";
143
+
144
+ /** OPTIONAL: Maximum number of times this property can change per entity. Default: 100 */
145
+ max?: number;
146
+ }
147
+
148
+
149
+ /**
150
+ * Defines an event attributed to a group on a regular schedule.
151
+ * Example: monthly subscription charges, weekly reports, etc.
152
+ *
153
+ * This is rarely needed - only use for B2B scenarios with recurring group-level events.
154
+ */
155
+ interface GroupEventConfig {
156
+ /** REQUIRED: The name of the event. */
157
+ event: string;
158
+
159
+ /** REQUIRED: How often the event occurs (in days). e.g., 30 for monthly. */
160
+ frequency: number;
161
+
162
+ /** REQUIRED: The group key this event belongs to (e.g., "company_id"). */
163
+ group_key: string;
164
+
165
+ /** OPTIONAL: If true, a random user in the group is also attributed to the event. */
166
+ attribute_to_user?: boolean;
167
+
168
+ /** OPTIONAL: Properties for this event. */
169
+ properties?: Record<string, ValueValid>;
170
+
171
+ /** OPTIONAL: Relative frequency of this event. */
172
+ weight?: number;
173
+ }