make-mp-data 1.5.1 → 1.5.3
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/.gcloudignore +17 -0
- package/.vscode/launch.json +37 -14
- package/.vscode/settings.json +2 -0
- package/.vscode/tasks.json +12 -0
- package/components/ai.js +93 -0
- package/components/chart.js +14 -0
- package/components/cli.js +8 -2
- package/components/project.js +11 -0
- package/components/prompt.txt +98 -0
- package/components/utils.js +126 -5
- package/{schemas → dungeons}/adspend.js +1 -1
- package/{schemas → dungeons}/anon.js +1 -1
- package/{schemas → dungeons}/big.js +1 -1
- package/{schemas → dungeons}/business.js +1 -1
- package/{schemas → dungeons}/complex.js +9 -9
- package/dungeons/foobar.js +241 -0
- package/{schemas → dungeons}/funnels.js +2 -3
- package/dungeons/gaming.js +314 -0
- package/{schemas → dungeons}/mirror.js +1 -1
- package/{schemas → dungeons}/sanity.js +1 -1
- package/dungeons/scd.js +205 -0
- package/dungeons/session-replay.js +175 -0
- package/{schemas → dungeons}/simple.js +1 -1
- package/dungeons/userAgent.js +190 -0
- package/env.yaml +1 -0
- package/index.js +453 -154
- package/package.json +9 -5
- package/scripts/deploy.sh +11 -0
- package/scripts/new-dungeon.sh +10 -4
- package/tests/benchmark/concurrency.mjs +2 -2
- package/tests/cli.test.js +121 -0
- package/tests/e2e.test.js +134 -186
- package/tests/int.test.js +3 -2
- package/tests/jest.config.js +8 -0
- package/tests/unit.test.js +1 -1
- package/tsconfig.json +1 -1
- package/types.d.ts +40 -9
- package/schemas/foobar.js +0 -125
- package/schemas/session-replay.js +0 -136
- /package/dungeons/{.gitkeep → customers/.gitkeep} +0 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "make-mp-data",
|
|
3
|
-
"version": "1.5.
|
|
3
|
+
"version": "1.5.03",
|
|
4
4
|
"description": "builds all mixpanel primitives for a given project",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "types.d.ts",
|
|
@@ -9,13 +9,15 @@
|
|
|
9
9
|
"dev": "nodemon scratch.mjs --ignore ./data/*",
|
|
10
10
|
"prune": "rm -f ./data/* && rm -f ./tmp/* && rm -f vscode-profile-*",
|
|
11
11
|
"post": "npm publish",
|
|
12
|
+
"deps": "./scripts/update-deps.sh",
|
|
12
13
|
"test": "NODE_ENV=test jest --runInBand",
|
|
13
14
|
"coverage": "node --no-warnings --experimental-vm-modules node_modules/jest/bin/jest.js --coverage && open ./tests/coverage/lcov-report/index.html",
|
|
14
|
-
"update:deps": "./scripts/update-deps.sh",
|
|
15
15
|
"new:dungeon": "./scripts/new-dungeon.sh",
|
|
16
16
|
"new:project": "node ./scripts/new-project.mjs",
|
|
17
17
|
"exp:benchmark": "node --no-warnings --experimental-vm-modules ./tests/benchmark/concurrency.mjs",
|
|
18
|
-
"exp:soup": "node ./tests/testSoup.mjs"
|
|
18
|
+
"exp:soup": "node ./tests/testSoup.mjs",
|
|
19
|
+
"func:local": "functions-framework --target=entry",
|
|
20
|
+
"func:deploy": "./scripts/deploy.sh"
|
|
19
21
|
},
|
|
20
22
|
"repository": {
|
|
21
23
|
"type": "git",
|
|
@@ -43,14 +45,16 @@
|
|
|
43
45
|
},
|
|
44
46
|
"homepage": "https://github.com/ak--47/make-mp-data#readme",
|
|
45
47
|
"dependencies": {
|
|
46
|
-
"
|
|
48
|
+
"@google-cloud/functions-framework": "^3.4.2",
|
|
49
|
+
"@google/generative-ai": "^0.16.0",
|
|
50
|
+
"ak-fetch": "^1.0.4",
|
|
47
51
|
"ak-tools": "^1.0.64",
|
|
48
52
|
"chance": "^1.1.11",
|
|
49
53
|
"chart.js": "^3.9.1",
|
|
50
54
|
"chartjs-node-canvas": "^4.1.6",
|
|
51
55
|
"dayjs": "^1.11.11",
|
|
52
56
|
"dotenv": "^16.4.5",
|
|
53
|
-
"mixpanel-import": "^2.
|
|
57
|
+
"mixpanel-import": "^2.6.4",
|
|
54
58
|
"p-limit": "^3.1.0",
|
|
55
59
|
"yargs": "^17.7.2"
|
|
56
60
|
},
|
package/scripts/new-dungeon.sh
CHANGED
|
@@ -19,7 +19,9 @@ const chance = u.initChance(SEED);
|
|
|
19
19
|
const num_users = 25_000
|
|
20
20
|
const days = 100
|
|
21
21
|
|
|
22
|
-
/** @
|
|
22
|
+
/** @typedef {import("../types.d.ts").Dungeon} Config */
|
|
23
|
+
|
|
24
|
+
/** @type {Config} */
|
|
23
25
|
const config = {
|
|
24
26
|
token: "",
|
|
25
27
|
seed: SEED,
|
|
@@ -42,8 +44,8 @@ const config = {
|
|
|
42
44
|
hasAvatar: true,
|
|
43
45
|
makeChart: false,
|
|
44
46
|
|
|
45
|
-
batchSize:
|
|
46
|
-
concurrency:
|
|
47
|
+
batchSize: 1_500_000,
|
|
48
|
+
concurrency: 1,
|
|
47
49
|
writeToDisk: false,
|
|
48
50
|
|
|
49
51
|
funnels: [],
|
|
@@ -56,7 +58,7 @@ const config = {
|
|
|
56
58
|
groupProps: {},
|
|
57
59
|
lookupTables: [],
|
|
58
60
|
hook: function (record, type, meta) {
|
|
59
|
-
const NOW = dayjs
|
|
61
|
+
const NOW = dayjs();
|
|
60
62
|
|
|
61
63
|
if (type === "event") {
|
|
62
64
|
const EVENT_TIME = dayjs(record.time);
|
|
@@ -78,6 +80,10 @@ const config = {
|
|
|
78
80
|
|
|
79
81
|
}
|
|
80
82
|
|
|
83
|
+
if (type === "everything") {
|
|
84
|
+
|
|
85
|
+
}
|
|
86
|
+
|
|
81
87
|
return record;
|
|
82
88
|
}
|
|
83
89
|
};
|
|
@@ -12,9 +12,9 @@ TO DOs
|
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
import main from "../../index.js";
|
|
15
|
-
import simple from '../../
|
|
15
|
+
import simple from '../../dungeons/simple.js';
|
|
16
16
|
|
|
17
|
-
/** @typedef {import('../../types').
|
|
17
|
+
/** @typedef {import('../../types').Dungeon} Config */
|
|
18
18
|
|
|
19
19
|
/** @type {Config} */
|
|
20
20
|
const noWrites = {
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
const generate = require('../index.js');
|
|
2
|
+
require('dotenv').config();
|
|
3
|
+
const { execSync } = require("child_process");
|
|
4
|
+
const u = require('ak-tools');
|
|
5
|
+
const Papa = require('papaparse');
|
|
6
|
+
|
|
7
|
+
const simple = require('../dungeons/simple.js');
|
|
8
|
+
const complex = require('../dungeons/complex.js');
|
|
9
|
+
const anon = require('../dungeons/anon.js');
|
|
10
|
+
const funnels = require('../dungeons/funnels.js');
|
|
11
|
+
const foobar = require('../dungeons/foobar.js');
|
|
12
|
+
const mirror = require('../dungeons/mirror.js');
|
|
13
|
+
const adspend = require('../dungeons/adspend.js');
|
|
14
|
+
const scd = require('../dungeons/scd.js');
|
|
15
|
+
|
|
16
|
+
const timeout = 600000;
|
|
17
|
+
const testToken = process.env.TEST_TOKEN || "hello token!";
|
|
18
|
+
|
|
19
|
+
describe('cli', () => {
|
|
20
|
+
|
|
21
|
+
test('sanity check', async () => {
|
|
22
|
+
console.log('SANITY TEST');
|
|
23
|
+
const run = execSync(`node ./index.js`);
|
|
24
|
+
const ending = `enjoy your data! :)`;
|
|
25
|
+
expect(run.toString().trim().endsWith(ending)).toBe(true);
|
|
26
|
+
const files = (await u.ls('./data')).filter(a => a.includes('.csv'));
|
|
27
|
+
expect(files.length).toBe(2);
|
|
28
|
+
const users = files.filter(a => a.includes('USERS'));
|
|
29
|
+
const events = files.filter(a => a.includes('EVENTS'));
|
|
30
|
+
expect(users.length).toBe(1);
|
|
31
|
+
expect(events.length).toBe(1);
|
|
32
|
+
const eventData = (await u.load(events[0])).trim();
|
|
33
|
+
const userProfilesData = (await u.load(users[0])).trim();
|
|
34
|
+
const parsedEvents = Papa.parse(eventData, { header: true }).data;
|
|
35
|
+
const parsedUsers = Papa.parse(userProfilesData, { header: true }).data;
|
|
36
|
+
expect(parsedEvents.length).toBeGreaterThan(42000);
|
|
37
|
+
expect(parsedUsers.length).toBeGreaterThan(420);
|
|
38
|
+
expect(parsedUsers.every(u => u.distinct_id)).toBe(true);
|
|
39
|
+
expect(parsedEvents.every(e => e.event)).toBe(true);
|
|
40
|
+
expect(parsedEvents.every(e => e.time)).toBe(true);
|
|
41
|
+
expect(parsedEvents.every(e => e.insert_id)).toBe(true);
|
|
42
|
+
expect(parsedEvents.every(e => e.device_id || e.user_id)).toBe(true);
|
|
43
|
+
expect(parsedUsers.every(u => u.name)).toBe(true);
|
|
44
|
+
expect(parsedUsers.every(u => u.email)).toBe(true);
|
|
45
|
+
// expect(parsedUsers.every(u => u.created)).toBe(true);
|
|
46
|
+
expect(parsedUsers.every(u => u.avatar)).toBe(false);
|
|
47
|
+
expect(parsedEvents.every(e => validateEvent(e))).toBe(true);
|
|
48
|
+
expect(parsedUsers.every(u => validateUser(u))).toBe(true);
|
|
49
|
+
}, timeout);
|
|
50
|
+
|
|
51
|
+
test('no args', async () => {
|
|
52
|
+
console.log('BARE CLI TEST');
|
|
53
|
+
const run = execSync(`node ./index.js --numEvents 1000 --numUsers 100`);
|
|
54
|
+
expect(run.toString().trim().includes('enjoy your data! :)')).toBe(true);
|
|
55
|
+
const csvs = (await u.ls('./data')).filter(a => a.includes('.csv'));
|
|
56
|
+
expect(csvs.length).toBe(2);
|
|
57
|
+
|
|
58
|
+
}, timeout);
|
|
59
|
+
|
|
60
|
+
test('--complex', async () => {
|
|
61
|
+
console.log('COMPLEX CLI TEST');
|
|
62
|
+
const run = execSync(`node ./index.js --numEvents 1000 --numUsers 100 --seed "deal with it" --complex`, { stdio: "ignore" });
|
|
63
|
+
const csvs = (await u.ls('./data')).filter(a => a.includes('.json'));
|
|
64
|
+
expect(csvs.length).toBe(8);
|
|
65
|
+
|
|
66
|
+
}, timeout);
|
|
67
|
+
|
|
68
|
+
test('--simple', async () => {
|
|
69
|
+
console.log('SIMPLE CLI TEST');
|
|
70
|
+
const run = execSync(`node ./index.js --numEvents 1000 --numUsers 100 --seed "deal with it" --simple`);
|
|
71
|
+
expect(run.toString().trim().includes('enjoy your data! :)')).toBe(true);
|
|
72
|
+
const csvs = (await u.ls('./data')).filter(a => a.includes('.csv'));
|
|
73
|
+
expect(csvs.length).toBe(2);
|
|
74
|
+
|
|
75
|
+
}, timeout);
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
beforeEach(() => {
|
|
81
|
+
clearData();
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
afterEach(() => {
|
|
85
|
+
clearData();
|
|
86
|
+
});
|
|
87
|
+
function clearData() {
|
|
88
|
+
try {
|
|
89
|
+
console.log('clearing...');
|
|
90
|
+
execSync(`npm run prune`);
|
|
91
|
+
console.log('...files cleared 👍');
|
|
92
|
+
}
|
|
93
|
+
catch (err) {
|
|
94
|
+
console.log('error clearing files');
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function validateEvent(event) {
|
|
99
|
+
if (!event.event) return false;
|
|
100
|
+
if (!event.device_id && !event.user_id) return false;
|
|
101
|
+
if (!event.time) return false;
|
|
102
|
+
if (!event.insert_id) return false;
|
|
103
|
+
return true;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
function validateUser(user) {
|
|
108
|
+
if (!user.distinct_id) return false;
|
|
109
|
+
if (!user.name) return false;
|
|
110
|
+
if (!user.email) return false;
|
|
111
|
+
// if (!user.created) return false;
|
|
112
|
+
return true;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
function validTime(str) {
|
|
117
|
+
if (!str) return false;
|
|
118
|
+
if (str.startsWith('-')) return false;
|
|
119
|
+
if (!str.startsWith('20')) return false;
|
|
120
|
+
return true;
|
|
121
|
+
}
|
package/tests/e2e.test.js
CHANGED
|
@@ -9,13 +9,14 @@ const { execSync } = require("child_process");
|
|
|
9
9
|
const u = require('ak-tools');
|
|
10
10
|
const Papa = require('papaparse');
|
|
11
11
|
|
|
12
|
-
const simple = require('../
|
|
13
|
-
const complex = require('../
|
|
14
|
-
const anon = require('../
|
|
15
|
-
const funnels = require('../
|
|
16
|
-
const foobar = require('../
|
|
17
|
-
const mirror = require('../
|
|
18
|
-
const adspend = require('../
|
|
12
|
+
const simple = require('../dungeons/simple.js');
|
|
13
|
+
const complex = require('../dungeons/complex.js');
|
|
14
|
+
const anon = require('../dungeons/anon.js');
|
|
15
|
+
const funnels = require('../dungeons/funnels.js');
|
|
16
|
+
const foobar = require('../dungeons/foobar.js');
|
|
17
|
+
const mirror = require('../dungeons/mirror.js');
|
|
18
|
+
const adspend = require('../dungeons/adspend.js');
|
|
19
|
+
const scd = require('../dungeons/scd.js');
|
|
19
20
|
|
|
20
21
|
const timeout = 600000;
|
|
21
22
|
const testToken = process.env.TEST_TOKEN || "hello token!";
|
|
@@ -68,9 +69,6 @@ describe('module', () => {
|
|
|
68
69
|
expect(groupProfilesData[0]?.length).toBe(5000);
|
|
69
70
|
expect(groupProfilesData[1]?.length).toBe(500);
|
|
70
71
|
expect(groupProfilesData[2]?.length).toBe(50);
|
|
71
|
-
expect(scdTableData.length).toBe(2);
|
|
72
|
-
expect(scdTableData[0]?.length).toBeGreaterThan(200);
|
|
73
|
-
expect(scdTableData[1]?.length).toBeGreaterThan(200);
|
|
74
72
|
expect(userProfilesData.length).toBe(100);
|
|
75
73
|
|
|
76
74
|
}, timeout);
|
|
@@ -107,6 +105,31 @@ describe('module', () => {
|
|
|
107
105
|
}, timeout);
|
|
108
106
|
|
|
109
107
|
|
|
108
|
+
test('works as module (scd)', async () => {
|
|
109
|
+
console.log('MODULE TEST: scd');
|
|
110
|
+
scd;
|
|
111
|
+
const results = await generate({
|
|
112
|
+
...scd,
|
|
113
|
+
token: testToken,
|
|
114
|
+
serviceAccount: process.env.SERVICE_ACCOUNT,
|
|
115
|
+
projectId: process.env.PROJECT_ID,
|
|
116
|
+
serviceSecret: process.env.SERVICE_SECRET,
|
|
117
|
+
verbose: true, writeToDisk: false, numEvents: 100, numUsers: 10, seed: "deal with it"
|
|
118
|
+
});
|
|
119
|
+
const { importResults} = results;
|
|
120
|
+
const {MRR_scd, NPS_scd, plan_scd, role_scd} = importResults;
|
|
121
|
+
expect(MRR_scd.success).toBeGreaterThan(10);
|
|
122
|
+
expect(NPS_scd.success).toBeGreaterThan(10);
|
|
123
|
+
expect(plan_scd.success).toBeGreaterThan(10);
|
|
124
|
+
expect(role_scd.success).toBeGreaterThan(10);
|
|
125
|
+
expect(MRR_scd.failed).toBe(0);
|
|
126
|
+
expect(NPS_scd.failed).toBe(0);
|
|
127
|
+
expect(plan_scd.failed).toBe(0);
|
|
128
|
+
expect(role_scd.failed).toBe(0);
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
}, timeout);
|
|
132
|
+
|
|
110
133
|
test('fails with invalid configuration', async () => {
|
|
111
134
|
try {
|
|
112
135
|
await generate({ numUsers: -10 });
|
|
@@ -132,166 +155,106 @@ describe('module', () => {
|
|
|
132
155
|
|
|
133
156
|
});
|
|
134
157
|
|
|
135
|
-
describe('batching', () => {
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
});
|
|
234
|
-
|
|
235
|
-
describe('cli', () => {
|
|
236
|
-
|
|
237
|
-
test('sanity check', async () => {
|
|
238
|
-
console.log('SANITY TEST');
|
|
239
|
-
const run = execSync(`node ./index.js`);
|
|
240
|
-
const ending = `enjoy your data! :)`;
|
|
241
|
-
expect(run.toString().trim().endsWith(ending)).toBe(true);
|
|
242
|
-
const files = (await u.ls('./data')).filter(a => a.includes('.csv'));
|
|
243
|
-
expect(files.length).toBe(2);
|
|
244
|
-
const users = files.filter(a => a.includes('USERS'));
|
|
245
|
-
const events = files.filter(a => a.includes('EVENTS'));
|
|
246
|
-
expect(users.length).toBe(1);
|
|
247
|
-
expect(events.length).toBe(1);
|
|
248
|
-
const eventData = (await u.load(events[0])).trim();
|
|
249
|
-
const userProfilesData = (await u.load(users[0])).trim();
|
|
250
|
-
const parsedEvents = Papa.parse(eventData, { header: true }).data;
|
|
251
|
-
const parsedUsers = Papa.parse(userProfilesData, { header: true }).data;
|
|
252
|
-
expect(parsedEvents.length).toBeGreaterThan(42000);
|
|
253
|
-
expect(parsedUsers.length).toBeGreaterThan(420);
|
|
254
|
-
expect(parsedUsers.every(u => u.distinct_id)).toBe(true);
|
|
255
|
-
expect(parsedEvents.every(e => e.event)).toBe(true);
|
|
256
|
-
expect(parsedEvents.every(e => e.time)).toBe(true);
|
|
257
|
-
expect(parsedEvents.every(e => e.insert_id)).toBe(true);
|
|
258
|
-
expect(parsedEvents.every(e => e.device_id || e.user_id)).toBe(true);
|
|
259
|
-
expect(parsedUsers.every(u => u.name)).toBe(true);
|
|
260
|
-
expect(parsedUsers.every(u => u.email)).toBe(true);
|
|
261
|
-
expect(parsedUsers.every(u => u.created)).toBe(true);
|
|
262
|
-
expect(parsedUsers.every(u => u.avatar)).toBe(false);
|
|
263
|
-
expect(parsedEvents.every(e => validateEvent(e))).toBe(true);
|
|
264
|
-
expect(parsedUsers.every(u => validateUser(u))).toBe(true);
|
|
265
|
-
}, timeout);
|
|
266
|
-
|
|
267
|
-
test('no args', async () => {
|
|
268
|
-
console.log('BARE CLI TEST');
|
|
269
|
-
const run = execSync(`node ./index.js --numEvents 1000 --numUsers 100`);
|
|
270
|
-
expect(run.toString().trim().includes('enjoy your data! :)')).toBe(true);
|
|
271
|
-
const csvs = (await u.ls('./data')).filter(a => a.includes('.csv'));
|
|
272
|
-
expect(csvs.length).toBe(2);
|
|
273
|
-
|
|
274
|
-
}, timeout);
|
|
275
|
-
|
|
276
|
-
test('--complex', async () => {
|
|
277
|
-
console.log('COMPLEX CLI TEST');
|
|
278
|
-
const run = execSync(`node ./index.js --numEvents 1000 --numUsers 100 --seed "deal with it" --complex`, { stdio: "ignore" });
|
|
279
|
-
const csvs = (await u.ls('./data')).filter(a => a.includes('.csv'));
|
|
280
|
-
expect(csvs.length).toBe(13);
|
|
281
|
-
|
|
282
|
-
}, timeout);
|
|
158
|
+
// describe('batching', () => {
|
|
159
|
+
// test('batch writes', async () => {
|
|
160
|
+
// const results = await generate({ ...foobar, batchSize: 1000, writeToDisk: true, numEvents: 10_000, numUsers: 5000, seed: "deal" });
|
|
161
|
+
// const { eventData, userProfilesData } = results;
|
|
162
|
+
// const files = (await u.ls('./data')).filter(a => a.endsWith('.json'));
|
|
163
|
+
// const eventFiles = files.filter(a => a.includes('EVENTS'));
|
|
164
|
+
// const userFiles = files.filter(a => a.includes('USERS'));
|
|
165
|
+
// const evWriteDir = eventData.getWriteDir();
|
|
166
|
+
// const usWriteDir = userProfilesData.getWriteDir();
|
|
167
|
+
// const evWritePath = eventData.getWritePath();
|
|
168
|
+
// const usWritePath = userProfilesData.getWritePath();
|
|
169
|
+
|
|
170
|
+
// const expectedEvWriteDir = `-EVENTS.json`;
|
|
171
|
+
// const expectedUsWriteDir = `-USERS.json`;
|
|
172
|
+
// const expectedWritePath = `-part-`;
|
|
173
|
+
|
|
174
|
+
// expect(eventFiles.length).toBe(22);
|
|
175
|
+
// expect(userFiles.length).toBe(5);
|
|
176
|
+
|
|
177
|
+
// expect(eventFiles.filter(a => a.includes('part')).length).toBe(23);
|
|
178
|
+
// expect(userFiles.filter(a => a.includes('part')).length).toBe(5);
|
|
179
|
+
// expect(evWriteDir.endsWith(expectedEvWriteDir)).toBe(true);
|
|
180
|
+
// expect(usWriteDir.endsWith(expectedUsWriteDir)).toBe(true);
|
|
181
|
+
// expect(evWritePath.includes(expectedWritePath)).toBe(true);
|
|
182
|
+
// expect(usWritePath.includes(expectedWritePath)).toBe(true);
|
|
183
|
+
|
|
184
|
+
// }, timeout);
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
// test('dont batch', async () => {
|
|
188
|
+
// const results = await generate({ ...foobar, writeToDisk: true, numEvents: 5000, numUsers: 1000, seed: "deal" });
|
|
189
|
+
// const { eventData, userProfilesData } = results;
|
|
190
|
+
// const files = await u.ls('./data');
|
|
191
|
+
// const eventFiles = files.filter(a => a.includes('EVENTS'));
|
|
192
|
+
// const userFiles = files.filter(a => a.includes('USERS'));
|
|
193
|
+
// expect(eventFiles.length).toBe(1);
|
|
194
|
+
// expect(userFiles.length).toBe(1);
|
|
195
|
+
// expect(eventFiles.filter(a => a.includes('part')).length).toBe(0);
|
|
196
|
+
// const evWriteDir = eventData.getWriteDir();
|
|
197
|
+
// const usWriteDir = userProfilesData.getWriteDir();
|
|
198
|
+
// const expectedEvWriteDir = `-EVENTS.json`;
|
|
199
|
+
// const expectedUsWriteDir = `-USERS.json`;
|
|
200
|
+
// expect(evWriteDir.endsWith(expectedEvWriteDir)).toBe(true);
|
|
201
|
+
// expect(usWriteDir.endsWith(expectedUsWriteDir)).toBe(true);
|
|
202
|
+
|
|
203
|
+
// const evWritePath = eventData.getWritePath();
|
|
204
|
+
// const usWritePath = userProfilesData.getWritePath();
|
|
205
|
+
// expect(evWritePath.endsWith(expectedEvWriteDir)).toBe(true);
|
|
206
|
+
// expect(usWritePath.endsWith(expectedUsWriteDir)).toBe(true);
|
|
207
|
+
|
|
208
|
+
// }, timeout);
|
|
209
|
+
|
|
210
|
+
// test('send to mp: batches', async () => {
|
|
211
|
+
// const results = await generate({ ...foobar, numDays: 90, hasAdSpend: true, token: testToken, batchSize: 4500, writeToDisk: true, numEvents: 10_000, numUsers: 5000, seed: "deal" });
|
|
212
|
+
// const { importResults } = results;
|
|
213
|
+
// const { adSpend, events, groups, users } = importResults;
|
|
214
|
+
// expect(adSpend.success).toBeGreaterThan(0);
|
|
215
|
+
// expect(events.success).toBeGreaterThan(0);
|
|
216
|
+
// expect(users.success).toBeGreaterThan(0);
|
|
217
|
+
// expect(groups[0].success).toBeGreaterThan(0);
|
|
218
|
+
// expect(groups[1].success).toBeGreaterThan(0);
|
|
219
|
+
// expect(adSpend.success).toBe(adSpend.total);
|
|
220
|
+
// expect(events.success).toBe(events.total);
|
|
221
|
+
// // expect(users.success).toBe(users.total);
|
|
222
|
+
// expect(groups.length).toBe(2);
|
|
223
|
+
// expect(groups[0].success).toBe(groups[0].total);
|
|
224
|
+
// expect(groups[1].success).toBe(groups[1].total);
|
|
225
|
+
// expect(adSpend.failed).toBe(0);
|
|
226
|
+
// expect(events.failed).toBe(0);
|
|
227
|
+
// expect(users.failed).toBe(0);
|
|
228
|
+
// expect(groups[0].failed).toBe(0);
|
|
229
|
+
// expect(groups[1].failed).toBe(0);
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
// }, timeout);
|
|
233
|
+
|
|
234
|
+
// test('send to mp: no batch', async () => {
|
|
235
|
+
// const results = await generate({ ...foobar, numDays: 90, hasAdSpend: true, token: testToken, writeToDisk: true, numEvents: 5000, numUsers: 1000, seed: "deal" });
|
|
236
|
+
// const { importResults } = results;
|
|
237
|
+
// const { adSpend, events, groups, users } = importResults;
|
|
238
|
+
// expect(adSpend.success).toBeGreaterThan(0);
|
|
239
|
+
// expect(events.success).toBeGreaterThan(0);
|
|
240
|
+
// expect(users.success).toBeGreaterThan(0);
|
|
241
|
+
// expect(groups[0].success).toBeGreaterThan(0);
|
|
242
|
+
// expect(groups[1].success).toBeGreaterThan(0);
|
|
243
|
+
// expect(adSpend.success).toBe(adSpend.total);
|
|
244
|
+
// expect(events.success).toBe(events.total);
|
|
245
|
+
// expect(users.success).toBe(users.total);
|
|
246
|
+
// expect(groups.length).toBe(2);
|
|
247
|
+
// expect(groups[0].success).toBe(groups[0].total);
|
|
248
|
+
// expect(groups[1].success).toBe(groups[1].total);
|
|
249
|
+
// expect(adSpend.failed).toBe(0);
|
|
250
|
+
// expect(events.failed).toBe(0);
|
|
251
|
+
// expect(users.failed).toBe(0);
|
|
252
|
+
// expect(groups[0].failed).toBe(0);
|
|
253
|
+
// expect(groups[1].failed).toBe(0);
|
|
254
|
+
|
|
255
|
+
// }, timeout);
|
|
256
|
+
// });
|
|
283
257
|
|
|
284
|
-
test('--simple', async () => {
|
|
285
|
-
console.log('SIMPLE CLI TEST');
|
|
286
|
-
const run = execSync(`node ./index.js --numEvents 1000 --numUsers 100 --seed "deal with it" --simple`);
|
|
287
|
-
expect(run.toString().trim().includes('enjoy your data! :)')).toBe(true);
|
|
288
|
-
const csvs = (await u.ls('./data')).filter(a => a.includes('.csv'));
|
|
289
|
-
expect(csvs.length).toBe(2);
|
|
290
|
-
|
|
291
|
-
}, timeout);
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
});
|
|
295
258
|
|
|
296
259
|
describe('options + tweaks', () => {
|
|
297
260
|
test('creates sessionIds', async () => {
|
|
@@ -382,26 +345,11 @@ describe('options + tweaks', () => {
|
|
|
382
345
|
|
|
383
346
|
});
|
|
384
347
|
|
|
385
|
-
beforeEach(() => {
|
|
386
|
-
clearData();
|
|
387
|
-
});
|
|
388
348
|
|
|
389
|
-
afterEach(() => {
|
|
390
|
-
clearData();
|
|
391
|
-
});
|
|
392
349
|
|
|
393
350
|
//helpers
|
|
394
351
|
|
|
395
|
-
|
|
396
|
-
try {
|
|
397
|
-
console.log('clearing...');
|
|
398
|
-
execSync(`npm run prune`);
|
|
399
|
-
console.log('...files cleared 👍');
|
|
400
|
-
}
|
|
401
|
-
catch (err) {
|
|
402
|
-
console.log('error clearing files');
|
|
403
|
-
}
|
|
404
|
-
}
|
|
352
|
+
|
|
405
353
|
|
|
406
354
|
function validateEvent(event) {
|
|
407
355
|
if (!event.event) return false;
|
|
@@ -416,7 +364,7 @@ function validateUser(user) {
|
|
|
416
364
|
if (!user.distinct_id) return false;
|
|
417
365
|
if (!user.name) return false;
|
|
418
366
|
if (!user.email) return false;
|
|
419
|
-
if (!user.created) return false;
|
|
367
|
+
// if (!user.created) return false;
|
|
420
368
|
return true;
|
|
421
369
|
}
|
|
422
370
|
|
package/tests/int.test.js
CHANGED
|
@@ -6,7 +6,7 @@ dayjs.extend(utc);
|
|
|
6
6
|
require('dotenv').config();
|
|
7
7
|
const path = require('path');
|
|
8
8
|
|
|
9
|
-
/** @typedef {import('../types.js').
|
|
9
|
+
/** @typedef {import('../types.js').Dungeon} Config */
|
|
10
10
|
/** @typedef {import('../types.js').EventConfig} EventConfig */
|
|
11
11
|
/** @typedef {import("../types.js").EventSchema} EventSchema */
|
|
12
12
|
/** @typedef {import('../types.js').ValueValid} ValueValid */
|
|
@@ -496,7 +496,7 @@ describe('orchestrators', () => {
|
|
|
496
496
|
});
|
|
497
497
|
|
|
498
498
|
|
|
499
|
-
test('userLoop: works (no funnels)', async () => {
|
|
499
|
+
test('userLoop: works (no funnels; no inference)', async () => {
|
|
500
500
|
/** @type {Config} */
|
|
501
501
|
const config = {
|
|
502
502
|
numUsers: 2,
|
|
@@ -509,6 +509,7 @@ describe('orchestrators', () => {
|
|
|
509
509
|
hasAnonIds: false,
|
|
510
510
|
hasSessionIds: false,
|
|
511
511
|
hasLocation: false,
|
|
512
|
+
alsoInferFunnels: false,
|
|
512
513
|
events: [{ event: "foo" }, { event: "bar" }, { event: "baz" }]
|
|
513
514
|
};
|
|
514
515
|
await userLoop(config, STORAGE);
|
package/tests/jest.config.js
CHANGED
|
@@ -7,6 +7,13 @@ const jestConfig = {
|
|
|
7
7
|
verbose: isDebugMode,
|
|
8
8
|
watch: false,
|
|
9
9
|
projects: [
|
|
10
|
+
{
|
|
11
|
+
"displayName": "cli",
|
|
12
|
+
"testMatch": [
|
|
13
|
+
"<rootDir>/tests/cli.test.js"
|
|
14
|
+
],
|
|
15
|
+
maxWorkers: 1
|
|
16
|
+
},
|
|
10
17
|
{
|
|
11
18
|
"displayName": "e2e",
|
|
12
19
|
"testMatch": [
|
|
@@ -14,6 +21,7 @@ const jestConfig = {
|
|
|
14
21
|
],
|
|
15
22
|
// @ts-ignore
|
|
16
23
|
maxWorkers: 1
|
|
24
|
+
|
|
17
25
|
|
|
18
26
|
},
|
|
19
27
|
{
|
package/tests/unit.test.js
CHANGED
|
@@ -6,7 +6,7 @@ const u = require('ak-tools');
|
|
|
6
6
|
dayjs.extend(utc);
|
|
7
7
|
require('dotenv').config();
|
|
8
8
|
|
|
9
|
-
/** @typedef {import('../types').
|
|
9
|
+
/** @typedef {import('../types').Dungeon} Config */
|
|
10
10
|
/** @typedef {import('../types').EventConfig} EventConfig */
|
|
11
11
|
/** @typedef {import('../types').ValueValid} ValueValid */
|
|
12
12
|
/** @typedef {import('../types').HookedArray} hookArray */
|
package/tsconfig.json
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
},
|
|
12
12
|
"include": [
|
|
13
13
|
"**/*.js"
|
|
14
|
-
, "soupTemplates.mjs", "tests/testSoup.mjs", "tests/testCases.mjs", "tests/benchmark/concurrency.mjs", "dungeons/pos.mjs", "scripts/new-project.mjs" ],
|
|
14
|
+
, "soupTemplates.mjs", "tests/testSoup.mjs", "tests/testCases.mjs", "tests/benchmark/concurrency.mjs", "dungeons/customers/pos.mjs", "scripts/new-project.mjs" ],
|
|
15
15
|
"exclude": [
|
|
16
16
|
"node_modules"
|
|
17
17
|
]
|