make-mp-data 3.0.6 ā 3.1.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/README.md +34 -0
- package/dungeons/capstone/capstone-ic3.js +291 -0
- package/dungeons/capstone/capstone-ic4.js +598 -0
- package/dungeons/capstone/capstone-ic5.js +668 -0
- package/dungeons/capstone/generate-product-lookup.js +309 -0
- package/dungeons/complex.js +428 -0
- package/entry.js +1 -1
- package/index.js +7 -2
- package/lib/cli/cli.js +3 -11
- package/lib/core/config-validator.js +7 -10
- package/lib/orchestrators/mixpanel-sender.js +47 -36
- package/package.json +2 -2
|
@@ -0,0 +1,428 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This is the default configuration file for the data generator in COMPLEX mode
|
|
3
|
+
* notice how the config object is structured, and see it's type definition in ./types.d.ts
|
|
4
|
+
* feel free to modify this file to customize the data you generate
|
|
5
|
+
* see helper functions in utils.js for more ways to generate data
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
import Chance from 'chance';
|
|
10
|
+
const chance = new Chance();
|
|
11
|
+
import dayjs from "dayjs";
|
|
12
|
+
import utc from "dayjs/plugin/utc.js";
|
|
13
|
+
dayjs.extend(utc);
|
|
14
|
+
import { weighNumRange, date, integer } from "../lib/utils/utils.js";
|
|
15
|
+
import * as u from 'ak-tools';
|
|
16
|
+
|
|
17
|
+
/** @type {import('../types.js').Dungeon} */
|
|
18
|
+
const config = {
|
|
19
|
+
token: "",
|
|
20
|
+
seed: "quite complexus",
|
|
21
|
+
numDays: 30, //how many days worth of data
|
|
22
|
+
numEvents: 100_000, //how many events
|
|
23
|
+
numUsers: 1000, //how many users
|
|
24
|
+
format: 'json', //csv or json
|
|
25
|
+
region: "US",
|
|
26
|
+
hasAnonIds: true, //if true, anonymousIds are created for each user
|
|
27
|
+
hasSessionIds: true, //if true, hasSessionIds are created for each user
|
|
28
|
+
|
|
29
|
+
hasLocation: true,
|
|
30
|
+
hasAndroidDevices: true,
|
|
31
|
+
hasIOSDevices: true,
|
|
32
|
+
hasDesktopDevices: true,
|
|
33
|
+
hasBrowser: true,
|
|
34
|
+
hasCampaigns: true,
|
|
35
|
+
isAnonymous: false,
|
|
36
|
+
hasAdSpend: true,
|
|
37
|
+
|
|
38
|
+
hasAvatar: true,
|
|
39
|
+
|
|
40
|
+
batchSize: 500_000,
|
|
41
|
+
concurrency: 1,
|
|
42
|
+
|
|
43
|
+
funnels: [],
|
|
44
|
+
events: [
|
|
45
|
+
{
|
|
46
|
+
"event": "checkout",
|
|
47
|
+
"weight": 2,
|
|
48
|
+
"properties": {
|
|
49
|
+
amount: weighNumRange(5, 500, .25),
|
|
50
|
+
currency: ["USD", "USD", "USD", "CAD", "EUR", "EUR", "BTC", "BTC", "ETH", "JPY"],
|
|
51
|
+
cart: makeProducts(12),
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
"event": "add to cart",
|
|
56
|
+
"weight": 4,
|
|
57
|
+
"properties": {
|
|
58
|
+
amount: weighNumRange(5, 500, .25),
|
|
59
|
+
qty: integer(1, 5),
|
|
60
|
+
product_id: weighNumRange(1, 1000, 1.4)
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
"event": "page view",
|
|
65
|
+
"weight": 10,
|
|
66
|
+
"properties": {
|
|
67
|
+
page: ["/", "/", "/", "/learn-more", "/pricing", "/contact", "/about", "/careers", "/sign-up", "/login", "/app", "/app", "/app", "/app"],
|
|
68
|
+
utm_source: ["$organic", "$organic", "$organic", "$organic", "google", "google", "google", "facebook", "facebook", "twitter", "linkedin"],
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
"event": "watch video",
|
|
73
|
+
"weight": 8,
|
|
74
|
+
"properties": {
|
|
75
|
+
category: ["funny", "educational", "inspirational", "music", "news", "sports", "cooking", "DIY", "travel", "gaming"],
|
|
76
|
+
hashTags: makeHashTags,
|
|
77
|
+
watchTimeSec: weighNumRange(10, 600, .25,),
|
|
78
|
+
quality: ["2160p", "1440p", "1080p", "720p", "480p", "360p", "240p"],
|
|
79
|
+
format: ["mp4", "avi", "mov", "mpg"],
|
|
80
|
+
video_id: weighNumRange(1, 50000, 1.4),
|
|
81
|
+
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
"event": "comment",
|
|
86
|
+
"weight": 2,
|
|
87
|
+
"properties": {
|
|
88
|
+
length: weighNumRange(1, 500, .25),
|
|
89
|
+
video_id: weighNumRange(1, 50000, 1.4),
|
|
90
|
+
has_replies: [true, false, false, false, false],
|
|
91
|
+
has_photo: [true, false, false, false, false],
|
|
92
|
+
|
|
93
|
+
}
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
"event": "save video",
|
|
97
|
+
"weight": 4,
|
|
98
|
+
"properties": {
|
|
99
|
+
video_id: weighNumRange(1, 50000, 1.4),
|
|
100
|
+
ui_control: ["toolbar", "menu", "keyboard"]
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
}
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
"event": "view item",
|
|
107
|
+
"weight": 8,
|
|
108
|
+
"properties": {
|
|
109
|
+
product_id: weighNumRange(1, 24, 3),
|
|
110
|
+
colors: ["light", "dark", "custom", "dark"]
|
|
111
|
+
}
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
"event": "save item",
|
|
115
|
+
"weight": 5,
|
|
116
|
+
"properties": {
|
|
117
|
+
product_id: weighNumRange(1, 1000, 12),
|
|
118
|
+
colors: ["light", "dark", "custom", "dark"]
|
|
119
|
+
}
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
"event": "support ticket",
|
|
123
|
+
"weight": 2,
|
|
124
|
+
"properties": {
|
|
125
|
+
product_id: weighNumRange(1, 1000, .6),
|
|
126
|
+
description: chance.sentence.bind(chance),
|
|
127
|
+
severity: ["low", "medium", "high"],
|
|
128
|
+
ticket_id: chance.guid.bind(chance)
|
|
129
|
+
}
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
"event": "sign up",
|
|
133
|
+
"isFirstEvent": true,
|
|
134
|
+
"weight": 0,
|
|
135
|
+
"properties": {
|
|
136
|
+
plan: ["free", "free", "free", "free", "basic", "basic", "basic", "premium", "premium", "enterprise"],
|
|
137
|
+
dateOfRenewal: date(100, false),
|
|
138
|
+
codewords: u.makeName,
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
],
|
|
142
|
+
superProps: {
|
|
143
|
+
linked_device: deviceAttributes()
|
|
144
|
+
// emotions: generateEmoji(),
|
|
145
|
+
|
|
146
|
+
},
|
|
147
|
+
/*
|
|
148
|
+
user properties work the same as event properties
|
|
149
|
+
each key should be an array or function reference
|
|
150
|
+
*/
|
|
151
|
+
userProps: {
|
|
152
|
+
title: chance.profession.bind(chance),
|
|
153
|
+
luckyNumber: weighNumRange(42, 420),
|
|
154
|
+
experiment: designExperiment(),
|
|
155
|
+
spiritAnimal: ["unicorn", "dragon", "phoenix", "sasquatch", "yeti", "kraken", "jackalope", "thunderbird", "mothman", "nessie", "chupacabra", "jersey devil", "bigfoot", "weindgo", "bunyip", "mokele-mbembe", "tatzelwurm", "megalodon"],
|
|
156
|
+
timezone: chance.timezone.bind(chance), // ["America/New_York", "America/Los_Angeles", "America/Chicago", "America/Denver", "America/Phoenix", "America/Anchorage", "Pacific/Honolulu"]
|
|
157
|
+
ip: chance.ip.bind(chance),
|
|
158
|
+
lastCart: makeProducts(5),
|
|
159
|
+
|
|
160
|
+
},
|
|
161
|
+
|
|
162
|
+
/** each generates it's own table */
|
|
163
|
+
scdProps: {
|
|
164
|
+
role: {
|
|
165
|
+
type: "user",
|
|
166
|
+
frequency: "week",
|
|
167
|
+
values: ["admin", "collaborator", "user", "view only", "no access"],
|
|
168
|
+
timing: 'fuzzy',
|
|
169
|
+
max: 10
|
|
170
|
+
},
|
|
171
|
+
NPS: {
|
|
172
|
+
type: "user",
|
|
173
|
+
frequency: "day",
|
|
174
|
+
values: weighNumRange(1, 10, 2, 150),
|
|
175
|
+
timing: 'fuzzy',
|
|
176
|
+
max: 10
|
|
177
|
+
},
|
|
178
|
+
MRR: {
|
|
179
|
+
type: "company_id",
|
|
180
|
+
frequency: "month",
|
|
181
|
+
values: weighNumRange(0, 10000, .15),
|
|
182
|
+
timing: 'fixed',
|
|
183
|
+
max: 10
|
|
184
|
+
},
|
|
185
|
+
AccountHealthScore: {
|
|
186
|
+
type: "company_id",
|
|
187
|
+
frequency: "week",
|
|
188
|
+
values: weighNumRange(1, 10, .15),
|
|
189
|
+
timing: 'fixed',
|
|
190
|
+
max: 40
|
|
191
|
+
},
|
|
192
|
+
plan: {
|
|
193
|
+
type: "company_id",
|
|
194
|
+
frequency: "month",
|
|
195
|
+
values: ["free", "basic", "premium", "enterprise"],
|
|
196
|
+
timing: 'fixed',
|
|
197
|
+
max: 10
|
|
198
|
+
}
|
|
199
|
+
},
|
|
200
|
+
|
|
201
|
+
mirrorProps: {
|
|
202
|
+
isBot: { events: "*", values: [false, false, false, false, true] },
|
|
203
|
+
profit: { events: ["checkout"], values: [4, 2, 42, 420] },
|
|
204
|
+
watchTimeSec: {
|
|
205
|
+
events: ["watch video"],
|
|
206
|
+
values: weighNumRange(50, 1200, 2)
|
|
207
|
+
}
|
|
208
|
+
},
|
|
209
|
+
|
|
210
|
+
/*
|
|
211
|
+
for group analytics keys, we need an array of arrays [[],[],[]]
|
|
212
|
+
each pair represents a group_key and the number of profiles for that key
|
|
213
|
+
*/
|
|
214
|
+
groupKeys: [
|
|
215
|
+
['company_id', 500, []],
|
|
216
|
+
['room_id', 10000, ["save video", "comment", "watch video"]],
|
|
217
|
+
|
|
218
|
+
],
|
|
219
|
+
groupProps: {
|
|
220
|
+
company_id: {
|
|
221
|
+
name: () => { return chance.company(); },
|
|
222
|
+
email: () => { return `CSM: ${chance.pickone(["AK", "Jessica", "Michelle", "Dana", "Brian", "Dave"])}`; },
|
|
223
|
+
"# of employees": weighNumRange(3, 10000),
|
|
224
|
+
"industry": ["tech", "finance", "healthcare", "education", "government", "non-profit"],
|
|
225
|
+
"segment": ["enterprise", "SMB", "mid-market"],
|
|
226
|
+
"products": [["core"], ["core"], ["core", "add-ons"], ["core", "pro-serve"], ["core", "add-ons", "pro-serve"], ["core", "BAA", "enterprise"], ["free"], ["free"], ["free", "addons"]],
|
|
227
|
+
},
|
|
228
|
+
room_id: {
|
|
229
|
+
name: () => { return `#${chance.word({ length: integer(4, 24), capitalize: true })}`; },
|
|
230
|
+
email: ["public", "private"],
|
|
231
|
+
"room provider": ["partner", "core", "core", "core"],
|
|
232
|
+
"room capacity": weighNumRange(3, 1000000),
|
|
233
|
+
"isPublic": [true, false, false, false, false],
|
|
234
|
+
"country": chance.country.bind(chance),
|
|
235
|
+
"isVerified": [true, true, false, false, false],
|
|
236
|
+
}
|
|
237
|
+
},
|
|
238
|
+
groupEvents: [{
|
|
239
|
+
attribute_to_user: false,
|
|
240
|
+
event: "card charged",
|
|
241
|
+
weight: 1,
|
|
242
|
+
frequency: 30,
|
|
243
|
+
group_key: "company_id",
|
|
244
|
+
group_size: 500,
|
|
245
|
+
properties: {
|
|
246
|
+
amount: weighNumRange(5, 500, .25),
|
|
247
|
+
currency: ["USD", "USD", "USD", "CAD", "EUR", "EUR", "BTC", "BTC", "ETH", "JPY"],
|
|
248
|
+
plan: ["basic", "premium", "enterprise"],
|
|
249
|
+
"payment method": []
|
|
250
|
+
}
|
|
251
|
+
}],
|
|
252
|
+
|
|
253
|
+
lookupTables: [
|
|
254
|
+
{
|
|
255
|
+
key: "product_id",
|
|
256
|
+
entries: 1000,
|
|
257
|
+
attributes: {
|
|
258
|
+
category: [
|
|
259
|
+
"Books", "Movies", "Music", "Games", "Electronics", "Computers", "Smart Home", "Home", "Garden & Tools", "Pet Supplies", "Food & Grocery", "Beauty", "Health", "Toys", "Kids", "Baby", "Handmade", "Sports", "Outdoors", "Automotive", "Industrial", "Entertainment", "Art"
|
|
260
|
+
],
|
|
261
|
+
"demand": ["high", "medium", "medium", "low"],
|
|
262
|
+
"supply": ["high", "medium", "medium", "low"],
|
|
263
|
+
"manufacturer": chance.company.bind(chance),
|
|
264
|
+
"price": weighNumRange(5, 500, .25),
|
|
265
|
+
"rating": weighNumRange(1, 5),
|
|
266
|
+
"reviews": weighNumRange(0, 35)
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
},
|
|
270
|
+
{
|
|
271
|
+
key: "video_id",
|
|
272
|
+
entries: 50000,
|
|
273
|
+
attributes: {
|
|
274
|
+
isFlagged: [true, false, false, false, false],
|
|
275
|
+
copyright: ["all rights reserved", "creative commons", "creative commons", "public domain", "fair use"],
|
|
276
|
+
uploader_id: chance.guid.bind(chance),
|
|
277
|
+
"uploader influence": ["low", "low", "low", "medium", "medium", "high"],
|
|
278
|
+
thumbs: weighNumRange(0, 35),
|
|
279
|
+
rating: ["G", "PG", "PG-13", "R", "NC-17", "PG-13", "R", "NC-17", "R", "PG", "PG"]
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
}
|
|
283
|
+
],
|
|
284
|
+
|
|
285
|
+
hook: function (record, type, meta) {
|
|
286
|
+
// event hook: weekend watch time boost ā videos watched on weekends get 1.5x duration
|
|
287
|
+
if (type === "event") {
|
|
288
|
+
if (record.event === "watch video" && record.time) {
|
|
289
|
+
const day = dayjs(record.time).day();
|
|
290
|
+
if (day === 0 || day === 6) {
|
|
291
|
+
record.watchTimeSec = Math.round((record.watchTimeSec || 60) * 1.5);
|
|
292
|
+
record.is_weekend = true;
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
// support tickets on high-severity get escalated flag
|
|
296
|
+
if (record.event === "support ticket" && record.severity === "high") {
|
|
297
|
+
record.escalated = true;
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
// everything hook: simulate cart abandonment ā users who "add to cart" but never "checkout" lose their last add-to-cart
|
|
302
|
+
if (type === "everything") {
|
|
303
|
+
const hasCheckout = record.some(e => e.event === "checkout");
|
|
304
|
+
const hasAddToCart = record.some(e => e.event === "add to cart");
|
|
305
|
+
if (hasAddToCart && !hasCheckout) {
|
|
306
|
+
// mark all their add-to-cart events as abandoned
|
|
307
|
+
for (const e of record) {
|
|
308
|
+
if (e.event === "add to cart") {
|
|
309
|
+
e.abandoned = true;
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
return record;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
return record;
|
|
317
|
+
}
|
|
318
|
+
};
|
|
319
|
+
|
|
320
|
+
|
|
321
|
+
|
|
322
|
+
function makeHashTags() {
|
|
323
|
+
const possibleHashtags = [];
|
|
324
|
+
for (let i = 0; i < 20; i++) {
|
|
325
|
+
possibleHashtags.push('#' + u.makeName(2, ''));
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
const numHashtags = integer(integer(1, 5), integer(5, 10));
|
|
329
|
+
const hashtags = [];
|
|
330
|
+
for (let i = 0; i < numHashtags; i++) {
|
|
331
|
+
hashtags.push(chance.pickone(possibleHashtags));
|
|
332
|
+
}
|
|
333
|
+
return [hashtags];
|
|
334
|
+
};
|
|
335
|
+
|
|
336
|
+
function makeProducts(maxItems = 10) {
|
|
337
|
+
|
|
338
|
+
return function () {
|
|
339
|
+
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"];
|
|
340
|
+
const slugs = ['/sale/', '/featured/', '/home/', '/search/', '/wishlist/', '/'];
|
|
341
|
+
const assetExtension = ['.png', '.jpg', '.jpeg', '.heic', '.mp4', '.mov', '.avi'];
|
|
342
|
+
const data = [];
|
|
343
|
+
const numOfItems = integer(1, 12);
|
|
344
|
+
|
|
345
|
+
for (var i = 0; i < numOfItems; i++) {
|
|
346
|
+
const category = chance.pickone(categories);
|
|
347
|
+
const slug = chance.pickone(slugs);
|
|
348
|
+
const asset = chance.pickone(assetExtension);
|
|
349
|
+
const product_id = chance.guid();
|
|
350
|
+
const price = integer(1, 300);
|
|
351
|
+
const quantity = integer(1, 5);
|
|
352
|
+
|
|
353
|
+
const item = {
|
|
354
|
+
product_id: product_id,
|
|
355
|
+
sku: integer(11111, 99999),
|
|
356
|
+
amount: price,
|
|
357
|
+
quantity: quantity,
|
|
358
|
+
value: price * quantity,
|
|
359
|
+
featured: chance.pickone([true, false]),
|
|
360
|
+
category: category,
|
|
361
|
+
urlSlug: slug + category,
|
|
362
|
+
asset: `${category}-${integer(1, 20)}${asset}`
|
|
363
|
+
};
|
|
364
|
+
|
|
365
|
+
data.push(item);
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
return () => [data];
|
|
369
|
+
};
|
|
370
|
+
};
|
|
371
|
+
|
|
372
|
+
|
|
373
|
+
function designExperiment() {
|
|
374
|
+
return function () {
|
|
375
|
+
const variants = ["A", "B", "C", "Control"];
|
|
376
|
+
const variant = chance.pickone(variants);
|
|
377
|
+
const experiments = ["no password", "social sign in", "new tutorial", "new search"];
|
|
378
|
+
const experiment = chance.pickone(experiments);
|
|
379
|
+
const multi_variates = ["A/B", "A/B/C", "A/B/C/D", "Control"];
|
|
380
|
+
const multi_variate = chance.pickone(multi_variates);
|
|
381
|
+
const impression_id = chance.guid();
|
|
382
|
+
|
|
383
|
+
|
|
384
|
+
|
|
385
|
+
const chosen = {
|
|
386
|
+
variant,
|
|
387
|
+
experiment,
|
|
388
|
+
multi_variate,
|
|
389
|
+
impression_id
|
|
390
|
+
};
|
|
391
|
+
|
|
392
|
+
return [chosen];
|
|
393
|
+
};
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
function deviceAttributes(isMobile = false) {
|
|
397
|
+
return function () {
|
|
398
|
+
let devices = ["desktop", "laptop", "desktop", "laptop", "desktop", "laptop", "other"];
|
|
399
|
+
if (isMobile) devices = [...devices, "mobile", "mobile", "mobile", "tablet"];
|
|
400
|
+
const device = chance.pickone(devices);
|
|
401
|
+
let oses = ["Windows", "macOS", "Windows", "macOS", "macOS", "Linux", "Windows", "macOS", "Windows", "macOS", "macOS", "TempleOS"];
|
|
402
|
+
if (isMobile) oses = [...oses, "iOS", "Android", "iOS", "Android"];
|
|
403
|
+
const os = chance.pickone(oses);
|
|
404
|
+
const browser = chance.pickone(["Chrome", "Firefox", "Safari", "Edge", "Opera", "IE", "Brave", "Vivaldi"]);
|
|
405
|
+
const version = chance.integer({ min: 1, max: 15 });
|
|
406
|
+
const resolution = chance.pickone(["1920x1080", "1280x720", "1024x768", "800x600", "640x480"]);
|
|
407
|
+
const language = chance.pickone(["en-US", "en-US", "en-US", "en-GB", "es", "es", "fr", "de", "it", "ja", "zh", "ru"]);
|
|
408
|
+
|
|
409
|
+
const chosen = {
|
|
410
|
+
platform: device,
|
|
411
|
+
os,
|
|
412
|
+
browser,
|
|
413
|
+
version,
|
|
414
|
+
resolution,
|
|
415
|
+
language
|
|
416
|
+
};
|
|
417
|
+
|
|
418
|
+
return chosen;
|
|
419
|
+
|
|
420
|
+
};
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
|
|
424
|
+
|
|
425
|
+
|
|
426
|
+
|
|
427
|
+
|
|
428
|
+
export default config;
|
package/entry.js
CHANGED
|
@@ -59,7 +59,7 @@ import getCliParams from './lib/cli/cli.js';
|
|
|
59
59
|
process.exit(0);
|
|
60
60
|
} catch (error) {
|
|
61
61
|
console.error(`\nā Job failed: ${error.message}`);
|
|
62
|
-
if (process.env.NODE_ENV
|
|
62
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
63
63
|
console.error(error.stack);
|
|
64
64
|
}
|
|
65
65
|
process.exit(1);
|
package/index.js
CHANGED
|
@@ -34,6 +34,8 @@ import dayjs from "dayjs";
|
|
|
34
34
|
import utc from "dayjs/plugin/utc.js";
|
|
35
35
|
import { timer } from 'ak-tools';
|
|
36
36
|
import { existsSync } from 'fs';
|
|
37
|
+
import path from 'path';
|
|
38
|
+
import { pathToFileURL } from 'url';
|
|
37
39
|
import { dataLogger as logger } from './lib/utils/logger.js';
|
|
38
40
|
|
|
39
41
|
// Initialize dayjs and time constants
|
|
@@ -123,8 +125,11 @@ async function main(config) {
|
|
|
123
125
|
console.log(`\nš Loading dungeon config from: ${firstArg}`);
|
|
124
126
|
}
|
|
125
127
|
try {
|
|
126
|
-
const
|
|
127
|
-
|
|
128
|
+
const absolutePath = path.resolve(firstArg);
|
|
129
|
+
const dungeonConfig = await import(pathToFileURL(absolutePath).href);
|
|
130
|
+
const loaded = dungeonConfig.default || dungeonConfig;
|
|
131
|
+
// Merge: dungeon config provides defaults; CLI flags override
|
|
132
|
+
config = { ...loaded, ...config };
|
|
128
133
|
} catch (error) {
|
|
129
134
|
console.error(`\nā Error loading dungeon config from ${firstArg}: ${error.message}`);
|
|
130
135
|
throw error;
|
package/lib/cli/cli.js
CHANGED
|
@@ -93,21 +93,18 @@ DATA MODEL: https://github.com/ak--47/make-mp-data/blob/main/default.js
|
|
|
93
93
|
})
|
|
94
94
|
.option("region", {
|
|
95
95
|
demandOption: false,
|
|
96
|
-
default: 'US',
|
|
97
96
|
alias: 'r',
|
|
98
|
-
describe: 'either US or EU or IN',
|
|
97
|
+
describe: 'either US or EU or IN (defaults to dungeon config or US)',
|
|
99
98
|
type: 'string'
|
|
100
99
|
})
|
|
101
100
|
.option('concurrency', {
|
|
102
101
|
alias: 'conn',
|
|
103
|
-
default: 10,
|
|
104
102
|
demandOption: false,
|
|
105
|
-
describe: 'concurrency level for data generation',
|
|
103
|
+
describe: 'concurrency level for data generation (defaults to dungeon config)',
|
|
106
104
|
type: 'number'
|
|
107
105
|
})
|
|
108
106
|
.options("complex", {
|
|
109
107
|
demandOption: false,
|
|
110
|
-
default: false,
|
|
111
108
|
describe: 'use complex data model (model all entities)',
|
|
112
109
|
alias: 'c',
|
|
113
110
|
type: 'boolean',
|
|
@@ -115,7 +112,6 @@ DATA MODEL: https://github.com/ak--47/make-mp-data/blob/main/default.js
|
|
|
115
112
|
})
|
|
116
113
|
.options("simple", {
|
|
117
114
|
demandOption: false,
|
|
118
|
-
default: false,
|
|
119
115
|
describe: 'use simple data model (basic events and users)',
|
|
120
116
|
alias: 'simp',
|
|
121
117
|
type: 'boolean',
|
|
@@ -123,7 +119,6 @@ DATA MODEL: https://github.com/ak--47/make-mp-data/blob/main/default.js
|
|
|
123
119
|
})
|
|
124
120
|
.options("sanity", {
|
|
125
121
|
demandOption: false,
|
|
126
|
-
default: false,
|
|
127
122
|
describe: 'run sanity checks on the generated data',
|
|
128
123
|
alias: 'san',
|
|
129
124
|
type: 'boolean',
|
|
@@ -131,15 +126,13 @@ DATA MODEL: https://github.com/ak--47/make-mp-data/blob/main/default.js
|
|
|
131
126
|
})
|
|
132
127
|
.option("writeToDisk", {
|
|
133
128
|
demandOption: false,
|
|
134
|
-
|
|
135
|
-
describe: 'write data to disk',
|
|
129
|
+
describe: 'write data to disk (CLI defaults to true)',
|
|
136
130
|
alias: 'w',
|
|
137
131
|
type: 'boolean',
|
|
138
132
|
coerce: boolCoerce
|
|
139
133
|
})
|
|
140
134
|
.option("hasSessionIds", {
|
|
141
135
|
demandOption: false,
|
|
142
|
-
default: false,
|
|
143
136
|
describe: 'create session ids in the data',
|
|
144
137
|
alias: 'sid',
|
|
145
138
|
type: 'boolean',
|
|
@@ -147,7 +140,6 @@ DATA MODEL: https://github.com/ak--47/make-mp-data/blob/main/default.js
|
|
|
147
140
|
})
|
|
148
141
|
.option("hasAnonIds", {
|
|
149
142
|
demandOption: false,
|
|
150
|
-
default: false,
|
|
151
143
|
describe: 'create anonymous ids in the data',
|
|
152
144
|
alias: 'aid',
|
|
153
145
|
type: 'boolean',
|
|
@@ -341,18 +341,15 @@ function transformSCDPropsWithoutCredentials(config) {
|
|
|
341
341
|
|
|
342
342
|
// Missing credentials - handle based on job type
|
|
343
343
|
if (!isUIJob) {
|
|
344
|
-
// For programmatic/CLI usage
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
'
|
|
349
|
-
'
|
|
350
|
-
'
|
|
351
|
-
' - projectId: Your Mixpanel project ID\n' +
|
|
352
|
-
'Without these credentials, SCD data cannot be imported to Mixpanel.'
|
|
344
|
+
// For programmatic/CLI usage: warn but continue. SCD files still generate;
|
|
345
|
+
// mixpanel-sender already gates SCD import on credential presence.
|
|
346
|
+
if (token && config.verbose !== false) {
|
|
347
|
+
console.warn(
|
|
348
|
+
'ā ļø SCD properties configured but service credentials missing. ' +
|
|
349
|
+
'SCD files will be generated but NOT imported to Mixpanel. ' +
|
|
350
|
+
'Provide serviceAccount + serviceSecret + projectId to enable SCD import.'
|
|
353
351
|
);
|
|
354
352
|
}
|
|
355
|
-
// If not sending to Mixpanel (no token), allow generation for testing
|
|
356
353
|
return;
|
|
357
354
|
}
|
|
358
355
|
|