make-mp-data 1.2.11 → 1.2.25

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.
@@ -1,7 +1,25 @@
1
1
  {
2
2
  "cSpell.words": [
3
+ "AVCHD",
4
+ "chupacabra",
5
+ "darr",
6
+ "dislikers",
7
+ "Dont",
8
+ "jackalope",
9
+ "mbembe",
10
+ "megalodon",
11
+ "Miley",
12
+ "mokele",
13
+ "mothman",
14
+ "nessie",
15
+ "nesty",
16
+ "planthopper",
17
+ "psyllid",
18
+ "tatzelwurm",
3
19
  "timesoup",
4
- "unparse"
20
+ "unparse",
21
+ "Vlogs",
22
+ "weindgo"
5
23
  ],
6
24
  "jest.runMode": "on-demand",
7
25
  "jest.jestCommandLine": "npm run test --",
package/index.js CHANGED
@@ -41,7 +41,7 @@ async function main(config) {
41
41
  superProps = { platform: ["web", "iOS", "Android"] },
42
42
  userProps = {
43
43
  favoriteColor: ["red", "green", "blue", "yellow"],
44
- spiritAnimal: chance.animal,
44
+ spiritAnimal: chance.animal.bind(chance),
45
45
  },
46
46
  scdProps = { NPS: u.weightedRange(0, 10, 150, 1.6) },
47
47
  groupKeys = [],
@@ -54,6 +54,7 @@ async function main(config) {
54
54
  region = "US",
55
55
  writeToDisk = false,
56
56
  verbose = false,
57
+ hook = (record) => record,
57
58
  } = config;
58
59
  VERBOSE = verbose;
59
60
  config.simulationName = makeName();
@@ -97,11 +98,11 @@ async function main(config) {
97
98
  .filter((e) => !e.isFirstEvent);
98
99
 
99
100
  const firstEvents = events.filter((e) => e.isFirstEvent);
100
- const eventData = [];
101
- const userProfilesData = [];
102
- let scdTableData = [];
103
- const groupProfilesData = [];
104
- const lookupTableData = [];
101
+ const eventData = enrichArray([], { hook, type: "event", config });
102
+ const userProfilesData = enrichArray([], { hook, type: "user", config });
103
+ let scdTableData = enrichArray([], { hook, type: "scd", config });
104
+ const groupProfilesData = enrichArray([], { hook, type: "groups", config });
105
+ const lookupTableData = enrichArray([], { hook, type: "lookups", config });
105
106
  const avgEvPerUser = Math.floor(numEvents / numUsers);
106
107
 
107
108
  //user loop
@@ -110,15 +111,15 @@ async function main(config) {
110
111
  u.progress("users", i);
111
112
  const user = generateUser();
112
113
  const { distinct_id, $created, anonymousIds, sessionIds } = user;
113
- userProfilesData.push(makeProfile(userProps, user));
114
+ userProfilesData.hPush(makeProfile(userProps, user));
114
115
  const mutations = chance.integer({ min: 1, max: 10 });
115
- scdTableData.push(makeSCD(scdProps, distinct_id, mutations, $created));
116
+ scdTableData.hPush(makeSCD(scdProps, distinct_id, mutations, $created));
116
117
  const numEventsThisUser = Math.round(
117
118
  chance.normal({ mean: avgEvPerUser, dev: avgEvPerUser / u.integer(3, 7) })
118
119
  );
119
-
120
+
120
121
  if (firstEvents.length) {
121
- eventData.push(
122
+ eventData.hPush(
122
123
  makeEvent(
123
124
  distinct_id,
124
125
  anonymousIds,
@@ -134,7 +135,7 @@ async function main(config) {
134
135
 
135
136
  //event loop
136
137
  for (let j = 0; j < numEventsThisUser; j++) {
137
- eventData.push(
138
+ eventData.hPush(
138
139
  makeEvent(
139
140
  distinct_id,
140
141
  anonymousIds,
@@ -163,11 +164,11 @@ async function main(config) {
163
164
  const group = {
164
165
  [groupKey]: i,
165
166
  ...makeProfile(groupProps[groupKey]),
166
- $distinct_id: i,
167
+ // $distinct_id: i,
167
168
  };
168
169
  groupProfiles.push(group);
169
170
  }
170
- groupProfilesData.push({ key: groupKey, data: groupProfiles });
171
+ groupProfilesData.hPush({ key: groupKey, data: groupProfiles });
171
172
  }
172
173
  log("\n");
173
174
 
@@ -183,7 +184,7 @@ async function main(config) {
183
184
  };
184
185
  data.push(item);
185
186
  }
186
- lookupTableData.push({ key, data });
187
+ lookupTableData.hPush({ key, data });
187
188
  }
188
189
  const { eventFiles, userFiles, scdFiles, groupFiles, lookupFiles, folder } =
189
190
  buildFileNames(config);
@@ -194,7 +195,7 @@ async function main(config) {
194
195
  [groupFiles, groupProfilesData],
195
196
  [lookupFiles, lookupTableData],
196
197
  ];
197
- log("\n")
198
+ log("\n");
198
199
  log(`---------------SIMULATION----------------`, "\n");
199
200
 
200
201
  if (!writeToDisk && !token) {
@@ -204,6 +205,8 @@ async function main(config) {
204
205
  scdTableData,
205
206
  groupProfilesData,
206
207
  lookupTableData,
208
+ import: {},
209
+ files: []
207
210
  };
208
211
  }
209
212
  log(`-----------------WRITES------------------`, `\n\n`);
@@ -443,6 +446,18 @@ function buildFileNames(config) {
443
446
  }
444
447
 
445
448
 
449
+ function enrichArray(arr = [], opts = {}) {
450
+ const { hook = a => a, type = "", config = {} } = opts;
451
+
452
+ function transformThenPush(item) {
453
+ return arr.push(hook(item, type, config));
454
+ }
455
+
456
+ arr.hPush = transformThenPush;
457
+
458
+ return arr;
459
+ };
460
+
446
461
 
447
462
 
448
463
  // this is for CLI
@@ -487,7 +502,9 @@ if (require.main === module) {
487
502
  main(config)
488
503
  .then((data) => {
489
504
  log(`-----------------SUMMARY-----------------`);
490
- const { events, groups, users } = data.import;
505
+ const d = { success: 0, bytes: 0 };
506
+ const darr = [d];
507
+ const { events = d, groups = darr, users = d } = data.import;
491
508
  const files = data.files;
492
509
  const folder = files?.pop();
493
510
  const groupBytes = groups.reduce((acc, group) => {
@@ -504,7 +521,7 @@ if (require.main === module) {
504
521
  bytes: bytesHuman(bytes || 0),
505
522
  };
506
523
  if (bytes > 0) console.table(stats);
507
- log(`\nfiles written to ${folder} ...`);
524
+ log(`\nfiles written to ${folder || "no where; we didn't write anything"} ...`);
508
525
  log(" " + files?.flat().join("\n "));
509
526
  log(`\n----------------SUMMARY-----------------\n\n\n`);
510
527
  })
package/models/complex.js CHANGED
@@ -8,7 +8,8 @@
8
8
 
9
9
  const Chance = require('chance');
10
10
  const chance = new Chance();
11
- const { weightedRange, makeProducts, date, makeHashTags } = require('../utils.js');
11
+ const { weightedRange, date, integer } = require('../utils.js');
12
+ const u = require('ak-tools');
12
13
 
13
14
  /** @type {import('../types.js').Config} */
14
15
  const config = {
@@ -28,26 +29,24 @@ const config = {
28
29
  "weight": 2,
29
30
  "properties": {
30
31
  amount: weightedRange(5, 500, 1000, .25),
31
- currency: ["USD", "CAD", "EUR", "BTC", "ETH", "JPY"],
32
- cart: makeProducts,
32
+ currency: ["USD", "USD", "USD", "CAD", "EUR", "EUR", "BTC", "BTC", "ETH", "JPY"],
33
+ cart: makeProducts(12),
33
34
  }
34
35
  },
35
36
  {
36
37
  "event": "add to cart",
37
38
  "weight": 4,
38
39
  "properties": {
39
- isFeaturedItem: [true, false, false],
40
40
  amount: weightedRange(5, 500, 1000, .25),
41
- rating: weightedRange(1, 5),
42
- reviews: weightedRange(0, 35),
43
- product_id: weightedRange(1, 1000)
41
+ qty: integer(1, 5),
42
+ product_id: weightedRange(1, 1000, 42, 1.4)
44
43
  }
45
44
  },
46
45
  {
47
46
  "event": "page view",
48
47
  "weight": 10,
49
48
  "properties": {
50
- page: ["/", "/", "/help", "/account", "/watch", "/listen", "/product", "/people", "/peace"],
49
+ page: ["/", "/", "/", "/learn-more", "/pricing", "/contact", "/about", "/careers", "/sign-up", "/login", "/app", "/app", "/app", "/app"],
51
50
  utm_source: ["$organic", "$organic", "$organic", "$organic", "google", "google", "google", "facebook", "facebook", "twitter", "linkedin"],
52
51
  }
53
52
  },
@@ -68,7 +67,7 @@ const config = {
68
67
  "event": "view item",
69
68
  "weight": 8,
70
69
  "properties": {
71
- product_id: weightedRange(1, 1000),
70
+ product_id: weightedRange(1, 1000, 24, 3),
72
71
  colors: ["light", "dark", "custom", "dark"]
73
72
  }
74
73
  },
@@ -76,22 +75,33 @@ const config = {
76
75
  "event": "save item",
77
76
  "weight": 5,
78
77
  "properties": {
79
- product_id: weightedRange(1, 1000),
78
+ product_id: weightedRange(1, 1000, 8, 12),
80
79
  colors: ["light", "dark", "custom", "dark"]
81
80
  }
82
81
  },
82
+ {
83
+ "event": "support ticket",
84
+ "weight": 2,
85
+ "properties": {
86
+ product_id: weightedRange(1, 1000, 420, .6),
87
+ description: chance.sentence.bind(chance),
88
+ severity: ["low", "medium", "high"],
89
+ ticket_id: chance.guid.bind(chance)
90
+ }
91
+ },
83
92
  {
84
93
  "event": "sign up",
85
94
  "isFirstEvent": true,
86
95
  "weight": 0,
87
96
  "properties": {
88
- variant: ["A", "B", "C", "Control"],
89
- experiment: ["no password", "social sign in", "new tutorial"],
97
+ plan: ["free", "free", "free", "free", "basic", "basic", "basic", "premium", "premium", "enterprise"],
98
+ dateOfRenewal: date(100, false),
99
+ codewords: u.makeName,
90
100
  }
91
101
  }
92
102
  ],
93
103
  superProps: {
94
- platform: ["web", "mobile", "web", "mobile", "web", "kiosk", "smartTV"],
104
+ device: deviceAttributes()
95
105
  // emotions: generateEmoji(),
96
106
 
97
107
  },
@@ -102,8 +112,12 @@ const config = {
102
112
  userProps: {
103
113
  title: chance.profession.bind(chance),
104
114
  luckyNumber: weightedRange(42, 420),
105
- // vibe: generateEmoji(),
106
- spiritAnimal: chance.animal.bind(chance)
115
+ experiment: designExperiment(),
116
+ spiritAnimal: ["unicorn", "dragon", "phoenix", "sasquatch", "yeti", "kraken", "jackalope", "thunderbird", "mothman", "nessie", "chupacabra", "jersey devil", "bigfoot", "weindgo", "bunyip", "mokele-mbembe", "tatzelwurm", "megalodon"],
117
+ timezone: chance.timezone.bind(chance), // ["America/New_York", "America/Los_Angeles", "America/Chicago", "America/Denver", "America/Phoenix", "America/Anchorage", "Pacific/Honolulu"]
118
+ ip: chance.ip.bind(chance),
119
+ lastCart: makeProducts(5),
120
+
107
121
  },
108
122
 
109
123
  scdProps: {
@@ -127,8 +141,9 @@ const config = {
127
141
  $name: () => { return chance.company(); },
128
142
  $email: () => { return `CSM: ${chance.pickone(["AK", "Jessica", "Michelle", "Dana", "Brian", "Dave"])}`; },
129
143
  "# of employees": weightedRange(3, 10000),
130
- "sector": ["tech", "finance", "healthcare", "education", "government", "non-profit"],
144
+ "industry": ["tech", "finance", "healthcare", "education", "government", "non-profit"],
131
145
  "segment": ["enterprise", "SMB", "mid-market"],
146
+ "products": [["core"], ["core"], ["core", "add-ons"], ["core", "pro-serve"], ["core", "add-ons", "pro-serve"], ["core", "BAA", "enterprise"], ["free"], ["free"], ["free", "addons"]],
132
147
  }
133
148
  },
134
149
 
@@ -172,6 +187,118 @@ const config = {
172
187
 
173
188
  }
174
189
  ],
190
+
191
+ hook: function (record, type, meta) {
192
+ return record;
193
+ }
194
+ };
195
+
196
+
197
+
198
+ function makeHashTags() {
199
+ const possibleHashtags = [];
200
+ for (let i = 0; i < 20; i++) {
201
+ possibleHashtags.push('#' + u.makeName(2, ''));
202
+ }
203
+
204
+ const numHashtags = integer(integer(1, 5), integer(5, 10));
205
+ const hashtags = [];
206
+ for (let i = 0; i < numHashtags; i++) {
207
+ hashtags.push(chance.pickone(possibleHashtags));
208
+ }
209
+ return [hashtags];
175
210
  };
176
211
 
212
+ function makeProducts(maxItems = 10) {
213
+
214
+ return function () {
215
+ const categories = ["Device Accessories", "eBooks", "Automotive", "Baby Products", "Beauty", "Books", "Camera & Photo", "Cell Phones & Accessories", "Collectible Coins", "Consumer Electronics", "Entertainment Collectibles", "Fine Art", "Grocery & Gourmet Food", "Health & Personal Care", "Home & Garden", "Independent Design", "Industrial & Scientific", "Accessories", "Major Appliances", "Music", "Musical Instruments", "Office Products", "Outdoors", "Personal Computers", "Pet Supplies", "Software", "Sports", "Sports Collectibles", "Tools & Home Improvement", "Toys & Games", "Video, DVD & Blu-ray", "Video Games", "Watches"];
216
+ const slugs = ['/sale/', '/featured/', '/home/', '/search/', '/wishlist/', '/'];
217
+ const assetExtension = ['.png', '.jpg', '.jpeg', '.heic', '.mp4', '.mov', '.avi'];
218
+ const data = [];
219
+ const numOfItems = integer(1, 12);
220
+
221
+ for (var i = 0; i < numOfItems; i++) {
222
+ const category = chance.pickone(categories);
223
+ const slug = chance.pickone(slugs);
224
+ const asset = chance.pickone(assetExtension);
225
+ const product_id = chance.guid();
226
+ const price = integer(1, 300);
227
+ const quantity = integer(1, 5);
228
+
229
+ const item = {
230
+ product_id: product_id,
231
+ sku: integer(11111, 99999),
232
+ amount: price,
233
+ quantity: quantity,
234
+ value: price * quantity,
235
+ featured: chance.pickone([true, false]),
236
+ category: category,
237
+ urlSlug: slug + category,
238
+ asset: `${category}-${integer(1, 20)}${asset}`
239
+ };
240
+
241
+ data.push(item);
242
+ }
243
+
244
+ return [data];
245
+ };
246
+ };
247
+
248
+
249
+ function designExperiment() {
250
+ return function () {
251
+ const variants = ["A", "B", "C", "Control"];
252
+ const variant = chance.pickone(variants);
253
+ const experiments = ["no password", "social sign in", "new tutorial", "new search"];
254
+ const experiment = chance.pickone(experiments);
255
+ const multi_variates = ["A/B", "A/B/C", "A/B/C/D", "Control"];
256
+ const multi_variate = chance.pickone(multi_variates);
257
+ const impression_id = chance.guid();
258
+
259
+
260
+
261
+ const chosen = {
262
+ variant,
263
+ experiment,
264
+ multi_variate,
265
+ impression_id
266
+ };
267
+
268
+ return [chosen];
269
+ };
270
+ }
271
+
272
+ function deviceAttributes(isMobile = false) {
273
+ return function () {
274
+ let devices = ["desktop", "laptop", "desktop", "laptop", "desktop", "laptop", "other"];
275
+ if (isMobile) devices = [...devices, "mobile", "mobile", "mobile", "tablet"];
276
+ const device = chance.pickone(devices);
277
+ const oses = ["Windows", "macOS", "Windows", "macOS", "macOS", "Linux", "Windows", "macOS", "Windows", "macOS", "macOS", "TempleOS"];
278
+ if (isMobile) oses = [...oses, "iOS", "Android", "iOS", "Android"];
279
+ const os = chance.pickone(oses);
280
+ const browser = chance.pickone(["Chrome", "Firefox", "Safari", "Edge", "Opera", "IE", "Brave", "Vivaldi"]);
281
+ const version = chance.integer({ min: 1, max: 15 });
282
+ const resolution = chance.pickone(["1920x1080", "1280x720", "1024x768", "800x600", "640x480"]);
283
+ const language = chance.pickone(["en-US", "en-US", "en-US", "en-GB", "es", "es", "fr", "de", "it", "ja", "zh", "ru"]);
284
+
285
+ const chosen = {
286
+ platform: device,
287
+ os,
288
+ browser,
289
+ version,
290
+ resolution,
291
+ language
292
+ };
293
+
294
+ return [chosen];
295
+
296
+ };
297
+ }
298
+
299
+
300
+
301
+
302
+
303
+
177
304
  module.exports = config;
@@ -38,8 +38,8 @@ function generateVideoMeta() {
38
38
  observedLatencyTimestamps: chance.pickset([].range(1, 300000), int(1, 40))
39
39
  },
40
40
  videoStats: {
41
- numerOfPlays: int(10, 10000000),
42
- isReccommendedVideo: chance.bool(),
41
+ numberOfPlays: int(10, 10000000),
42
+ isRecommendedVideo: chance.bool(),
43
43
  inPlaylists: chance.pickset(hashtags, int(1, hashtags.length)),
44
44
  likers: chance.n(chance.guid, int(3, 100)),
45
45
  dislikers: chance.n(chance.guid, int(3, 100)),
@@ -49,12 +49,12 @@ function generateVideoMeta() {
49
49
  hashtags: chance.pickset(hashtags, int(1, 10)),
50
50
  category: chance.pickone(categories),
51
51
  },
52
- availibility: {
52
+ availability: {
53
53
  hasAdvertisements: chance.bool(),
54
54
  canBeSeenOnPlans: chance.pickset(plans, int(1, plans.length)),
55
55
  releaseInfo: {
56
56
  isReleased: chance.bool({ likelihood: 90 }),
57
- relaseDate: chance.date({ year: 2021 })
57
+ releaseDate: chance.date({ year: 2021 })
58
58
  }
59
59
  }
60
60
 
package/models/simple.js CHANGED
@@ -4,7 +4,7 @@ const dayjs = require("dayjs");
4
4
  const utc = require("dayjs/plugin/utc");
5
5
  dayjs.extend(utc);
6
6
  const { uid, comma } = require('ak-tools');
7
- const { weighList, weightedRange, date, integer } = require('../utils')
7
+ const { weighList, weightedRange, date, integer } = require('../utils');
8
8
 
9
9
  const itemCategories = ["Books", "Movies", "Music", "Games", "Electronics", "Computers", "Smart Home", "Home", "Garden", "Pet", "Beauty", "Health", "Toys", "Kids", "Baby", "Handmade", "Sports", "Outdoors", "Automotive", "Industrial", "Entertainment", "Art", "Food", "Appliances", "Office", "Wedding", "Software"];
10
10
 
@@ -114,10 +114,10 @@ const config = {
114
114
  userProps: {
115
115
  title: chance.profession.bind(chance),
116
116
  luckyNumber: weightedRange(42, 420),
117
- spiritAnimal: chance.animal.bind(chance)
117
+ spiritAnimal: ["duck", "dog", "otter", "penguin", "cat", "elephant", "lion", "cheetah", "giraffe", "zebra", "rhino", "hippo", "whale", "dolphin", "shark", "octopus", "squid", "jellyfish", "starfish", "seahorse", "crab", "lobster", "shrimp", "clam", "snail", "slug", "butterfly", "moth", "bee", "wasp", "ant", "beetle", "ladybug", "caterpillar", "centipede", "millipede", "scorpion", "spider", "tarantula", "tick", "mite", "mosquito", "fly", "dragonfly", "damselfly", "grasshopper", "cricket", "locust", "mantis", "cockroach", "termite", "praying mantis", "walking stick", "stick bug", "leaf insect", "lacewing", "aphid", "cicada", "thrips", "psyllid", "scale insect", "whitefly", "mealybug", "planthopper", "leafhopper", "treehopper", "flea", "louse", "bedbug", "flea beetle", "weevil", "longhorn beetle", "leaf beetle", "tiger beetle", "ground beetle", "lady beetle", "firefly", "click beetle", "rove beetle", "scarab beetle", "dung beetle", "stag beetle", "rhinoceros beetle", "hercules beetle", "goliath beetle", "jewel beetle", "tortoise beetle"]
118
118
  },
119
119
 
120
- scdProps: { },
120
+ scdProps: {},
121
121
 
122
122
  /*
123
123
  for group analytics keys, we need an array of arrays [[],[],[]]
@@ -126,6 +126,9 @@ const config = {
126
126
  groupKeys: [],
127
127
  groupProps: {},
128
128
  lookupTables: [],
129
+ hook: function (record, type, meta) {
130
+ return record;
131
+ }
129
132
  };
130
133
 
131
134
 
package/package.json CHANGED
@@ -1,13 +1,15 @@
1
1
  {
2
2
  "name": "make-mp-data",
3
- "version": "1.2.11",
3
+ "version": "1.2.25",
4
4
  "description": "builds all mixpanel primitives for a given project",
5
5
  "main": "index.js",
6
6
  "types": "types.d.ts",
7
7
  "scripts": {
8
8
  "start": "node index.js",
9
+ "dev": "./scripts/go.sh",
10
+ "complex": "nodemon index.js --complex",
11
+ "simple": "nodemon index.js",
9
12
  "prune": "rm ./data/*",
10
- "go": "sh ./scripts/go.sh",
11
13
  "post": "npm publish",
12
14
  "test": "jest --runInBand",
13
15
  "deps": "sh ./scripts/deps.sh"
@@ -38,7 +40,7 @@
38
40
  },
39
41
  "homepage": "https://github.com/ak--47/make-mp-data#readme",
40
42
  "dependencies": {
41
- "ak-tools": "^1.0.55",
43
+ "ak-tools": "^1.0.57",
42
44
  "chance": "^1.1.11",
43
45
  "dayjs": "^1.11.11",
44
46
  "mixpanel-import": "^2.5.51",
package/scripts/go.sh CHANGED
@@ -1,2 +1,2 @@
1
1
  #!/bin/bash
2
- RUNTIME=local node --inspect index.js --writeToDisk false -u 100 -e 10000
2
+ RUNTIME=local nodemon --inspect index.js --writeToDisk false -u 100 -e 10000
@@ -55,16 +55,6 @@ describe('utils', () => {
55
55
 
56
56
 
57
57
 
58
- test('hashtags', () => {
59
- const hashtags = makeHashTags();
60
- expect(hashtags).toBeInstanceOf(Array);
61
- expect(hashtags).not.toHaveLength(0);
62
- hashtags.forEach(tag => {
63
- expect(tag).toMatch(/^#/);
64
- });
65
- });
66
-
67
-
68
58
 
69
59
  test('person: fields', () => {
70
60
  const generatedPerson = person();
@@ -74,19 +64,19 @@ describe('utils', () => {
74
64
  });
75
65
 
76
66
 
77
- test('date: past date', () => {
67
+ test('date: past', () => {
78
68
  const pastDate = date(10, true, 'YYYY-MM-DD')();
79
69
  expect(dayjs(pastDate, 'YYYY-MM-DD').isValid()).toBeTruthy();
80
70
  expect(dayjs(pastDate).isBefore(dayjs())).toBeTruthy();
81
71
  });
82
72
 
83
- test('date: future date', () => {
73
+ test('date: future', () => {
84
74
  const futureDate = date(10, false, 'YYYY-MM-DD')();
85
75
  expect(dayjs(futureDate, 'YYYY-MM-DD').isValid()).toBeTruthy();
86
76
  expect(dayjs(futureDate).isAfter(dayjs())).toBeTruthy();
87
77
  });
88
78
 
89
- test('dates: returns pairs of dates', () => {
79
+ test('dates: pairs', () => {
90
80
  const datePairs = dates(10, 3, 'YYYY-MM-DD');
91
81
  expect(datePairs).toBeInstanceOf(Array);
92
82
  expect(datePairs).toHaveLength(3);
@@ -95,18 +85,18 @@ describe('utils', () => {
95
85
  });
96
86
  });
97
87
 
98
- test('choose: choose from array', () => {
88
+ test('choose: array', () => {
99
89
  const options = ['apple', 'banana', 'cherry'];
100
90
  const choice = choose(options);
101
91
  expect(options).toContain(choice);
102
92
  });
103
93
 
104
- test('choose: execute function', () => {
94
+ test('choose: function', () => {
105
95
  const result = choose(() => 'test');
106
96
  expect(result).toBe('test');
107
97
  });
108
98
 
109
- test('exhaust: exhaust array elements', () => {
99
+ test('exhaust: elements', () => {
110
100
  const arr = [1, 2, 3];
111
101
  const exhaustFn = exhaust([...arr]);
112
102
  expect(exhaustFn()).toBe(1);
@@ -115,25 +105,21 @@ describe('utils', () => {
115
105
  expect(exhaustFn()).toBeUndefined();
116
106
  });
117
107
 
118
- test('generateEmoji: returns string of emojis', () => {
119
- const emojis = generateEmoji(5)();
120
- expect(typeof emojis).toBe('string');
121
- expect(emojis.split(', ').length).toBeLessThanOrEqual(5);
122
- });
123
108
 
124
- test('getUniqueKeys: find unique keys', () => {
109
+
110
+ test('unique keys', () => {
125
111
  const objects = [{ a: 1, b: 2 }, { a: 3, c: 4 }, { a: 5, b: 6 }];
126
112
  const uniqueKeys = getUniqueKeys(objects);
127
113
  expect(uniqueKeys).toEqual(expect.arrayContaining(['a', 'b', 'c']));
128
114
  });
129
115
 
130
116
 
131
- test('date: generates a valid date', () => {
117
+ test('date', () => {
132
118
  const result = date();
133
119
  expect(dayjs(result()).isValid()).toBe(true);
134
120
  });
135
121
 
136
- test('dates: generates an array of date pairs', () => {
122
+ test('dates', () => {
137
123
  const result = dates();
138
124
  expect(result).toBeInstanceOf(Array);
139
125
  expect(result.length).toBe(5); // Assuming default numPairs is 5
@@ -145,7 +131,7 @@ describe('utils', () => {
145
131
  });
146
132
  });
147
133
 
148
- test('day: generates a day within range', () => {
134
+ test('day', () => {
149
135
  const start = '2020-01-01';
150
136
  const end = '2020-01-30';
151
137
  const result = day(start, end);
@@ -154,7 +140,7 @@ describe('utils', () => {
154
140
  expect(dayjs(dayResult.day).isBefore(dayjs(dayResult.end))).toBe(true);
155
141
  });
156
142
 
157
- test('exhaust: sequentially removes items from array', () => {
143
+ test('exhaust', () => {
158
144
  const arr = [1, 2, 3];
159
145
  const next = exhaust(arr);
160
146
  expect(next()).toBe(1);
@@ -163,7 +149,13 @@ describe('utils', () => {
163
149
  expect(next()).toBe(undefined); // or whatever your implementation does after array is exhausted
164
150
  });
165
151
 
166
- test('generateEmoji: generates correct format and length', () => {
152
+ test('emoji: works', () => {
153
+ const emojis = generateEmoji(5)();
154
+ expect(typeof emojis).toBe('string');
155
+ expect(emojis.split(', ').length).toBeLessThanOrEqual(5);
156
+ });
157
+
158
+ test('emoji: length', () => {
167
159
  const result = generateEmoji();
168
160
  const emojis = result();
169
161
  expect(typeof emojis).toBe('string');
package/types.d.ts CHANGED
@@ -1,73 +1,76 @@
1
1
  declare namespace main {
2
+ type primitives = string | number | boolean | Date | Object;
3
+ type valueValid =
4
+ | primitives
5
+ | primitives[]
6
+ | (() => primitives | primitives[]);
2
7
 
3
- type primitives = string | number | boolean | Date | Object;
4
- type valueValid = primitives | primitives[] | (() => primitives | primitives[]);
8
+ export interface Config {
9
+ token?: string;
10
+ seed?: string;
11
+ numDays?: number;
12
+ numEvents?: number;
13
+ numUsers?: number;
14
+ format?: "csv" | "json";
15
+ region?: string;
16
+ events?: EventConfig[];
17
+ superProps?: Record<string, valueValid>;
18
+ userProps?: Record<string, valueValid>;
19
+ scdProps?: Record<string, valueValid>;
20
+ groupKeys?: [string, number][];
21
+ groupProps?: Record<string, GroupProperty>; // Adjust according to usage
22
+ lookupTables?: LookupTable[];
23
+ writeToDisk?: boolean;
24
+ simulationName?: string;
25
+ verbose?: boolean;
26
+ anonIds?: boolean;
27
+ sessionIds?: boolean;
28
+ hook?: Hook;
29
+ }
5
30
 
6
- export interface Config {
7
- token?: string;
8
- seed?: string;
9
- numDays?: number;
10
- numEvents?: number;
11
- numUsers?: number;
12
- format?: "csv" | "json";
13
- region?: string;
14
- events?: EventConfig[];
15
- superProps?: Record<string, valueValid>;
16
- userProps?: Record<string, valueValid>;
17
- scdProps?: Record<string, valueValid>;
18
- groupKeys?: [string, number][];
19
- groupProps?: Record<string, GroupProperty>; // Adjust according to usage
20
- lookupTables?: LookupTable[];
21
- writeToDisk?: boolean;
22
- simulationName?: string;
23
- verbose?: boolean;
24
- anonIds?: boolean;
25
- sessionIds?: boolean;
26
- }
27
-
28
- interface EventConfig {
29
- event?: string;
30
- weight?: number;
31
- properties?: {
32
- [key: string]: valueValid; // Consider refining based on actual properties used
33
- };
34
- isFirstEvent?: boolean;
35
- }
31
+ export type Hook = (record: any, type: string, meta: any) => any;
36
32
 
37
- interface GroupProperty {
38
- [key?: string]: valueValid;
39
- }
33
+ interface EventConfig {
34
+ event?: string;
35
+ weight?: number;
36
+ properties?: {
37
+ [key: string]: valueValid; // Consider refining based on actual properties used
38
+ };
39
+ isFirstEvent?: boolean;
40
+ }
40
41
 
41
- interface LookupTable {
42
- key: string;
43
- entries: number;
44
- attributes: {
42
+ interface GroupProperty {
45
43
  [key?: string]: valueValid;
46
- };
47
- }
44
+ }
45
+
46
+ interface LookupTable {
47
+ key: string;
48
+ entries: number;
49
+ attributes: {
50
+ [key?: string]: valueValid;
51
+ };
52
+ }
48
53
 
49
- type Result = {
54
+ type Result = {
50
55
  eventData: {
51
- event: any;
52
- $source: string;
56
+ event: any;
57
+ $source: string;
53
58
  }[];
54
59
  userProfilesData: any[];
55
60
  scdTableData: any[];
56
61
  groupProfilesData: {
57
- key: string;
58
- data: any[];
62
+ key: string;
63
+ data: any[];
59
64
  }[];
60
65
  lookupTableData: {
61
- key: string;
62
- data: any[];
66
+ key: string;
67
+ data: any[];
63
68
  }[];
64
69
  import?: undefined;
65
70
  files?: undefined;
71
+ };
66
72
  }
67
73
 
68
- }
69
-
70
-
71
74
  /**
72
75
  * Mixpanel Data Generator
73
76
  * model events, users, groups, and lookup tables (and SCD props!)
@@ -75,8 +78,5 @@ type Result = {
75
78
  * const gen = require('make-mp-data')
76
79
  * const dta = gen({writeToDisk: false})
77
80
  */
78
- declare function main(
79
- config: main.Config
80
- ): Promise<main.Result>;
81
- export = main;
82
-
81
+ declare function main(config: main.Config): Promise<main.Result>;
82
+ export = main;
package/utils.js CHANGED
@@ -81,16 +81,29 @@ function day(start, end) {
81
81
  };
82
82
 
83
83
  function choose(value) {
84
- if (typeof value === 'function') {
85
- return value();
86
- }
87
- if (Array.isArray(value)) {
88
- return chance.pickone(value);
89
- }
84
+ try {
85
+ // Keep resolving the value if it's a function
86
+ while (typeof value === 'function') {
87
+ value = value();
88
+ }
90
89
 
91
- return value;
92
- };
90
+ // Now, if the resolved value is an array, use chance.pickone
91
+ if (Array.isArray(value)) {
92
+ return chance.pickone(value);
93
+ }
93
94
 
95
+ if (typeof value === 'string') {
96
+ return value;
97
+ }
98
+
99
+ // If it's not a function or array, return it as is
100
+ return value;
101
+ }
102
+ catch (e) {
103
+ console.error(`\n\nerror on value: ${value};\n\n`,e, '\n\n');
104
+ return '';
105
+ }
106
+ }
94
107
  function exhaust(arr) {
95
108
  return function () {
96
109
  return arr.shift();
@@ -120,63 +133,6 @@ function integer(min, max) {
120
133
  return 0;
121
134
  };
122
135
 
123
- function makeHashTags() {
124
- const popularHashtags = [
125
- '#GalacticAdventures',
126
- '#EnchantedExplorations',
127
- '#MagicalMoments',
128
- '#EpicQuests',
129
- '#WonderfulWorlds',
130
- '#FantasyFrenzy',
131
- '#MysticalMayhem',
132
- '#MythicalMarvels',
133
- '#LegendaryLegends',
134
- '#DreamlandDiaries',
135
- '#WhimsicalWonders',
136
- '#FabledFables'
137
- ];
138
-
139
- const numHashtags = integer(integer(1, 5), integer(5, 10));
140
- const hashtags = [];
141
- for (let i = 0; i < numHashtags; i++) {
142
- hashtags.push(chance.pickone(popularHashtags));
143
- }
144
- return hashtags;
145
- };
146
-
147
- function makeProducts() {
148
- let categories = ["Device Accessories", "eBooks", "Automotive", "Baby Products", "Beauty", "Books", "Camera & Photo", "Cell Phones & Accessories", "Collectible Coins", "Consumer Electronics", "Entertainment Collectibles", "Fine Art", "Grocery & Gourmet Food", "Health & Personal Care", "Home & Garden", "Independent Design", "Industrial & Scientific", "Accessories", "Major Appliances", "Music", "Musical Instruments", "Office Products", "Outdoors", "Personal Computers", "Pet Supplies", "Software", "Sports", "Sports Collectibles", "Tools & Home Improvement", "Toys & Games", "Video, DVD & Blu-ray", "Video Games", "Watches"];
149
- let slugs = ['/sale/', '/featured/', '/home/', '/search/', '/wishlist/', '/'];
150
- let assetExtension = ['.png', '.jpg', '.jpeg', '.heic', '.mp4', '.mov', '.avi'];
151
- let data = [];
152
- let numOfItems = integer(1, 12);
153
-
154
- for (var i = 0; i < numOfItems; i++) {
155
-
156
- let category = chance.pickone(categories);
157
- let slug = chance.pickone(slugs);
158
- let asset = chance.pickone(assetExtension);
159
- let product_id = chance.guid();
160
- let price = integer(1, 300);
161
- let quantity = integer(1, 5);
162
-
163
- let item = {
164
- product_id: product_id,
165
- sku: integer(11111, 99999),
166
- amount: price,
167
- quantity: quantity,
168
- value: price * quantity,
169
- featured: chance.pickone([true, false]),
170
- category: category,
171
- urlSlug: slug + category,
172
- asset: `${category}-${integer(1, 20)}${asset}`
173
- };
174
-
175
- data.push(item);
176
- }
177
-
178
- return data;
179
- };
180
136
 
181
137
  // Box-Muller transform to generate standard normally distributed values
182
138
  function boxMullerRandom() {
@@ -351,8 +307,7 @@ module.exports = {
351
307
  choose,
352
308
  exhaust,
353
309
  integer,
354
- makeHashTags,
355
- makeProducts,
310
+
356
311
  boxMullerRandom,
357
312
  applySkew,
358
313
  mapToRange,