make-mp-data 1.4.4 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.vscode/launch.json +1 -1
- package/.vscode/settings.json +1 -0
- package/index.js +1410 -0
- package/package.json +12 -9
- package/schemas/adspend.js +96 -0
- package/schemas/anon.js +4 -4
- package/schemas/big.js +160 -0
- package/schemas/complex.js +32 -25
- package/schemas/foobar.js +22 -7
- package/schemas/funnels.js +12 -12
- package/schemas/mirror.js +129 -0
- package/schemas/simple.js +18 -32
- package/scratch.mjs +33 -11
- package/scripts/jsdoctest.js +1 -1
- package/scripts/new.sh +68 -0
- package/{core → src}/cli.js +10 -3
- package/{core → src}/utils.js +167 -197
- package/tests/benchmark/concurrency.mjs +52 -0
- package/tests/coverage/.gitkeep +0 -0
- package/tests/e2e.test.js +245 -58
- package/tests/int.test.js +618 -0
- package/tests/jest.config.js +11 -2
- package/tests/testSoup.mjs +3 -3
- package/tests/unit.test.js +351 -227
- package/tsconfig.json +1 -1
- package/types.d.ts +217 -97
- package/core/index.js +0 -1008
- package/schemas/deepNest.js +0 -106
- /package/{data → dungeons}/.gitkeep +0 -0
- /package/{core → src}/chart.js +0 -0
- /package/{core → src}/defaults.js +0 -0
package/tsconfig.json
CHANGED
package/types.d.ts
CHANGED
|
@@ -1,33 +1,53 @@
|
|
|
1
1
|
declare namespace main {
|
|
2
|
+
/**
|
|
3
|
+
* most of the time, the value of a property is a primitive
|
|
4
|
+
*/
|
|
2
5
|
type Primitives = string | number | boolean | Date | Record<string, any>;
|
|
3
6
|
|
|
4
|
-
|
|
7
|
+
/**
|
|
8
|
+
* a "validValue" can be a primitive, an array of primitives, or a function that returns a primitive
|
|
9
|
+
*/
|
|
5
10
|
export type ValueValid = Primitives | ValueValid[] | (() => ValueValid);
|
|
6
11
|
|
|
7
|
-
|
|
12
|
+
/**
|
|
13
|
+
* main config object for the entire data generation
|
|
14
|
+
*/
|
|
8
15
|
export interface Config {
|
|
16
|
+
// constants
|
|
9
17
|
token?: string;
|
|
10
18
|
seed?: string;
|
|
11
19
|
numDays?: number;
|
|
12
20
|
epochStart?: number;
|
|
13
21
|
epochEnd?: number;
|
|
14
22
|
numEvents?: number;
|
|
15
|
-
numUsers?: number;
|
|
16
|
-
|
|
17
|
-
//switches
|
|
18
|
-
isAnonymous?: boolean;
|
|
19
|
-
hasLocation?: boolean;
|
|
20
|
-
hasCampaigns?: boolean;
|
|
21
|
-
hasAdSpend?: boolean;
|
|
22
|
-
hasIOSDevices?: boolean;
|
|
23
|
-
hasAndroidDevices?: boolean;
|
|
24
|
-
hasDesktopDevices?: boolean;
|
|
25
|
-
hasBrowser?: boolean;
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
format?: "csv" | "json";
|
|
23
|
+
numUsers?: number;
|
|
24
|
+
format?: "csv" | "json" | string;
|
|
29
25
|
region?: "US" | "EU";
|
|
30
|
-
|
|
26
|
+
concurrency?: number;
|
|
27
|
+
batchSize?: number;
|
|
28
|
+
|
|
29
|
+
// ids
|
|
30
|
+
simulationName?: string;
|
|
31
|
+
name?: string;
|
|
32
|
+
|
|
33
|
+
//switches
|
|
34
|
+
isAnonymous?: boolean;
|
|
35
|
+
hasAvatar?: boolean;
|
|
36
|
+
hasLocation?: boolean;
|
|
37
|
+
hasCampaigns?: boolean;
|
|
38
|
+
hasAdSpend?: boolean;
|
|
39
|
+
hasIOSDevices?: boolean;
|
|
40
|
+
hasAndroidDevices?: boolean;
|
|
41
|
+
hasDesktopDevices?: boolean;
|
|
42
|
+
hasBrowser?: boolean;
|
|
43
|
+
writeToDisk?: boolean | string;
|
|
44
|
+
verbose?: boolean;
|
|
45
|
+
hasAnonIds?: boolean;
|
|
46
|
+
hasSessionIds?: boolean;
|
|
47
|
+
makeChart?: boolean | string;
|
|
48
|
+
|
|
49
|
+
//models
|
|
50
|
+
events?: EventConfig[]; //| string[]; //can also be a array of strings
|
|
31
51
|
superProps?: Record<string, ValueValid>;
|
|
32
52
|
funnels?: Funnel[];
|
|
33
53
|
userProps?: Record<string, ValueValid>;
|
|
@@ -35,23 +55,26 @@ declare namespace main {
|
|
|
35
55
|
mirrorProps?: Record<string, MirrorProps>;
|
|
36
56
|
groupKeys?: [string, number][] | [string, number, string[]][]; // [key, numGroups, [events]]
|
|
37
57
|
groupProps?: Record<string, Record<string, ValueValid>>;
|
|
38
|
-
lookupTables?:
|
|
39
|
-
writeToDisk?: boolean;
|
|
40
|
-
simulationName?: string;
|
|
41
|
-
verbose?: boolean;
|
|
42
|
-
anonIds?: boolean;
|
|
43
|
-
sessionIds?: boolean;
|
|
44
|
-
makeChart?: boolean | string;
|
|
58
|
+
lookupTables?: LookupTableSchema[];
|
|
45
59
|
soup?: soup;
|
|
46
60
|
hook?: Hook<any>;
|
|
61
|
+
|
|
62
|
+
//allow anything to be on the config
|
|
63
|
+
[key: string]: any;
|
|
47
64
|
}
|
|
48
65
|
|
|
66
|
+
/**
|
|
67
|
+
* the soup is a set of parameters that determine the distribution of events over time
|
|
68
|
+
*/
|
|
49
69
|
type soup = {
|
|
50
70
|
deviation?: number;
|
|
51
71
|
peaks?: number;
|
|
52
72
|
mean?: number;
|
|
53
73
|
};
|
|
54
74
|
|
|
75
|
+
/**
|
|
76
|
+
* the types of hooks that can be used
|
|
77
|
+
*/
|
|
55
78
|
type hookTypes =
|
|
56
79
|
| "event"
|
|
57
80
|
| "user"
|
|
@@ -61,139 +84,236 @@ declare namespace main {
|
|
|
61
84
|
| "mirror"
|
|
62
85
|
| "funnel-pre"
|
|
63
86
|
| "funnel-post"
|
|
64
|
-
|
|
65
|
-
|
|
87
|
+
| "ad-spend"
|
|
88
|
+
| "churn"
|
|
66
89
|
| "";
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* a hook is a function that can be called before each entity is created, and can be used to modify attributes
|
|
93
|
+
*/
|
|
67
94
|
export type Hook<T> = (record: any, type: hookTypes, meta: any) => T;
|
|
68
95
|
|
|
69
|
-
export interface
|
|
96
|
+
export interface hookArrayOptions<T> {
|
|
70
97
|
hook?: Hook<T>;
|
|
71
98
|
type?: hookTypes;
|
|
99
|
+
filename?: string;
|
|
100
|
+
format?: "csv" | "json" | string;
|
|
101
|
+
concurrency?: number;
|
|
102
|
+
[key: string]: any;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* an enriched array is an array that has a hookPush method that can be used to transform-then-push items into the array
|
|
107
|
+
*/
|
|
108
|
+
export interface HookedArray<T> extends Array<T> {
|
|
109
|
+
hookPush: (item: T | T[]) => any;
|
|
110
|
+
flush: () => void;
|
|
111
|
+
getWriteDir: () => string;
|
|
112
|
+
getWritePath: () => string;
|
|
72
113
|
[key: string]: any;
|
|
73
114
|
}
|
|
74
115
|
|
|
75
|
-
export
|
|
76
|
-
|
|
116
|
+
export type AllData =
|
|
117
|
+
| HookedArray<EventSchema>
|
|
118
|
+
| HookedArray<UserProfile>
|
|
119
|
+
| HookedArray<GroupProfileSchema>
|
|
120
|
+
| HookedArray<LookupTableSchema>
|
|
121
|
+
| HookedArray<SCDSchema>
|
|
122
|
+
| any[];
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* the storage object is a key-value store that holds arrays of data
|
|
126
|
+
*/
|
|
127
|
+
export interface Storage {
|
|
128
|
+
eventData?: HookedArray<EventSchema>;
|
|
129
|
+
mirrorEventData?: HookedArray<EventSchema>;
|
|
130
|
+
userProfilesData?: HookedArray<UserProfile>;
|
|
131
|
+
adSpendData?: HookedArray<EventSchema>;
|
|
132
|
+
groupProfilesData?: HookedArray<GroupProfileSchema>[];
|
|
133
|
+
lookupTableData?: HookedArray<LookupTableSchema>[];
|
|
134
|
+
scdTableData?: HookedArray<SCDSchema>[];
|
|
77
135
|
}
|
|
78
136
|
|
|
137
|
+
/**
|
|
138
|
+
* how we define events and their properties
|
|
139
|
+
*/
|
|
79
140
|
export interface EventConfig {
|
|
80
141
|
event?: string;
|
|
81
142
|
weight?: number;
|
|
82
143
|
properties?: Record<string, ValueValid>;
|
|
83
144
|
isFirstEvent?: boolean;
|
|
145
|
+
isChurnEvent?: boolean;
|
|
84
146
|
relativeTimeMs?: number;
|
|
85
147
|
}
|
|
86
148
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
149
|
+
/**
|
|
150
|
+
* the generated event data
|
|
151
|
+
*/
|
|
152
|
+
export interface EventSchema {
|
|
153
|
+
event: string;
|
|
154
|
+
time: string;
|
|
155
|
+
source: string;
|
|
156
|
+
insert_id: string;
|
|
157
|
+
device_id?: string;
|
|
158
|
+
session_id?: string;
|
|
159
|
+
user_id?: string;
|
|
160
|
+
[key: string]: ValueValid;
|
|
95
161
|
}
|
|
96
162
|
|
|
163
|
+
/**
|
|
164
|
+
* how we define funnels and their properties
|
|
165
|
+
*/
|
|
97
166
|
export interface Funnel {
|
|
167
|
+
/**
|
|
168
|
+
* the sequence of events that define the funnel
|
|
169
|
+
*/
|
|
98
170
|
sequence: string[];
|
|
171
|
+
/**
|
|
172
|
+
* how likely the funnel is to be selected
|
|
173
|
+
*/
|
|
99
174
|
weight?: number;
|
|
175
|
+
/**
|
|
176
|
+
* If true, the funnel will be the first thing the user does
|
|
177
|
+
*/
|
|
100
178
|
isFirstFunnel?: boolean;
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
179
|
+
/**
|
|
180
|
+
* If true, the funnel will require the user to repeat the sequence of events in order to convert
|
|
181
|
+
* If false, the user does not need to repeat the sequence of events in order to convert
|
|
182
|
+
* ^ when false, users who repeat the repetitive steps are more likely to convert
|
|
183
|
+
*/
|
|
184
|
+
requireRepeats?: boolean;
|
|
185
|
+
/**
|
|
186
|
+
* how the events in the funnel are ordered for each user
|
|
187
|
+
*/
|
|
107
188
|
order?:
|
|
189
|
+
| string
|
|
108
190
|
| "sequential"
|
|
109
191
|
| "first-fixed"
|
|
110
192
|
| "last-fixed"
|
|
111
|
-
| "random"
|
|
193
|
+
| "random" //totally shuffled
|
|
112
194
|
| "first-and-last-fixed"
|
|
113
195
|
| "middle-fixed"
|
|
114
|
-
|
|
196
|
+
| "interrupted";
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* todo: implement this
|
|
200
|
+
* if set, the funnel might be the last thing the user does
|
|
201
|
+
* ^ the numerical value is the likelihood that the user will churn
|
|
202
|
+
* todo: allow for users to be resurrected
|
|
203
|
+
*/
|
|
204
|
+
isChurnFunnel?: void | number;
|
|
205
|
+
/**
|
|
206
|
+
* the likelihood that a user will convert (0-100%)
|
|
207
|
+
*/
|
|
115
208
|
conversionRate?: number;
|
|
209
|
+
/**
|
|
210
|
+
* the time it takes (on average) to convert in hours
|
|
211
|
+
*/
|
|
116
212
|
timeToConvert?: number;
|
|
213
|
+
/**
|
|
214
|
+
* funnel properties go onto each event in the funnel and are held constant
|
|
215
|
+
*/
|
|
117
216
|
props?: Record<string, ValueValid>;
|
|
118
217
|
}
|
|
119
218
|
|
|
219
|
+
/**
|
|
220
|
+
* mirror props are used to show mutations of event data over time
|
|
221
|
+
* there are different strategies for how to mutate the data
|
|
222
|
+
*/
|
|
120
223
|
export interface MirrorProps {
|
|
224
|
+
/**
|
|
225
|
+
* the event that will be mutated in the new version
|
|
226
|
+
*/
|
|
121
227
|
events?: string[] | "*";
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
228
|
+
/**
|
|
229
|
+
* "create" - create this key in the new version; value are chosen
|
|
230
|
+
* "update" - update this key in the new version; values are chosen
|
|
231
|
+
* "fill" - update this key in the new version, but only if the existing key is null or unset
|
|
232
|
+
* "delete" - delete this key in the new version; values are ignored
|
|
233
|
+
*/
|
|
234
|
+
strategy?: "create" | "update" | "fill" | "delete" | "";
|
|
235
|
+
values?: ValueValid[];
|
|
236
|
+
/**
|
|
237
|
+
* optional: for 'fill' mode, daysUnfilled will dictate where the cutoff is in the unfilled data
|
|
238
|
+
*/
|
|
239
|
+
daysUnfilled?: number;
|
|
130
240
|
}
|
|
131
241
|
|
|
132
|
-
export interface
|
|
242
|
+
export interface UserProfile {
|
|
243
|
+
name?: string;
|
|
244
|
+
email?: string;
|
|
245
|
+
avatar?: string;
|
|
246
|
+
created: string | undefined;
|
|
133
247
|
distinct_id: string;
|
|
134
|
-
insertTime: string;
|
|
135
|
-
startTime: string;
|
|
136
248
|
[key: string]: ValueValid;
|
|
137
249
|
}
|
|
138
250
|
|
|
139
|
-
export
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
}
|
|
251
|
+
export interface Person {
|
|
252
|
+
name: string;
|
|
253
|
+
email?: string;
|
|
254
|
+
avatar?: string;
|
|
255
|
+
created: string | undefined;
|
|
256
|
+
anonymousIds: string[];
|
|
257
|
+
sessionIds: string[];
|
|
258
|
+
distinct_id?: string;
|
|
259
|
+
}
|
|
148
260
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
[key: string]: any;
|
|
261
|
+
/**
|
|
262
|
+
* the generated user data
|
|
263
|
+
*/
|
|
264
|
+
export interface LookupTableSchema {
|
|
265
|
+
key: string;
|
|
266
|
+
entries: number;
|
|
267
|
+
attributes: Record<string, ValueValid>;
|
|
157
268
|
}
|
|
158
269
|
|
|
159
|
-
export interface
|
|
270
|
+
export interface LookupTableData {
|
|
160
271
|
key: string;
|
|
161
272
|
data: any[];
|
|
162
273
|
}
|
|
163
274
|
|
|
164
|
-
export interface
|
|
275
|
+
export interface SCDSchema {
|
|
276
|
+
distinct_id: string;
|
|
277
|
+
insertTime: string;
|
|
278
|
+
startTime: string;
|
|
279
|
+
[key: string]: ValueValid;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
export interface GroupProfileSchema {
|
|
165
283
|
key: string;
|
|
166
284
|
data: any[];
|
|
167
285
|
}
|
|
168
286
|
|
|
287
|
+
/**
|
|
288
|
+
* the end result of importing data into mixpanel
|
|
289
|
+
*/
|
|
169
290
|
export interface ImportResults {
|
|
170
291
|
events: ImportResult;
|
|
171
292
|
users: ImportResult;
|
|
172
293
|
groups: ImportResult[];
|
|
173
294
|
}
|
|
295
|
+
type ImportResult = import("mixpanel-import").ImportResults;
|
|
174
296
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
[key: string]: ValueValid;
|
|
196
|
-
}
|
|
297
|
+
/**
|
|
298
|
+
* the end result of the data generation
|
|
299
|
+
*/
|
|
300
|
+
export type Result = {
|
|
301
|
+
eventData: EventSchema[];
|
|
302
|
+
mirrorEventData: EventSchema[];
|
|
303
|
+
userProfilesData: any[];
|
|
304
|
+
scdTableData: any[];
|
|
305
|
+
adSpendData: EventSchema[];
|
|
306
|
+
groupProfilesData: GroupProfileSchema[];
|
|
307
|
+
lookupTableData: LookupTableData[];
|
|
308
|
+
importResults?: ImportResults;
|
|
309
|
+
files?: string[];
|
|
310
|
+
time?: {
|
|
311
|
+
start: number;
|
|
312
|
+
end: number;
|
|
313
|
+
delta: number;
|
|
314
|
+
human: string;
|
|
315
|
+
};
|
|
316
|
+
};
|
|
197
317
|
}
|
|
198
318
|
|
|
199
319
|
/**
|