make-mp-data 2.0.0 → 2.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dungeons/adspend.js +96 -0
- package/dungeons/anon.js +104 -0
- package/dungeons/big.js +225 -0
- package/dungeons/business.js +345 -0
- package/dungeons/complex.js +396 -0
- package/dungeons/experiments.js +125 -0
- package/dungeons/foobar.js +241 -0
- package/dungeons/funnels.js +272 -0
- package/dungeons/gaming.js +315 -0
- package/dungeons/media.js +7 -7
- package/dungeons/mirror.js +129 -0
- package/dungeons/sanity.js +113 -0
- package/dungeons/scd.js +205 -0
- package/dungeons/simple.js +195 -0
- package/dungeons/userAgent.js +190 -0
- package/entry.js +57 -0
- package/index.js +96 -68
- package/lib/cli/cli.js +10 -5
- package/lib/core/config-validator.js +28 -12
- package/lib/core/context.js +147 -130
- package/lib/core/storage.js +45 -31
- package/lib/data/defaults.js +2 -2
- package/lib/generators/adspend.js +1 -2
- package/lib/generators/events.js +35 -24
- package/lib/generators/funnels.js +1 -2
- package/lib/generators/mirror.js +1 -2
- package/lib/orchestrators/mixpanel-sender.js +15 -7
- package/lib/orchestrators/user-loop.js +21 -10
- package/lib/orchestrators/worker-manager.js +5 -2
- package/lib/utils/ai.js +36 -63
- package/lib/utils/chart.js +5 -0
- package/lib/utils/instructions.txt +593 -0
- package/lib/utils/utils.js +162 -38
- package/package.json +23 -9
- package/types.d.ts +376 -376
- package/.claude/settings.local.json +0 -20
- package/.gcloudignore +0 -18
- package/.gitattributes +0 -2
- package/.prettierrc +0 -0
- package/.vscode/launch.json +0 -80
- package/.vscode/settings.json +0 -69
- package/.vscode/tasks.json +0 -12
- package/dungeons/customers/.gitkeep +0 -0
- package/env.yaml +0 -1
- package/lib/cloud-function.js +0 -20
- package/scratch.mjs +0 -62
- package/scripts/dana.mjs +0 -137
- package/scripts/deploy.sh +0 -15
- package/scripts/jsdoctest.js +0 -5
- package/scripts/new-dungeon.sh +0 -98
- package/scripts/new-project.mjs +0 -14
- package/scripts/run-index.sh +0 -2
- package/scripts/update-deps.sh +0 -5
- package/tests/benchmark/concurrency.mjs +0 -52
- package/tests/cli.test.js +0 -124
- package/tests/coverage/.gitkeep +0 -0
- package/tests/e2e.test.js +0 -379
- package/tests/int.test.js +0 -715
- package/tests/testCases.mjs +0 -229
- package/tests/testSoup.mjs +0 -28
- package/tests/unit.test.js +0 -910
- package/tmp/.gitkeep +0 -0
- package/tsconfig.json +0 -18
- package/vitest.config.js +0 -47
package/types.d.ts
CHANGED
|
@@ -1,412 +1,412 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
type Primitives = string | number | boolean | Date | Record<string, any>;
|
|
1
|
+
/**
|
|
2
|
+
* most of the time, the value of a property is a primitive
|
|
3
|
+
*/
|
|
4
|
+
type Primitives = string | number | boolean | Date | Record<string, any>;
|
|
6
5
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
6
|
+
/**
|
|
7
|
+
* a "validValue" can be a primitive, an array of primitives, or a function that returns a primitive
|
|
8
|
+
*/
|
|
9
|
+
export type ValueValid = Primitives | ValueValid[] | (() => ValueValid);
|
|
11
10
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
export type SCDProp = {
|
|
77
|
-
type?: string | "user" | "company_id" | "team_id" | "department_id";
|
|
78
|
-
frequency: "day" | "week" | "month" | "year";
|
|
79
|
-
values: ValueValid;
|
|
80
|
-
timing: "fixed" | "fuzzy";
|
|
81
|
-
max?: number;
|
|
82
|
-
};
|
|
11
|
+
/**
|
|
12
|
+
* main config object for the entire data generation
|
|
13
|
+
*/
|
|
14
|
+
export interface Dungeon {
|
|
15
|
+
// constants
|
|
16
|
+
token?: string;
|
|
17
|
+
seed?: string;
|
|
18
|
+
numDays?: number;
|
|
19
|
+
epochStart?: number;
|
|
20
|
+
epochEnd?: number;
|
|
21
|
+
numEvents?: number;
|
|
22
|
+
numUsers?: number;
|
|
23
|
+
format?: "csv" | "json" | string;
|
|
24
|
+
region?: "US" | "EU";
|
|
25
|
+
concurrency?: number;
|
|
26
|
+
batchSize?: number;
|
|
27
|
+
|
|
28
|
+
serviceAccount?: string;
|
|
29
|
+
serviceSecret?: string;
|
|
30
|
+
projectId?: string;
|
|
31
|
+
|
|
32
|
+
// ids
|
|
33
|
+
simulationName?: string;
|
|
34
|
+
name?: string;
|
|
35
|
+
|
|
36
|
+
//switches
|
|
37
|
+
isAnonymous?: boolean;
|
|
38
|
+
hasAvatar?: boolean;
|
|
39
|
+
hasLocation?: boolean;
|
|
40
|
+
hasCampaigns?: boolean;
|
|
41
|
+
hasAdSpend?: boolean;
|
|
42
|
+
hasIOSDevices?: boolean;
|
|
43
|
+
hasAndroidDevices?: boolean;
|
|
44
|
+
hasDesktopDevices?: boolean;
|
|
45
|
+
hasBrowser?: boolean;
|
|
46
|
+
writeToDisk?: boolean | string;
|
|
47
|
+
verbose?: boolean;
|
|
48
|
+
hasAnonIds?: boolean;
|
|
49
|
+
hasSessionIds?: boolean;
|
|
50
|
+
alsoInferFunnels?: boolean;
|
|
51
|
+
makeChart?: boolean | string;
|
|
52
|
+
singleCountry?: string;
|
|
53
|
+
|
|
54
|
+
//models
|
|
55
|
+
events?: EventConfig[]; //| string[]; //can also be a array of strings
|
|
56
|
+
superProps?: Record<string, ValueValid>;
|
|
57
|
+
funnels?: Funnel[];
|
|
58
|
+
userProps?: Record<string, ValueValid>;
|
|
59
|
+
scdProps?: Record<string, SCDProp>;
|
|
60
|
+
mirrorProps?: Record<string, MirrorProps>;
|
|
61
|
+
groupKeys?: [string, number][] | [string, number, string[]][]; // [key, numGroups, [events]]
|
|
62
|
+
groupProps?: Record<string, Record<string, ValueValid>>;
|
|
63
|
+
groupEvents?: GroupEventConfig[];
|
|
64
|
+
lookupTables?: LookupTableSchema[];
|
|
65
|
+
soup?: soup;
|
|
66
|
+
hook?: Hook<any>;
|
|
67
|
+
|
|
68
|
+
//allow anything to be on the config
|
|
69
|
+
[key: string]: any;
|
|
70
|
+
|
|
71
|
+
//probabilities
|
|
72
|
+
percentUsersBornInDataset?: number;
|
|
73
|
+
}
|
|
83
74
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
};
|
|
75
|
+
export type SCDProp = {
|
|
76
|
+
type?: string | "user" | "company_id" | "team_id" | "department_id";
|
|
77
|
+
frequency: "day" | "week" | "month" | "year";
|
|
78
|
+
values: ValueValid;
|
|
79
|
+
timing: "fixed" | "fuzzy";
|
|
80
|
+
max?: number;
|
|
81
|
+
};
|
|
92
82
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
| "scd"
|
|
102
|
-
| "scd-pre"
|
|
103
|
-
| "mirror"
|
|
104
|
-
| "funnel-pre"
|
|
105
|
-
| "funnel-post"
|
|
106
|
-
| "ad-spend"
|
|
107
|
-
| "churn"
|
|
108
|
-
| "group-event"
|
|
109
|
-
| "everything"
|
|
110
|
-
| "";
|
|
83
|
+
/**
|
|
84
|
+
* the soup is a set of parameters that determine the distribution of events over time
|
|
85
|
+
*/
|
|
86
|
+
type soup = {
|
|
87
|
+
deviation?: number;
|
|
88
|
+
peaks?: number;
|
|
89
|
+
mean?: number;
|
|
90
|
+
};
|
|
111
91
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
92
|
+
/**
|
|
93
|
+
* the types of hooks that can be used
|
|
94
|
+
*/
|
|
95
|
+
export type hookTypes =
|
|
96
|
+
| "event"
|
|
97
|
+
| "user"
|
|
98
|
+
| "group"
|
|
99
|
+
| "lookup"
|
|
100
|
+
| "scd"
|
|
101
|
+
| "scd-pre"
|
|
102
|
+
| "mirror"
|
|
103
|
+
| "funnel-pre"
|
|
104
|
+
| "funnel-post"
|
|
105
|
+
| "ad-spend"
|
|
106
|
+
| "churn"
|
|
107
|
+
| "group-event"
|
|
108
|
+
| "everything"
|
|
109
|
+
| "";
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* a hook is a function that can be called before each entity is created, and can be used to modify attributes
|
|
113
|
+
*/
|
|
114
|
+
export type Hook<T> = (record: any, type: hookTypes, meta: any) => T;
|
|
115
|
+
|
|
116
|
+
export interface hookArrayOptions<T> {
|
|
117
|
+
hook?: Hook<T>;
|
|
118
|
+
type?: hookTypes;
|
|
119
|
+
filename?: string;
|
|
120
|
+
format?: "csv" | "json" | string;
|
|
121
|
+
concurrency?: number;
|
|
122
|
+
context?: Context;
|
|
123
|
+
[key: string]: any;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* an enriched array is an array that has a hookPush method that can be used to transform-then-push items into the array
|
|
128
|
+
*/
|
|
129
|
+
export interface HookedArray<T> extends Array<T> {
|
|
130
|
+
hookPush: (item: T | T[], ...meta: any[]) => any;
|
|
131
|
+
flush: () => void;
|
|
132
|
+
getWriteDir: () => string;
|
|
133
|
+
getWritePath: () => string;
|
|
134
|
+
[key: string]: any;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
export type AllData =
|
|
138
|
+
| HookedArray<EventSchema>
|
|
139
|
+
| HookedArray<UserProfile>
|
|
140
|
+
| HookedArray<GroupProfileSchema>
|
|
141
|
+
| HookedArray<LookupTableSchema>
|
|
142
|
+
| HookedArray<SCDSchema>
|
|
143
|
+
| any[];
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* the storage object is a key-value store that holds arrays of data
|
|
147
|
+
*/
|
|
148
|
+
export interface Storage {
|
|
149
|
+
eventData?: HookedArray<EventSchema>;
|
|
150
|
+
mirrorEventData?: HookedArray<EventSchema>;
|
|
151
|
+
userProfilesData?: HookedArray<UserProfile>;
|
|
152
|
+
adSpendData?: HookedArray<EventSchema>;
|
|
153
|
+
groupProfilesData?: HookedArray<GroupProfileSchema>[];
|
|
154
|
+
lookupTableData?: HookedArray<LookupTableSchema>[];
|
|
155
|
+
scdTableData?: HookedArray<SCDSchema>[];
|
|
156
|
+
groupEventData?: HookedArray<EventSchema>;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Runtime state for tracking execution metrics and flags
|
|
161
|
+
*/
|
|
162
|
+
export interface RuntimeState {
|
|
163
|
+
operations: number;
|
|
164
|
+
eventCount: number;
|
|
165
|
+
userCount: number;
|
|
166
|
+
isBatchMode: boolean;
|
|
167
|
+
verbose: boolean;
|
|
168
|
+
isCLI: boolean;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Default data factories for generating realistic test data
|
|
173
|
+
*/
|
|
174
|
+
export interface Defaults {
|
|
175
|
+
locationsUsers: () => any[];
|
|
176
|
+
locationsEvents: () => any[];
|
|
177
|
+
iOSDevices: () => any[];
|
|
178
|
+
androidDevices: () => any[];
|
|
179
|
+
desktopDevices: () => any[];
|
|
180
|
+
browsers: () => any[];
|
|
181
|
+
campaigns: () => any[];
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Context object that replaces global variables with dependency injection
|
|
186
|
+
* Contains validated config, storage containers, defaults, and runtime state
|
|
187
|
+
*/
|
|
188
|
+
export interface Context {
|
|
189
|
+
config: Dungeon;
|
|
190
|
+
storage: Storage | null;
|
|
191
|
+
defaults: Defaults;
|
|
192
|
+
campaigns: any[];
|
|
193
|
+
runtime: RuntimeState;
|
|
194
|
+
FIXED_NOW: number;
|
|
195
|
+
FIXED_BEGIN?: number;
|
|
196
|
+
TIME_SHIFT_SECONDS: number;
|
|
197
|
+
|
|
198
|
+
// State update methods
|
|
199
|
+
incrementOperations(): void;
|
|
200
|
+
incrementEvents(): void;
|
|
201
|
+
incrementUsers(): void;
|
|
202
|
+
setStorage(storage: Storage): void;
|
|
203
|
+
|
|
204
|
+
// State getter methods
|
|
205
|
+
getOperations(): number;
|
|
206
|
+
getEventCount(): number;
|
|
207
|
+
getUserCount(): number;
|
|
208
|
+
incrementUserCount(): void;
|
|
209
|
+
incrementEventCount(): void;
|
|
210
|
+
isBatchMode(): boolean;
|
|
211
|
+
isCLI(): boolean;
|
|
212
|
+
|
|
213
|
+
// Time helper methods
|
|
214
|
+
getTimeShift(): number;
|
|
215
|
+
getDaysShift(): number;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* how we define events and their properties
|
|
220
|
+
*/
|
|
221
|
+
export interface EventConfig {
|
|
222
|
+
event?: string;
|
|
223
|
+
weight?: number;
|
|
224
|
+
properties?: Record<string, ValueValid>;
|
|
225
|
+
isFirstEvent?: boolean;
|
|
226
|
+
isChurnEvent?: boolean;
|
|
227
|
+
isSessionStartEvent?: boolean;
|
|
228
|
+
relativeTimeMs?: number;
|
|
229
|
+
}
|
|
116
230
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
231
|
+
export interface GroupEventConfig extends EventConfig {
|
|
232
|
+
frequency: number; //how often the event occurs (in days)
|
|
233
|
+
group_key: string; //the key that the group is based on
|
|
234
|
+
attribute_to_user: boolean; //if true, the event also goes to a user
|
|
235
|
+
group_size: number; //the number of users in the group
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* the generated event data
|
|
240
|
+
*/
|
|
241
|
+
export interface EventSchema {
|
|
242
|
+
event: string;
|
|
243
|
+
time: string;
|
|
244
|
+
source: string;
|
|
245
|
+
insert_id: string;
|
|
246
|
+
device_id?: string;
|
|
247
|
+
session_id?: string;
|
|
248
|
+
user_id?: string;
|
|
249
|
+
[key: string]: ValueValid;
|
|
250
|
+
}
|
|
125
251
|
|
|
252
|
+
/**
|
|
253
|
+
* how we define funnels and their properties
|
|
254
|
+
*/
|
|
255
|
+
export interface Funnel {
|
|
126
256
|
/**
|
|
127
|
-
*
|
|
257
|
+
* the sequence of events that define the funnel
|
|
128
258
|
*/
|
|
129
|
-
|
|
130
|
-
hookPush: (item: T | T[], ...meta) => any;
|
|
131
|
-
flush: () => void;
|
|
132
|
-
getWriteDir: () => string;
|
|
133
|
-
getWritePath: () => string;
|
|
134
|
-
[key: string]: any;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
export type AllData =
|
|
138
|
-
| HookedArray<EventSchema>
|
|
139
|
-
| HookedArray<UserProfile>
|
|
140
|
-
| HookedArray<GroupProfileSchema>
|
|
141
|
-
| HookedArray<LookupTableSchema>
|
|
142
|
-
| HookedArray<SCDSchema>
|
|
143
|
-
| any[];
|
|
144
|
-
|
|
259
|
+
sequence: string[];
|
|
145
260
|
/**
|
|
146
|
-
* the
|
|
261
|
+
* how likely the funnel is to be selected
|
|
147
262
|
*/
|
|
148
|
-
|
|
149
|
-
eventData?: HookedArray<EventSchema>;
|
|
150
|
-
mirrorEventData?: HookedArray<EventSchema>;
|
|
151
|
-
userProfilesData?: HookedArray<UserProfile>;
|
|
152
|
-
adSpendData?: HookedArray<EventSchema>;
|
|
153
|
-
groupProfilesData?: HookedArray<GroupProfileSchema>[];
|
|
154
|
-
lookupTableData?: HookedArray<LookupTableSchema>[];
|
|
155
|
-
scdTableData?: HookedArray<SCDSchema>[];
|
|
156
|
-
groupEventData?: HookedArray<EventSchema>;
|
|
157
|
-
}
|
|
158
|
-
|
|
263
|
+
weight?: number;
|
|
159
264
|
/**
|
|
160
|
-
*
|
|
265
|
+
* If true, the funnel will be the first thing the user does
|
|
161
266
|
*/
|
|
162
|
-
|
|
163
|
-
operations: number;
|
|
164
|
-
eventCount: number;
|
|
165
|
-
userCount: number;
|
|
166
|
-
isBatchMode: boolean;
|
|
167
|
-
verbose: boolean;
|
|
168
|
-
isCLI: boolean;
|
|
169
|
-
}
|
|
170
|
-
|
|
267
|
+
isFirstFunnel?: boolean;
|
|
171
268
|
/**
|
|
172
|
-
*
|
|
269
|
+
* If true, the funnel will require the user to repeat the sequence of events in order to convert
|
|
270
|
+
* If false, the user does not need to repeat the sequence of events in order to convert
|
|
271
|
+
* ^ when false, users who repeat the repetitive steps are more likely to convert
|
|
173
272
|
*/
|
|
174
|
-
|
|
175
|
-
locationsUsers: () => any[];
|
|
176
|
-
locationsEvents: () => any[];
|
|
177
|
-
iOSDevices: () => any[];
|
|
178
|
-
androidDevices: () => any[];
|
|
179
|
-
desktopDevices: () => any[];
|
|
180
|
-
browsers: () => any[];
|
|
181
|
-
campaigns: () => any[];
|
|
182
|
-
}
|
|
183
|
-
|
|
273
|
+
requireRepeats?: boolean;
|
|
184
274
|
/**
|
|
185
|
-
*
|
|
186
|
-
* Contains validated config, storage containers, defaults, and runtime state
|
|
275
|
+
* how the events in the funnel are ordered for each user
|
|
187
276
|
*/
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
// State update methods
|
|
198
|
-
incrementOperations(): void;
|
|
199
|
-
incrementEvents(): void;
|
|
200
|
-
incrementUsers(): void;
|
|
201
|
-
setStorage(storage: Storage): void;
|
|
202
|
-
|
|
203
|
-
// State getter methods
|
|
204
|
-
getOperations(): number;
|
|
205
|
-
getEventCount(): number;
|
|
206
|
-
getUserCount(): number;
|
|
207
|
-
incrementUserCount(): void;
|
|
208
|
-
incrementEventCount(): void;
|
|
209
|
-
isBatchMode(): boolean;
|
|
210
|
-
isCLI(): boolean;
|
|
211
|
-
|
|
212
|
-
// Time helper methods
|
|
213
|
-
getTimeShift(): number;
|
|
214
|
-
getDaysShift(): number;
|
|
215
|
-
}
|
|
277
|
+
order?:
|
|
278
|
+
| string
|
|
279
|
+
| "sequential"
|
|
280
|
+
| "first-fixed"
|
|
281
|
+
| "last-fixed"
|
|
282
|
+
| "random" //totally shuffled
|
|
283
|
+
| "first-and-last-fixed"
|
|
284
|
+
| "middle-fixed"
|
|
285
|
+
| "interrupted";
|
|
216
286
|
|
|
217
287
|
/**
|
|
218
|
-
*
|
|
288
|
+
* todo: implement this
|
|
289
|
+
* if set, the funnel might be the last thing the user does
|
|
290
|
+
* ^ the numerical value is the likelihood that the user will churn
|
|
291
|
+
* todo: allow for users to be resurrected
|
|
219
292
|
*/
|
|
220
|
-
|
|
221
|
-
event?: string;
|
|
222
|
-
weight?: number;
|
|
223
|
-
properties?: Record<string, ValueValid>;
|
|
224
|
-
isFirstEvent?: boolean;
|
|
225
|
-
isChurnEvent?: boolean;
|
|
226
|
-
isSessionStartEvent?: boolean;
|
|
227
|
-
relativeTimeMs?: number;
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
export interface GroupEventConfig extends EventConfig {
|
|
231
|
-
frequency: number; //how often the event occurs (in days)
|
|
232
|
-
group_key: string; //the key that the group is based on
|
|
233
|
-
attribute_to_user: boolean; //if true, the event also goes to a user
|
|
234
|
-
group_size: number; //the number of users in the group
|
|
235
|
-
}
|
|
236
|
-
|
|
293
|
+
isChurnFunnel?: void | number;
|
|
237
294
|
/**
|
|
238
|
-
* the
|
|
295
|
+
* the likelihood that a user will convert (0-100%)
|
|
239
296
|
*/
|
|
240
|
-
|
|
241
|
-
event: string;
|
|
242
|
-
time: string;
|
|
243
|
-
source: string;
|
|
244
|
-
insert_id: string;
|
|
245
|
-
device_id?: string;
|
|
246
|
-
session_id?: string;
|
|
247
|
-
user_id?: string;
|
|
248
|
-
[key: string]: ValueValid;
|
|
249
|
-
}
|
|
250
|
-
|
|
297
|
+
conversionRate?: number;
|
|
251
298
|
/**
|
|
252
|
-
*
|
|
299
|
+
* the time it takes (on average) to convert in hours
|
|
253
300
|
*/
|
|
254
|
-
|
|
255
|
-
/**
|
|
256
|
-
* the sequence of events that define the funnel
|
|
257
|
-
*/
|
|
258
|
-
sequence: string[];
|
|
259
|
-
/**
|
|
260
|
-
* how likely the funnel is to be selected
|
|
261
|
-
*/
|
|
262
|
-
weight?: number;
|
|
263
|
-
/**
|
|
264
|
-
* If true, the funnel will be the first thing the user does
|
|
265
|
-
*/
|
|
266
|
-
isFirstFunnel?: boolean;
|
|
267
|
-
/**
|
|
268
|
-
* If true, the funnel will require the user to repeat the sequence of events in order to convert
|
|
269
|
-
* If false, the user does not need to repeat the sequence of events in order to convert
|
|
270
|
-
* ^ when false, users who repeat the repetitive steps are more likely to convert
|
|
271
|
-
*/
|
|
272
|
-
requireRepeats?: boolean;
|
|
273
|
-
/**
|
|
274
|
-
* how the events in the funnel are ordered for each user
|
|
275
|
-
*/
|
|
276
|
-
order?:
|
|
277
|
-
| string
|
|
278
|
-
| "sequential"
|
|
279
|
-
| "first-fixed"
|
|
280
|
-
| "last-fixed"
|
|
281
|
-
| "random" //totally shuffled
|
|
282
|
-
| "first-and-last-fixed"
|
|
283
|
-
| "middle-fixed"
|
|
284
|
-
| "interrupted";
|
|
285
|
-
|
|
286
|
-
/**
|
|
287
|
-
* todo: implement this
|
|
288
|
-
* if set, the funnel might be the last thing the user does
|
|
289
|
-
* ^ the numerical value is the likelihood that the user will churn
|
|
290
|
-
* todo: allow for users to be resurrected
|
|
291
|
-
*/
|
|
292
|
-
isChurnFunnel?: void | number;
|
|
293
|
-
/**
|
|
294
|
-
* the likelihood that a user will convert (0-100%)
|
|
295
|
-
*/
|
|
296
|
-
conversionRate?: number;
|
|
297
|
-
/**
|
|
298
|
-
* the time it takes (on average) to convert in hours
|
|
299
|
-
*/
|
|
300
|
-
timeToConvert?: number;
|
|
301
|
-
/**
|
|
302
|
-
* funnel properties go onto each event in the funnel and are held constant
|
|
303
|
-
*/
|
|
304
|
-
props?: Record<string, ValueValid>;
|
|
305
|
-
}
|
|
306
|
-
|
|
301
|
+
timeToConvert?: number;
|
|
307
302
|
/**
|
|
308
|
-
*
|
|
309
|
-
* there are different strategies for how to mutate the data
|
|
303
|
+
* funnel properties go onto each event in the funnel and are held constant
|
|
310
304
|
*/
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
* the event that will be mutated in the new version
|
|
314
|
-
*/
|
|
315
|
-
events?: string[] | "*";
|
|
316
|
-
/**
|
|
317
|
-
* "create" - create this key in the new version; value are chosen
|
|
318
|
-
* "update" - update this key in the new version; values are chosen
|
|
319
|
-
* "fill" - update this key in the new version, but only if the existing key is null or unset
|
|
320
|
-
* "delete" - delete this key in the new version; values are ignored
|
|
321
|
-
*/
|
|
322
|
-
strategy?: "create" | "update" | "fill" | "delete" | "";
|
|
323
|
-
values?: ValueValid[];
|
|
324
|
-
/**
|
|
325
|
-
* optional: for 'fill' mode, daysUnfilled will dictate where the cutoff is in the unfilled data
|
|
326
|
-
*/
|
|
327
|
-
daysUnfilled?: number;
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
export interface UserProfile {
|
|
331
|
-
name?: string;
|
|
332
|
-
email?: string;
|
|
333
|
-
avatar?: string;
|
|
334
|
-
created: string | undefined;
|
|
335
|
-
distinct_id: string;
|
|
336
|
-
[key: string]: ValueValid;
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
export interface Person {
|
|
340
|
-
name: string;
|
|
341
|
-
email?: string;
|
|
342
|
-
avatar?: string;
|
|
343
|
-
created: string | undefined;
|
|
344
|
-
anonymousIds: string[];
|
|
345
|
-
sessionIds: string[];
|
|
346
|
-
distinct_id?: string;
|
|
347
|
-
}
|
|
305
|
+
props?: Record<string, ValueValid>;
|
|
306
|
+
}
|
|
348
307
|
|
|
308
|
+
/**
|
|
309
|
+
* mirror props are used to show mutations of event data over time
|
|
310
|
+
* there are different strategies for how to mutate the data
|
|
311
|
+
*/
|
|
312
|
+
export interface MirrorProps {
|
|
349
313
|
/**
|
|
350
|
-
* the
|
|
314
|
+
* the event that will be mutated in the new version
|
|
351
315
|
*/
|
|
352
|
-
|
|
353
|
-
key: string;
|
|
354
|
-
entries: number;
|
|
355
|
-
attributes: Record<string, ValueValid>;
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
export interface LookupTableData {
|
|
359
|
-
key: string;
|
|
360
|
-
data: any[];
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
export interface SCDSchema {
|
|
364
|
-
distinct_id: string;
|
|
365
|
-
insertTime: string;
|
|
366
|
-
startTime: string;
|
|
367
|
-
[key: string]: ValueValid;
|
|
368
|
-
}
|
|
369
|
-
|
|
370
|
-
export interface GroupProfileSchema {
|
|
371
|
-
key: string;
|
|
372
|
-
data: any[];
|
|
373
|
-
}
|
|
374
|
-
|
|
316
|
+
events?: string[] | "*";
|
|
375
317
|
/**
|
|
376
|
-
*
|
|
318
|
+
* "create" - create this key in the new version; value are chosen
|
|
319
|
+
* "update" - update this key in the new version; values are chosen
|
|
320
|
+
* "fill" - update this key in the new version, but only if the existing key is null or unset
|
|
321
|
+
* "delete" - delete this key in the new version; values are ignored
|
|
377
322
|
*/
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
users: ImportResult;
|
|
381
|
-
groups: ImportResult[];
|
|
382
|
-
}
|
|
383
|
-
type ImportResult = import("mixpanel-import").ImportResults;
|
|
384
|
-
|
|
323
|
+
strategy?: "create" | "update" | "fill" | "delete" | "";
|
|
324
|
+
values?: ValueValid[];
|
|
385
325
|
/**
|
|
386
|
-
* the
|
|
326
|
+
* optional: for 'fill' mode, daysUnfilled will dictate where the cutoff is in the unfilled data
|
|
387
327
|
*/
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
328
|
+
daysUnfilled?: number;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
export interface UserProfile {
|
|
332
|
+
name?: string;
|
|
333
|
+
email?: string;
|
|
334
|
+
avatar?: string;
|
|
335
|
+
created: string | undefined;
|
|
336
|
+
distinct_id: string;
|
|
337
|
+
[key: string]: ValueValid;
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
export interface Person {
|
|
341
|
+
name: string;
|
|
342
|
+
email?: string;
|
|
343
|
+
avatar?: string;
|
|
344
|
+
created: string | undefined;
|
|
345
|
+
anonymousIds: string[];
|
|
346
|
+
sessionIds: string[];
|
|
347
|
+
distinct_id?: string;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
/**
|
|
351
|
+
* the generated user data
|
|
352
|
+
*/
|
|
353
|
+
export interface LookupTableSchema {
|
|
354
|
+
key: string;
|
|
355
|
+
entries: number;
|
|
356
|
+
attributes: Record<string, ValueValid>;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
export interface LookupTableData {
|
|
360
|
+
key: string;
|
|
361
|
+
data: any[];
|
|
408
362
|
}
|
|
409
363
|
|
|
364
|
+
export interface SCDSchema {
|
|
365
|
+
distinct_id: string;
|
|
366
|
+
insertTime: string;
|
|
367
|
+
startTime: string;
|
|
368
|
+
[key: string]: ValueValid;
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
export interface GroupProfileSchema {
|
|
372
|
+
key: string;
|
|
373
|
+
data: any[];
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
/**
|
|
377
|
+
* the end result of importing data into mixpanel
|
|
378
|
+
*/
|
|
379
|
+
export interface ImportResults {
|
|
380
|
+
events: ImportResult;
|
|
381
|
+
users: ImportResult;
|
|
382
|
+
groups: ImportResult[];
|
|
383
|
+
}
|
|
384
|
+
type ImportResult = import("mixpanel-import").ImportResults;
|
|
385
|
+
|
|
386
|
+
/**
|
|
387
|
+
* the end result of the data generation
|
|
388
|
+
*/
|
|
389
|
+
export type Result = {
|
|
390
|
+
eventData: EventSchema[];
|
|
391
|
+
mirrorEventData: EventSchema[];
|
|
392
|
+
userProfilesData: any[];
|
|
393
|
+
scdTableData: any[][];
|
|
394
|
+
adSpendData: EventSchema[];
|
|
395
|
+
groupProfilesData: GroupProfileSchema[][];
|
|
396
|
+
lookupTableData: LookupTableData[][];
|
|
397
|
+
importResults?: ImportResults;
|
|
398
|
+
files?: string[];
|
|
399
|
+
time?: {
|
|
400
|
+
start: number;
|
|
401
|
+
end: number;
|
|
402
|
+
delta: number;
|
|
403
|
+
human: string;
|
|
404
|
+
};
|
|
405
|
+
operations?: number;
|
|
406
|
+
eventCount?: number;
|
|
407
|
+
userCount?: number;
|
|
408
|
+
};
|
|
409
|
+
|
|
410
410
|
/**
|
|
411
411
|
* Mixpanel Data Generator
|
|
412
412
|
* model events, users, groups, and lookup tables (and SCD props!)
|
|
@@ -414,6 +414,6 @@ declare namespace main {
|
|
|
414
414
|
* import datagenerator from 'make-mp-data';
|
|
415
415
|
* const data = await datagenerator({...opts});
|
|
416
416
|
*/
|
|
417
|
-
declare function main(config:
|
|
417
|
+
declare function main(config: Dungeon): Promise<Result>;
|
|
418
418
|
|
|
419
|
-
export
|
|
419
|
+
export default main;
|