@walkeros/server-destination-mixpanel 3.3.0-next-1776098542393
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 +145 -0
- package/dist/dev.d.mts +197 -0
- package/dist/dev.d.ts +197 -0
- package/dist/dev.js +1 -0
- package/dist/dev.js.map +1 -0
- package/dist/dev.mjs +1 -0
- package/dist/dev.mjs.map +1 -0
- package/dist/examples/index.d.mts +152 -0
- package/dist/examples/index.d.ts +152 -0
- package/dist/examples/index.js +405 -0
- package/dist/examples/index.mjs +383 -0
- package/dist/index.d.mts +116 -0
- package/dist/index.d.ts +116 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +1 -0
- package/dist/index.mjs.map +1 -0
- package/dist/walkerOS.json +1095 -0
- package/package.json +75 -0
|
@@ -0,0 +1,383 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __export = (target, all) => {
|
|
3
|
+
for (var name in all)
|
|
4
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
// src/examples/env.ts
|
|
8
|
+
var env_exports = {};
|
|
9
|
+
__export(env_exports, {
|
|
10
|
+
push: () => push,
|
|
11
|
+
simulation: () => simulation
|
|
12
|
+
});
|
|
13
|
+
var noop = (() => {
|
|
14
|
+
});
|
|
15
|
+
var noopPeople = {
|
|
16
|
+
set: noop,
|
|
17
|
+
set_once: noop,
|
|
18
|
+
increment: noop,
|
|
19
|
+
append: noop,
|
|
20
|
+
union: noop,
|
|
21
|
+
remove: noop,
|
|
22
|
+
unset: noop,
|
|
23
|
+
delete_user: noop
|
|
24
|
+
};
|
|
25
|
+
var noopGroups = {
|
|
26
|
+
set: noop,
|
|
27
|
+
set_once: noop,
|
|
28
|
+
union: noop,
|
|
29
|
+
remove: noop,
|
|
30
|
+
unset: noop,
|
|
31
|
+
delete_group: noop
|
|
32
|
+
};
|
|
33
|
+
function mockInit() {
|
|
34
|
+
return {
|
|
35
|
+
track: noop,
|
|
36
|
+
import: noop,
|
|
37
|
+
alias: noop,
|
|
38
|
+
people: { ...noopPeople },
|
|
39
|
+
groups: { ...noopGroups }
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
var push = {
|
|
43
|
+
Mixpanel: { init: mockInit }
|
|
44
|
+
};
|
|
45
|
+
var simulation = [
|
|
46
|
+
"call:Mixpanel.init",
|
|
47
|
+
"call:mp.track",
|
|
48
|
+
"call:mp.import",
|
|
49
|
+
"call:mp.alias",
|
|
50
|
+
"call:mp.people.set",
|
|
51
|
+
"call:mp.people.set_once",
|
|
52
|
+
"call:mp.people.increment",
|
|
53
|
+
"call:mp.people.append",
|
|
54
|
+
"call:mp.people.union",
|
|
55
|
+
"call:mp.people.remove",
|
|
56
|
+
"call:mp.people.unset",
|
|
57
|
+
"call:mp.people.delete_user",
|
|
58
|
+
"call:mp.groups.set",
|
|
59
|
+
"call:mp.groups.set_once",
|
|
60
|
+
"call:mp.groups.union",
|
|
61
|
+
"call:mp.groups.remove",
|
|
62
|
+
"call:mp.groups.unset",
|
|
63
|
+
"call:mp.groups.delete_group"
|
|
64
|
+
];
|
|
65
|
+
|
|
66
|
+
// src/examples/step.ts
|
|
67
|
+
var step_exports = {};
|
|
68
|
+
__export(step_exports, {
|
|
69
|
+
aliasBeforeTrack: () => aliasBeforeTrack,
|
|
70
|
+
allPeopleOperations: () => allPeopleOperations,
|
|
71
|
+
companyGroupProfile: () => companyGroupProfile,
|
|
72
|
+
defaultEventForwarding: () => defaultEventForwarding,
|
|
73
|
+
historicalImport: () => historicalImport,
|
|
74
|
+
perEventIdentify: () => perEventIdentify,
|
|
75
|
+
trackWithGroup: () => trackWithGroup,
|
|
76
|
+
trackWithInclude: () => trackWithInclude,
|
|
77
|
+
userLoginPeopleSet: () => userLoginPeopleSet,
|
|
78
|
+
wildcardIgnored: () => wildcardIgnored
|
|
79
|
+
});
|
|
80
|
+
import { getEvent } from "@walkeros/core";
|
|
81
|
+
var defaultEventForwarding = {
|
|
82
|
+
in: getEvent("product view", { timestamp: 1700000100 }),
|
|
83
|
+
settings: {
|
|
84
|
+
identify: {
|
|
85
|
+
map: {
|
|
86
|
+
distinctId: "user.id"
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
out: ["mp.track", "product view", { distinct_id: "us3r" }]
|
|
91
|
+
};
|
|
92
|
+
var trackWithInclude = {
|
|
93
|
+
in: getEvent("product view", { timestamp: 1700000101 }),
|
|
94
|
+
settings: {
|
|
95
|
+
identify: {
|
|
96
|
+
map: {
|
|
97
|
+
distinctId: "user.id"
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
},
|
|
101
|
+
configInclude: ["data"],
|
|
102
|
+
out: [
|
|
103
|
+
"mp.track",
|
|
104
|
+
"product view",
|
|
105
|
+
{
|
|
106
|
+
distinct_id: "us3r",
|
|
107
|
+
data_id: "ers",
|
|
108
|
+
data_name: "Everyday Ruck Snack",
|
|
109
|
+
data_color: "black",
|
|
110
|
+
data_size: "l",
|
|
111
|
+
data_price: 420
|
|
112
|
+
}
|
|
113
|
+
]
|
|
114
|
+
};
|
|
115
|
+
var perEventIdentify = {
|
|
116
|
+
in: getEvent("user login", {
|
|
117
|
+
timestamp: 1700000102,
|
|
118
|
+
data: {
|
|
119
|
+
user_id: "resolved-id",
|
|
120
|
+
plan: "premium"
|
|
121
|
+
}
|
|
122
|
+
}),
|
|
123
|
+
mapping: {
|
|
124
|
+
settings: {
|
|
125
|
+
identify: {
|
|
126
|
+
map: {
|
|
127
|
+
distinctId: "data.user_id"
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
},
|
|
132
|
+
out: [
|
|
133
|
+
"mp.track",
|
|
134
|
+
"user login",
|
|
135
|
+
{
|
|
136
|
+
distinct_id: "resolved-id"
|
|
137
|
+
}
|
|
138
|
+
]
|
|
139
|
+
};
|
|
140
|
+
var trackWithGroup = {
|
|
141
|
+
in: getEvent("page view", {
|
|
142
|
+
timestamp: 1700000103,
|
|
143
|
+
data: {
|
|
144
|
+
company_id: "acme"
|
|
145
|
+
}
|
|
146
|
+
}),
|
|
147
|
+
settings: {
|
|
148
|
+
identify: {
|
|
149
|
+
map: {
|
|
150
|
+
distinctId: "user.id"
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
},
|
|
154
|
+
mapping: {
|
|
155
|
+
settings: {
|
|
156
|
+
group: {
|
|
157
|
+
map: {
|
|
158
|
+
key: { value: "company_id" },
|
|
159
|
+
id: "data.company_id"
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
},
|
|
164
|
+
out: [
|
|
165
|
+
"mp.track",
|
|
166
|
+
"page view",
|
|
167
|
+
{
|
|
168
|
+
distinct_id: "us3r",
|
|
169
|
+
company_id: "acme"
|
|
170
|
+
}
|
|
171
|
+
]
|
|
172
|
+
};
|
|
173
|
+
var userLoginPeopleSet = {
|
|
174
|
+
in: getEvent("user login", {
|
|
175
|
+
timestamp: 1700000104,
|
|
176
|
+
data: {
|
|
177
|
+
user_id: "new-user-123",
|
|
178
|
+
plan: "premium",
|
|
179
|
+
company: "Acme",
|
|
180
|
+
email: "user@acme.com"
|
|
181
|
+
}
|
|
182
|
+
}),
|
|
183
|
+
mapping: {
|
|
184
|
+
skip: true,
|
|
185
|
+
settings: {
|
|
186
|
+
identify: {
|
|
187
|
+
map: {
|
|
188
|
+
distinctId: "data.user_id"
|
|
189
|
+
}
|
|
190
|
+
},
|
|
191
|
+
people: {
|
|
192
|
+
map: {
|
|
193
|
+
set: {
|
|
194
|
+
map: {
|
|
195
|
+
plan: "data.plan",
|
|
196
|
+
company: "data.company",
|
|
197
|
+
email: "data.email"
|
|
198
|
+
}
|
|
199
|
+
},
|
|
200
|
+
set_once: {
|
|
201
|
+
map: {
|
|
202
|
+
first_login: "timestamp"
|
|
203
|
+
}
|
|
204
|
+
},
|
|
205
|
+
increment: {
|
|
206
|
+
map: {
|
|
207
|
+
login_count: { value: 1 }
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
},
|
|
214
|
+
out: [
|
|
215
|
+
[
|
|
216
|
+
"mp.people.set",
|
|
217
|
+
"new-user-123",
|
|
218
|
+
{ plan: "premium", company: "Acme", email: "user@acme.com" }
|
|
219
|
+
],
|
|
220
|
+
["mp.people.set_once", "new-user-123", { first_login: 1700000104 }],
|
|
221
|
+
["mp.people.increment", "new-user-123", { login_count: 1 }]
|
|
222
|
+
]
|
|
223
|
+
};
|
|
224
|
+
var allPeopleOperations = {
|
|
225
|
+
in: getEvent("profile update", {
|
|
226
|
+
timestamp: 1700000105,
|
|
227
|
+
data: {
|
|
228
|
+
name: "Jane Doe",
|
|
229
|
+
email: "jane@acme.com",
|
|
230
|
+
page: "/docs/getting-started",
|
|
231
|
+
removed_tag: "trial",
|
|
232
|
+
source: "referral"
|
|
233
|
+
}
|
|
234
|
+
}),
|
|
235
|
+
mapping: {
|
|
236
|
+
skip: true,
|
|
237
|
+
settings: {
|
|
238
|
+
identify: {
|
|
239
|
+
map: {
|
|
240
|
+
distinctId: "user.id"
|
|
241
|
+
}
|
|
242
|
+
},
|
|
243
|
+
people: {
|
|
244
|
+
map: {
|
|
245
|
+
set: {
|
|
246
|
+
map: {
|
|
247
|
+
name: "data.name",
|
|
248
|
+
email: "data.email"
|
|
249
|
+
}
|
|
250
|
+
},
|
|
251
|
+
set_once: {
|
|
252
|
+
map: {
|
|
253
|
+
signup_source: "data.source"
|
|
254
|
+
}
|
|
255
|
+
},
|
|
256
|
+
increment: {
|
|
257
|
+
map: {
|
|
258
|
+
page_views: { value: 1 }
|
|
259
|
+
}
|
|
260
|
+
},
|
|
261
|
+
append: {
|
|
262
|
+
map: {
|
|
263
|
+
visited_pages: "data.page"
|
|
264
|
+
}
|
|
265
|
+
},
|
|
266
|
+
union: {
|
|
267
|
+
map: {
|
|
268
|
+
unique_tags: { value: ["active"] }
|
|
269
|
+
}
|
|
270
|
+
},
|
|
271
|
+
remove: {
|
|
272
|
+
map: {
|
|
273
|
+
tags: "data.removed_tag"
|
|
274
|
+
}
|
|
275
|
+
},
|
|
276
|
+
unset: { value: ["old_plan"] }
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
},
|
|
281
|
+
out: [
|
|
282
|
+
["mp.people.set", "us3r", { name: "Jane Doe", email: "jane@acme.com" }],
|
|
283
|
+
["mp.people.set_once", "us3r", { signup_source: "referral" }],
|
|
284
|
+
["mp.people.increment", "us3r", { page_views: 1 }],
|
|
285
|
+
["mp.people.append", "us3r", { visited_pages: "/docs/getting-started" }],
|
|
286
|
+
["mp.people.union", "us3r", { unique_tags: ["active"] }],
|
|
287
|
+
["mp.people.remove", "us3r", { tags: "trial" }],
|
|
288
|
+
["mp.people.unset", "us3r", ["old_plan"]]
|
|
289
|
+
]
|
|
290
|
+
};
|
|
291
|
+
var companyGroupProfile = {
|
|
292
|
+
in: getEvent("company update", {
|
|
293
|
+
timestamp: 1700000106,
|
|
294
|
+
data: {
|
|
295
|
+
company_id: "acme-inc",
|
|
296
|
+
company_name: "Acme, Inc.",
|
|
297
|
+
plan: "enterprise",
|
|
298
|
+
employee_count: 250,
|
|
299
|
+
founded_year: 2010
|
|
300
|
+
}
|
|
301
|
+
}),
|
|
302
|
+
mapping: {
|
|
303
|
+
skip: true,
|
|
304
|
+
settings: {
|
|
305
|
+
groupProfile: {
|
|
306
|
+
map: {
|
|
307
|
+
key: { value: "company_id" },
|
|
308
|
+
id: "data.company_id",
|
|
309
|
+
set: {
|
|
310
|
+
map: {
|
|
311
|
+
name: "data.company_name",
|
|
312
|
+
plan: "data.plan",
|
|
313
|
+
employee_count: "data.employee_count"
|
|
314
|
+
}
|
|
315
|
+
},
|
|
316
|
+
set_once: {
|
|
317
|
+
map: {
|
|
318
|
+
founded: "data.founded_year"
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
},
|
|
325
|
+
out: [
|
|
326
|
+
[
|
|
327
|
+
"mp.groups.set",
|
|
328
|
+
"company_id",
|
|
329
|
+
"acme-inc",
|
|
330
|
+
{ name: "Acme, Inc.", plan: "enterprise", employee_count: 250 }
|
|
331
|
+
],
|
|
332
|
+
["mp.groups.set_once", "company_id", "acme-inc", { founded: 2010 }]
|
|
333
|
+
]
|
|
334
|
+
};
|
|
335
|
+
var historicalImport = {
|
|
336
|
+
in: getEvent("order complete", {
|
|
337
|
+
timestamp: 1700000107,
|
|
338
|
+
data: {
|
|
339
|
+
total: 99.99
|
|
340
|
+
}
|
|
341
|
+
}),
|
|
342
|
+
settings: {
|
|
343
|
+
useImport: true,
|
|
344
|
+
identify: {
|
|
345
|
+
map: {
|
|
346
|
+
distinctId: "user.id"
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
},
|
|
350
|
+
out: ["mp.import", "order complete", 1700000107, { distinct_id: "us3r" }]
|
|
351
|
+
};
|
|
352
|
+
var aliasBeforeTrack = {
|
|
353
|
+
in: getEvent("user login", {
|
|
354
|
+
timestamp: 1700000108,
|
|
355
|
+
data: {
|
|
356
|
+
user_id: "new-user-456",
|
|
357
|
+
anon_id: "anon-789"
|
|
358
|
+
}
|
|
359
|
+
}),
|
|
360
|
+
mapping: {
|
|
361
|
+
settings: {
|
|
362
|
+
identify: {
|
|
363
|
+
map: {
|
|
364
|
+
distinctId: "data.user_id",
|
|
365
|
+
alias: "data.anon_id"
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
},
|
|
370
|
+
out: [
|
|
371
|
+
["mp.alias", "new-user-456", "anon-789"],
|
|
372
|
+
["mp.track", "user login", { distinct_id: "new-user-456" }]
|
|
373
|
+
]
|
|
374
|
+
};
|
|
375
|
+
var wildcardIgnored = {
|
|
376
|
+
in: getEvent("debug noise", { timestamp: 1700000109 }),
|
|
377
|
+
mapping: { ignore: true },
|
|
378
|
+
out: []
|
|
379
|
+
};
|
|
380
|
+
export {
|
|
381
|
+
env_exports as env,
|
|
382
|
+
step_exports as step
|
|
383
|
+
};
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { Mapping as Mapping$1, Destination as Destination$1 } from '@walkeros/core';
|
|
2
|
+
import { DestinationServer } from '@walkeros/server-core';
|
|
3
|
+
|
|
4
|
+
type MixpanelCallback = (err: Error | undefined) => void;
|
|
5
|
+
/**
|
|
6
|
+
* Subset of the Mixpanel People API used by the destination.
|
|
7
|
+
* Every method requires `distinct_id` as the first argument (stateless server SDK).
|
|
8
|
+
*/
|
|
9
|
+
interface MixpanelPeople {
|
|
10
|
+
set(distinctId: string, properties: Record<string, unknown>, callback?: MixpanelCallback): void;
|
|
11
|
+
set_once(distinctId: string, properties: Record<string, unknown>, callback?: MixpanelCallback): void;
|
|
12
|
+
increment(distinctId: string, properties: Record<string, number>, callback?: MixpanelCallback): void;
|
|
13
|
+
append(distinctId: string, properties: Record<string, unknown>, callback?: MixpanelCallback): void;
|
|
14
|
+
union(distinctId: string, data: Record<string, unknown>, callback?: MixpanelCallback): void;
|
|
15
|
+
remove(distinctId: string, data: Record<string, unknown>, callback?: MixpanelCallback): void;
|
|
16
|
+
unset(distinctId: string, propertyName: string | string[], callback?: MixpanelCallback): void;
|
|
17
|
+
delete_user(distinctId: string, callback?: MixpanelCallback): void;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Subset of the Mixpanel Groups API used by the destination.
|
|
21
|
+
* Every method requires `(groupKey, groupId)` as the first two args.
|
|
22
|
+
*/
|
|
23
|
+
interface MixpanelGroups {
|
|
24
|
+
set(groupKey: string, groupId: string, properties: Record<string, unknown>, callback?: MixpanelCallback): void;
|
|
25
|
+
set_once(groupKey: string, groupId: string, properties: Record<string, unknown>, callback?: MixpanelCallback): void;
|
|
26
|
+
union(groupKey: string, groupId: string, data: Record<string, unknown>, callback?: MixpanelCallback): void;
|
|
27
|
+
remove(groupKey: string, groupId: string, data: Record<string, unknown>, callback?: MixpanelCallback): void;
|
|
28
|
+
unset(groupKey: string, groupId: string, propertyName: string | string[], callback?: MixpanelCallback): void;
|
|
29
|
+
delete_group(groupKey: string, groupId: string, callback?: MixpanelCallback): void;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Subset of the Mixpanel SDK instance the destination uses.
|
|
33
|
+
*/
|
|
34
|
+
interface MixpanelClient {
|
|
35
|
+
track(eventName: string, properties: Record<string, unknown>, callback?: MixpanelCallback): void;
|
|
36
|
+
import(eventName: string, time: Date | number, properties?: Record<string, unknown>, callback?: MixpanelCallback): void;
|
|
37
|
+
alias(distinctId: string, alias: string, callback?: MixpanelCallback): void;
|
|
38
|
+
people: MixpanelPeople;
|
|
39
|
+
groups: MixpanelGroups;
|
|
40
|
+
}
|
|
41
|
+
interface Settings {
|
|
42
|
+
apiKey: string;
|
|
43
|
+
secret?: string;
|
|
44
|
+
host?: string;
|
|
45
|
+
protocol?: string;
|
|
46
|
+
keepAlive?: boolean;
|
|
47
|
+
geolocate?: boolean;
|
|
48
|
+
debug?: boolean;
|
|
49
|
+
verbose?: boolean;
|
|
50
|
+
test?: boolean;
|
|
51
|
+
identify?: Mapping$1.Value;
|
|
52
|
+
group?: Mapping$1.Value;
|
|
53
|
+
include?: string[];
|
|
54
|
+
useImport?: boolean;
|
|
55
|
+
/** Initialized Mixpanel client instance — set during init(). */
|
|
56
|
+
client?: MixpanelClient;
|
|
57
|
+
}
|
|
58
|
+
type InitSettings = Partial<Settings>;
|
|
59
|
+
/**
|
|
60
|
+
* Per-rule mapping settings. Keys follow Mixpanel's native method names.
|
|
61
|
+
* No `reset` (not applicable server-side).
|
|
62
|
+
*/
|
|
63
|
+
interface Mapping {
|
|
64
|
+
identify?: Mapping$1.Value;
|
|
65
|
+
people?: Mapping$1.Value;
|
|
66
|
+
group?: Mapping$1.Value;
|
|
67
|
+
groupProfile?: Mapping$1.Value;
|
|
68
|
+
useImport?: Mapping$1.Value;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Environment with optional Mixpanel constructor override for testing.
|
|
72
|
+
* Follows the same pattern as GCP BigQuery's `env.BigQuery`.
|
|
73
|
+
*/
|
|
74
|
+
interface Env extends DestinationServer.Env {
|
|
75
|
+
Mixpanel?: {
|
|
76
|
+
init: (...args: unknown[]) => MixpanelClient;
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
type Types = Destination$1.Types<Settings, Mapping, Env, InitSettings>;
|
|
80
|
+
interface Destination extends DestinationServer.Destination<Types> {
|
|
81
|
+
init: DestinationServer.InitFn<Types>;
|
|
82
|
+
}
|
|
83
|
+
type Config = {
|
|
84
|
+
settings: Settings;
|
|
85
|
+
} & DestinationServer.Config<Types>;
|
|
86
|
+
type InitFn = DestinationServer.InitFn<Types>;
|
|
87
|
+
type PushFn = DestinationServer.PushFn<Types>;
|
|
88
|
+
type PartialConfig = DestinationServer.PartialConfig<Types>;
|
|
89
|
+
type PushEvents = DestinationServer.PushEvents<Mapping>;
|
|
90
|
+
type Rule = Mapping$1.Rule<Mapping>;
|
|
91
|
+
type Rules = Mapping$1.Rules<Rule>;
|
|
92
|
+
|
|
93
|
+
type index_Config = Config;
|
|
94
|
+
type index_Destination = Destination;
|
|
95
|
+
type index_Env = Env;
|
|
96
|
+
type index_InitFn = InitFn;
|
|
97
|
+
type index_InitSettings = InitSettings;
|
|
98
|
+
type index_Mapping = Mapping;
|
|
99
|
+
type index_MixpanelCallback = MixpanelCallback;
|
|
100
|
+
type index_MixpanelClient = MixpanelClient;
|
|
101
|
+
type index_MixpanelGroups = MixpanelGroups;
|
|
102
|
+
type index_MixpanelPeople = MixpanelPeople;
|
|
103
|
+
type index_PartialConfig = PartialConfig;
|
|
104
|
+
type index_PushEvents = PushEvents;
|
|
105
|
+
type index_PushFn = PushFn;
|
|
106
|
+
type index_Rule = Rule;
|
|
107
|
+
type index_Rules = Rules;
|
|
108
|
+
type index_Settings = Settings;
|
|
109
|
+
type index_Types = Types;
|
|
110
|
+
declare namespace index {
|
|
111
|
+
export type { index_Config as Config, index_Destination as Destination, index_Env as Env, index_InitFn as InitFn, index_InitSettings as InitSettings, index_Mapping as Mapping, index_MixpanelCallback as MixpanelCallback, index_MixpanelClient as MixpanelClient, index_MixpanelGroups as MixpanelGroups, index_MixpanelPeople as MixpanelPeople, index_PartialConfig as PartialConfig, index_PushEvents as PushEvents, index_PushFn as PushFn, index_Rule as Rule, index_Rules as Rules, index_Settings as Settings, index_Types as Types };
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
declare const destinationMixpanel: Destination;
|
|
115
|
+
|
|
116
|
+
export { index as DestinationMixpanel, destinationMixpanel as default, destinationMixpanel };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { Mapping as Mapping$1, Destination as Destination$1 } from '@walkeros/core';
|
|
2
|
+
import { DestinationServer } from '@walkeros/server-core';
|
|
3
|
+
|
|
4
|
+
type MixpanelCallback = (err: Error | undefined) => void;
|
|
5
|
+
/**
|
|
6
|
+
* Subset of the Mixpanel People API used by the destination.
|
|
7
|
+
* Every method requires `distinct_id` as the first argument (stateless server SDK).
|
|
8
|
+
*/
|
|
9
|
+
interface MixpanelPeople {
|
|
10
|
+
set(distinctId: string, properties: Record<string, unknown>, callback?: MixpanelCallback): void;
|
|
11
|
+
set_once(distinctId: string, properties: Record<string, unknown>, callback?: MixpanelCallback): void;
|
|
12
|
+
increment(distinctId: string, properties: Record<string, number>, callback?: MixpanelCallback): void;
|
|
13
|
+
append(distinctId: string, properties: Record<string, unknown>, callback?: MixpanelCallback): void;
|
|
14
|
+
union(distinctId: string, data: Record<string, unknown>, callback?: MixpanelCallback): void;
|
|
15
|
+
remove(distinctId: string, data: Record<string, unknown>, callback?: MixpanelCallback): void;
|
|
16
|
+
unset(distinctId: string, propertyName: string | string[], callback?: MixpanelCallback): void;
|
|
17
|
+
delete_user(distinctId: string, callback?: MixpanelCallback): void;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Subset of the Mixpanel Groups API used by the destination.
|
|
21
|
+
* Every method requires `(groupKey, groupId)` as the first two args.
|
|
22
|
+
*/
|
|
23
|
+
interface MixpanelGroups {
|
|
24
|
+
set(groupKey: string, groupId: string, properties: Record<string, unknown>, callback?: MixpanelCallback): void;
|
|
25
|
+
set_once(groupKey: string, groupId: string, properties: Record<string, unknown>, callback?: MixpanelCallback): void;
|
|
26
|
+
union(groupKey: string, groupId: string, data: Record<string, unknown>, callback?: MixpanelCallback): void;
|
|
27
|
+
remove(groupKey: string, groupId: string, data: Record<string, unknown>, callback?: MixpanelCallback): void;
|
|
28
|
+
unset(groupKey: string, groupId: string, propertyName: string | string[], callback?: MixpanelCallback): void;
|
|
29
|
+
delete_group(groupKey: string, groupId: string, callback?: MixpanelCallback): void;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Subset of the Mixpanel SDK instance the destination uses.
|
|
33
|
+
*/
|
|
34
|
+
interface MixpanelClient {
|
|
35
|
+
track(eventName: string, properties: Record<string, unknown>, callback?: MixpanelCallback): void;
|
|
36
|
+
import(eventName: string, time: Date | number, properties?: Record<string, unknown>, callback?: MixpanelCallback): void;
|
|
37
|
+
alias(distinctId: string, alias: string, callback?: MixpanelCallback): void;
|
|
38
|
+
people: MixpanelPeople;
|
|
39
|
+
groups: MixpanelGroups;
|
|
40
|
+
}
|
|
41
|
+
interface Settings {
|
|
42
|
+
apiKey: string;
|
|
43
|
+
secret?: string;
|
|
44
|
+
host?: string;
|
|
45
|
+
protocol?: string;
|
|
46
|
+
keepAlive?: boolean;
|
|
47
|
+
geolocate?: boolean;
|
|
48
|
+
debug?: boolean;
|
|
49
|
+
verbose?: boolean;
|
|
50
|
+
test?: boolean;
|
|
51
|
+
identify?: Mapping$1.Value;
|
|
52
|
+
group?: Mapping$1.Value;
|
|
53
|
+
include?: string[];
|
|
54
|
+
useImport?: boolean;
|
|
55
|
+
/** Initialized Mixpanel client instance — set during init(). */
|
|
56
|
+
client?: MixpanelClient;
|
|
57
|
+
}
|
|
58
|
+
type InitSettings = Partial<Settings>;
|
|
59
|
+
/**
|
|
60
|
+
* Per-rule mapping settings. Keys follow Mixpanel's native method names.
|
|
61
|
+
* No `reset` (not applicable server-side).
|
|
62
|
+
*/
|
|
63
|
+
interface Mapping {
|
|
64
|
+
identify?: Mapping$1.Value;
|
|
65
|
+
people?: Mapping$1.Value;
|
|
66
|
+
group?: Mapping$1.Value;
|
|
67
|
+
groupProfile?: Mapping$1.Value;
|
|
68
|
+
useImport?: Mapping$1.Value;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Environment with optional Mixpanel constructor override for testing.
|
|
72
|
+
* Follows the same pattern as GCP BigQuery's `env.BigQuery`.
|
|
73
|
+
*/
|
|
74
|
+
interface Env extends DestinationServer.Env {
|
|
75
|
+
Mixpanel?: {
|
|
76
|
+
init: (...args: unknown[]) => MixpanelClient;
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
type Types = Destination$1.Types<Settings, Mapping, Env, InitSettings>;
|
|
80
|
+
interface Destination extends DestinationServer.Destination<Types> {
|
|
81
|
+
init: DestinationServer.InitFn<Types>;
|
|
82
|
+
}
|
|
83
|
+
type Config = {
|
|
84
|
+
settings: Settings;
|
|
85
|
+
} & DestinationServer.Config<Types>;
|
|
86
|
+
type InitFn = DestinationServer.InitFn<Types>;
|
|
87
|
+
type PushFn = DestinationServer.PushFn<Types>;
|
|
88
|
+
type PartialConfig = DestinationServer.PartialConfig<Types>;
|
|
89
|
+
type PushEvents = DestinationServer.PushEvents<Mapping>;
|
|
90
|
+
type Rule = Mapping$1.Rule<Mapping>;
|
|
91
|
+
type Rules = Mapping$1.Rules<Rule>;
|
|
92
|
+
|
|
93
|
+
type index_Config = Config;
|
|
94
|
+
type index_Destination = Destination;
|
|
95
|
+
type index_Env = Env;
|
|
96
|
+
type index_InitFn = InitFn;
|
|
97
|
+
type index_InitSettings = InitSettings;
|
|
98
|
+
type index_Mapping = Mapping;
|
|
99
|
+
type index_MixpanelCallback = MixpanelCallback;
|
|
100
|
+
type index_MixpanelClient = MixpanelClient;
|
|
101
|
+
type index_MixpanelGroups = MixpanelGroups;
|
|
102
|
+
type index_MixpanelPeople = MixpanelPeople;
|
|
103
|
+
type index_PartialConfig = PartialConfig;
|
|
104
|
+
type index_PushEvents = PushEvents;
|
|
105
|
+
type index_PushFn = PushFn;
|
|
106
|
+
type index_Rule = Rule;
|
|
107
|
+
type index_Rules = Rules;
|
|
108
|
+
type index_Settings = Settings;
|
|
109
|
+
type index_Types = Types;
|
|
110
|
+
declare namespace index {
|
|
111
|
+
export type { index_Config as Config, index_Destination as Destination, index_Env as Env, index_InitFn as InitFn, index_InitSettings as InitSettings, index_Mapping as Mapping, index_MixpanelCallback as MixpanelCallback, index_MixpanelClient as MixpanelClient, index_MixpanelGroups as MixpanelGroups, index_MixpanelPeople as MixpanelPeople, index_PartialConfig as PartialConfig, index_PushEvents as PushEvents, index_PushFn as PushFn, index_Rule as Rule, index_Rules as Rules, index_Settings as Settings, index_Types as Types };
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
declare const destinationMixpanel: Destination;
|
|
115
|
+
|
|
116
|
+
export { index as DestinationMixpanel, destinationMixpanel as default, destinationMixpanel };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";var mod,__create=Object.create,__defProp=Object.defineProperty,__getOwnPropDesc=Object.getOwnPropertyDescriptor,__getOwnPropNames=Object.getOwnPropertyNames,__getProtoOf=Object.getPrototypeOf,__hasOwnProp=Object.prototype.hasOwnProperty,__copyProps=(to,from,except,desc)=>{if(from&&"object"==typeof from||"function"==typeof from)for(let key of __getOwnPropNames(from))__hasOwnProp.call(to,key)||key===except||__defProp(to,key,{get:()=>from[key],enumerable:!(desc=__getOwnPropDesc(from,key))||desc.enumerable});return to},index_exports={};((target,all)=>{for(var name in all)__defProp(target,name,{get:all[name],enumerable:!0})})(index_exports,{DestinationMixpanel:()=>types_exports,default:()=>index_default,destinationMixpanel:()=>destinationMixpanel}),module.exports=(mod=index_exports,__copyProps(__defProp({},"__esModule",{value:!0}),mod));var import_mixpanel=((mod,isNodeMode,target)=>(target=null!=mod?__create(__getProtoOf(mod)):{},__copyProps(!isNodeMode&&mod&&mod.__esModule?target:__defProp(target,"default",{value:mod,enumerable:!0}),mod)))(require("mixpanel"));var import_core=require("@walkeros/core"),PEOPLE_OBJECT_OPS=["set","set_once","increment","append","union","remove"],GROUP_OBJECT_OPS=["set","set_once","union","remove"];function wrapCallback(fn){return new Promise((resolve,reject)=>{fn(err=>{err?reject(err):resolve()})})}var push=async function(event,{config:config,rule:rule,data:data,collector:collector,logger:logger}){var _a,_b;const settings=config.settings,client=settings.client;if(!client)return void logger.throw("Mixpanel client not initialized");const mappingSettings=(null==rule?void 0:rule.settings)||{},identifyMapping=null!=(_a=mappingSettings.identify)?_a:settings.identify;let distinctId,alias;if(void 0!==identifyMapping){const resolved=await(0,import_core.getMappingValue)(event,identifyMapping,{collector:collector});if((0,import_core.isObject)(resolved)){const r=resolved;(0,import_core.isString)(r.distinctId)&&""!==r.distinctId&&(distinctId=r.distinctId),(0,import_core.isString)(r.alias)&&""!==r.alias&&(alias=r.alias)}}if(distinctId&&alias&&await wrapCallback(cb=>{client.alias(distinctId,alias,cb)}),distinctId&&void 0!==mappingSettings.people){const resolved=await(0,import_core.getMappingValue)(event,mappingSettings.people,{collector:collector});(0,import_core.isObject)(resolved)&&await async function(client,distinctId,resolved){const promises=[];for(const op of PEOPLE_OBJECT_OPS){const bag=resolved[op];(0,import_core.isObject)(bag)&&0!==Object.keys(bag).length&&promises.push(wrapCallback(cb=>{client.people[op](distinctId,bag,cb)}))}const unsetVal=resolved.unset;if(void 0!==unsetVal)if((0,import_core.isString)(unsetVal))promises.push(wrapCallback(cb=>{client.people.unset(distinctId,unsetVal,cb)}));else if((0,import_core.isArray)(unsetVal)){const names=unsetVal.filter(v=>(0,import_core.isString)(v));names.length>0&&promises.push(wrapCallback(cb=>{client.people.unset(distinctId,names,cb)}))}!0===resolved.delete_user&&promises.push(wrapCallback(cb=>{client.people.delete_user(distinctId,cb)})),await Promise.all(promises)}(client,distinctId,resolved)}let groupProps={};const groupMapping=null!=(_b=mappingSettings.group)?_b:settings.group;if(void 0!==groupMapping){const resolved=await(0,import_core.getMappingValue)(event,groupMapping,{collector:collector});if((0,import_core.isObject)(resolved)){const{key:gKey,id:gId}=resolved;(0,import_core.isString)(gKey)&&""!==gKey&&(0,import_core.isString)(gId)&&""!==gId&&(groupProps={[gKey]:gId})}}if(void 0!==mappingSettings.groupProfile){const resolved=await(0,import_core.getMappingValue)(event,mappingSettings.groupProfile,{collector:collector});(0,import_core.isObject)(resolved)&&await async function(client,resolved){const{key:key,id:id}=resolved;if(!(0,import_core.isString)(key)||""===key||!(0,import_core.isString)(id)||""===id)return;const promises=[];for(const op of GROUP_OBJECT_OPS){const bag=resolved[op];(0,import_core.isObject)(bag)&&0!==Object.keys(bag).length&&promises.push(wrapCallback(cb=>{client.groups[op](key,id,bag,cb)}))}const unsetVal=resolved.unset;if(void 0!==unsetVal)if((0,import_core.isString)(unsetVal))promises.push(wrapCallback(cb=>{client.groups.unset(key,id,unsetVal,cb)}));else if((0,import_core.isArray)(unsetVal)){const names=unsetVal.filter(v=>(0,import_core.isString)(v));names.length>0&&promises.push(wrapCallback(cb=>{client.groups.unset(key,id,names,cb)}))}!0===resolved.delete&&promises.push(wrapCallback(cb=>{client.groups.delete_group(key,id,cb)})),await Promise.all(promises)}(client,resolved)}if(!0!==(null==rule?void 0:rule.skip)){const eventName=(0,import_core.isString)(null==rule?void 0:rule.name)?rule.name:event.name,properties={};distinctId&&(properties.distinct_id=distinctId),Object.assign(properties,groupProps),(0,import_core.isObject)(data)&&Object.assign(properties,data);if(settings.useImport||mappingSettings.useImport){const timestamp=event.timestamp||Date.now();await wrapCallback(cb=>{client.import(eventName,timestamp,properties,cb)})}else await wrapCallback(cb=>{client.track(eventName,properties,cb)})}},types_exports={},destinationMixpanel={type:"mixpanel",config:{},async init({config:partialConfig,env:env,logger:logger}){const config=function(partialConfig={},env,logger){const settings=partialConfig.settings||{},{apiKey:apiKey}=settings;apiKey||logger.throw("Config settings apiKey missing");const initOptions={};void 0!==settings.secret&&(initOptions.secret=settings.secret),void 0!==settings.host&&(initOptions.host=settings.host),void 0!==settings.protocol&&(initOptions.protocol=settings.protocol),void 0!==settings.keepAlive&&(initOptions.keepAlive=settings.keepAlive),void 0!==settings.geolocate&&(initOptions.geolocate=settings.geolocate),void 0!==settings.debug&&(initOptions.debug=settings.debug),void 0!==settings.verbose&&(initOptions.verbose=settings.verbose),void 0!==settings.test&&(initOptions.test=settings.test),settings.useImport&&!settings.secret&&logger.warn("useImport requires secret for /import authentication");const client=((null==env?void 0:env.Mixpanel)||import_mixpanel.default).init(apiKey,initOptions),settingsConfig={...settings,apiKey:apiKey,client:client};return{...partialConfig,settings:settingsConfig}}(partialConfig,env,logger);return config},push:async(event,context)=>await push(event,context),destroy({config:config}){(null==config?void 0:config.settings)&&(config.settings.client=void 0)}},index_default=destinationMixpanel;//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/config.ts","../src/push.ts","../src/types/index.ts"],"sourcesContent":["import type { Destination } from './types';\nimport { getConfig } from './config';\nimport { push } from './push';\n\n// Types\nexport * as DestinationMixpanel from './types';\n\nexport const destinationMixpanel: Destination = {\n type: 'mixpanel',\n\n config: {},\n\n async init({ config: partialConfig, env, logger }) {\n const config = getConfig(partialConfig, env, logger);\n return config;\n },\n\n async push(event, context) {\n return await push(event, context);\n },\n\n destroy({ config }) {\n // SDK fires immediately — no flush/close needed.\n // Just clear the client reference.\n if (config?.settings) {\n config.settings.client = undefined;\n }\n },\n};\n\nexport default destinationMixpanel;\n","import type {\n Config,\n Env,\n MixpanelClient,\n PartialConfig,\n Settings,\n} from './types';\nimport type { Logger } from '@walkeros/core';\nimport Mixpanel from 'mixpanel';\n\nexport function getConfig(\n partialConfig: PartialConfig = {},\n env: Env | undefined,\n logger: Logger.Instance,\n): Config {\n const settings = (partialConfig.settings || {}) as Partial<Settings>;\n const { apiKey } = settings;\n\n if (!apiKey) logger.throw('Config settings apiKey missing');\n\n // Build SDK init options from settings\n const initOptions: Record<string, unknown> = {};\n if (settings.secret !== undefined) initOptions.secret = settings.secret;\n if (settings.host !== undefined) initOptions.host = settings.host;\n if (settings.protocol !== undefined) initOptions.protocol = settings.protocol;\n if (settings.keepAlive !== undefined)\n initOptions.keepAlive = settings.keepAlive;\n if (settings.geolocate !== undefined)\n initOptions.geolocate = settings.geolocate;\n if (settings.debug !== undefined) initOptions.debug = settings.debug;\n if (settings.verbose !== undefined) initOptions.verbose = settings.verbose;\n if (settings.test !== undefined) initOptions.test = settings.test;\n\n // Warn if useImport without secret\n if (settings.useImport && !settings.secret) {\n logger.warn('useImport requires secret for /import authentication');\n }\n\n // Use Mixpanel from env if available, otherwise use real Mixpanel\n const MixpanelFactory = env?.Mixpanel || Mixpanel;\n const client = MixpanelFactory.init(\n apiKey,\n initOptions,\n ) as unknown as MixpanelClient;\n\n const settingsConfig: Settings = {\n ...settings,\n apiKey,\n client,\n };\n\n return { ...partialConfig, settings: settingsConfig };\n}\n","import type { MixpanelCallback, MixpanelClient, PushFn } from './types';\nimport { getMappingValue, isArray, isObject, isString } from '@walkeros/core';\n\ntype PeopleObjectOp =\n | 'set'\n | 'set_once'\n | 'increment'\n | 'append'\n | 'union'\n | 'remove';\n\nconst PEOPLE_OBJECT_OPS: PeopleObjectOp[] = [\n 'set',\n 'set_once',\n 'increment',\n 'append',\n 'union',\n 'remove',\n];\n\ntype GroupObjectOp = 'set' | 'set_once' | 'union' | 'remove';\n\nconst GROUP_OBJECT_OPS: GroupObjectOp[] = [\n 'set',\n 'set_once',\n 'union',\n 'remove',\n];\n\n/**\n * Wraps a Mixpanel SDK callback-based call in a Promise.\n */\nfunction wrapCallback(fn: (cb: MixpanelCallback) => void): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n fn((err) => {\n if (err) reject(err);\n else resolve();\n });\n });\n}\n\n/**\n * Apply people operations to the Mixpanel client.\n * All people methods require distinct_id as the first argument.\n */\nasync function applyPeople(\n client: MixpanelClient,\n distinctId: string,\n resolved: Record<string, unknown>,\n): Promise<void> {\n const promises: Promise<void>[] = [];\n\n for (const op of PEOPLE_OBJECT_OPS) {\n const bag = resolved[op];\n if (!isObject(bag) || Object.keys(bag).length === 0) continue;\n promises.push(\n wrapCallback((cb) => {\n (\n client.people[op] as (\n id: string,\n props: Record<string, unknown>,\n cb: MixpanelCallback,\n ) => void\n )(distinctId, bag as Record<string, unknown>, cb);\n }),\n );\n }\n\n // Handle unset — string or string[]\n const unsetVal = resolved.unset;\n if (unsetVal !== undefined) {\n if (isString(unsetVal)) {\n promises.push(\n wrapCallback((cb) => {\n client.people.unset(distinctId, unsetVal, cb);\n }),\n );\n } else if (isArray(unsetVal)) {\n const names = (unsetVal as unknown[]).filter((v): v is string =>\n isString(v),\n );\n if (names.length > 0) {\n promises.push(\n wrapCallback((cb) => {\n client.people.unset(distinctId, names, cb);\n }),\n );\n }\n }\n }\n\n // Handle delete_user\n if (resolved.delete_user === true) {\n promises.push(\n wrapCallback((cb) => {\n client.people.delete_user(distinctId, cb);\n }),\n );\n }\n\n await Promise.all(promises);\n}\n\n/**\n * Apply group profile operations to the Mixpanel client.\n */\nasync function applyGroupProfile(\n client: MixpanelClient,\n resolved: Record<string, unknown>,\n): Promise<void> {\n const { key, id } = resolved as { key?: unknown; id?: unknown };\n if (!isString(key) || key === '' || !isString(id) || id === '') return;\n\n const promises: Promise<void>[] = [];\n\n for (const op of GROUP_OBJECT_OPS) {\n const bag = resolved[op];\n if (!isObject(bag) || Object.keys(bag).length === 0) continue;\n promises.push(\n wrapCallback((cb) => {\n (\n client.groups[op] as (\n gk: string,\n gi: string,\n props: Record<string, unknown>,\n cb: MixpanelCallback,\n ) => void\n )(key, id, bag as Record<string, unknown>, cb);\n }),\n );\n }\n\n // Handle unset\n const unsetVal = resolved.unset;\n if (unsetVal !== undefined) {\n if (isString(unsetVal)) {\n promises.push(\n wrapCallback((cb) => {\n client.groups.unset(key, id, unsetVal, cb);\n }),\n );\n } else if (isArray(unsetVal)) {\n const names = (unsetVal as unknown[]).filter((v): v is string =>\n isString(v),\n );\n if (names.length > 0) {\n promises.push(\n wrapCallback((cb) => {\n client.groups.unset(key, id, names, cb);\n }),\n );\n }\n }\n }\n\n // Handle delete\n if (resolved.delete === true) {\n promises.push(\n wrapCallback((cb) => {\n client.groups.delete_group(key, id, cb);\n }),\n );\n }\n\n await Promise.all(promises);\n}\n\nexport const push: PushFn = async function (\n event,\n { config, rule, data, collector, logger },\n) {\n const settings = config.settings!;\n const client = settings.client;\n if (!client) {\n logger.throw('Mixpanel client not initialized');\n return;\n }\n\n const mappingSettings = rule?.settings || {};\n\n // 1. Resolve identity — rule-level override wins over destination-level.\n const identifyMapping = mappingSettings.identify ?? settings.identify;\n let distinctId: string | undefined;\n let alias: string | undefined;\n\n if (identifyMapping !== undefined) {\n const resolved = await getMappingValue(event, identifyMapping, {\n collector,\n });\n if (isObject(resolved)) {\n const r = resolved as Record<string, unknown>;\n if (isString(r.distinctId) && r.distinctId !== '') {\n distinctId = r.distinctId;\n }\n if (isString(r.alias) && r.alias !== '') {\n alias = r.alias;\n }\n }\n }\n\n // 2. Alias — fire before people/track (legacy identity merge)\n if (distinctId && alias) {\n await wrapCallback((cb) => {\n client.alias(distinctId!, alias!, cb);\n });\n }\n\n // 3. People operations — require distinct_id\n if (distinctId && mappingSettings.people !== undefined) {\n const resolved = await getMappingValue(event, mappingSettings.people, {\n collector,\n });\n if (isObject(resolved)) {\n await applyPeople(\n client,\n distinctId,\n resolved as Record<string, unknown>,\n );\n }\n }\n\n // 4. Group — attach group keys to event properties\n let groupProps: Record<string, unknown> = {};\n const groupMapping = mappingSettings.group ?? settings.group;\n if (groupMapping !== undefined) {\n const resolved = await getMappingValue(event, groupMapping, { collector });\n if (isObject(resolved)) {\n const { key: gKey, id: gId } = resolved as {\n key?: unknown;\n id?: unknown;\n };\n if (isString(gKey) && gKey !== '' && isString(gId) && gId !== '') {\n groupProps = { [gKey]: gId };\n }\n }\n }\n\n // 5. Group profile operations\n if (mappingSettings.groupProfile !== undefined) {\n const resolved = await getMappingValue(\n event,\n mappingSettings.groupProfile,\n {\n collector,\n },\n );\n if (isObject(resolved)) {\n await applyGroupProfile(client, resolved as Record<string, unknown>);\n }\n }\n\n // 6. Track/Import — unless the rule opts out via skip\n if (rule?.skip !== true) {\n const eventName = isString(rule?.name) ? rule.name : event.name;\n const properties: Record<string, unknown> = {};\n\n // Add distinct_id to properties\n if (distinctId) {\n properties.distinct_id = distinctId;\n }\n\n // Add group properties\n Object.assign(properties, groupProps);\n\n // Add mapped data (from collector/rule resolution)\n if (isObject(data)) {\n Object.assign(properties, data as Record<string, unknown>);\n }\n\n // Determine if we should use import or track\n const useImport = settings.useImport || mappingSettings.useImport;\n\n if (useImport) {\n const timestamp = event.timestamp || Date.now();\n await wrapCallback((cb) => {\n client.import(eventName, timestamp, properties, cb);\n });\n } else {\n await wrapCallback((cb) => {\n client.track(eventName, properties, cb);\n });\n }\n }\n};\n","import type {\n Mapping as WalkerOSMapping,\n Destination as CoreDestination,\n} from '@walkeros/core';\nimport type { DestinationServer } from '@walkeros/server-core';\nimport type Mixpanel from 'mixpanel';\n\n// Re-export the SDK's callback type for convenience\nexport type MixpanelCallback = (err: Error | undefined) => void;\n\n/**\n * Subset of the Mixpanel People API used by the destination.\n * Every method requires `distinct_id` as the first argument (stateless server SDK).\n */\nexport interface MixpanelPeople {\n set(\n distinctId: string,\n properties: Record<string, unknown>,\n callback?: MixpanelCallback,\n ): void;\n set_once(\n distinctId: string,\n properties: Record<string, unknown>,\n callback?: MixpanelCallback,\n ): void;\n increment(\n distinctId: string,\n properties: Record<string, number>,\n callback?: MixpanelCallback,\n ): void;\n append(\n distinctId: string,\n properties: Record<string, unknown>,\n callback?: MixpanelCallback,\n ): void;\n union(\n distinctId: string,\n data: Record<string, unknown>,\n callback?: MixpanelCallback,\n ): void;\n remove(\n distinctId: string,\n data: Record<string, unknown>,\n callback?: MixpanelCallback,\n ): void;\n unset(\n distinctId: string,\n propertyName: string | string[],\n callback?: MixpanelCallback,\n ): void;\n delete_user(distinctId: string, callback?: MixpanelCallback): void;\n}\n\n/**\n * Subset of the Mixpanel Groups API used by the destination.\n * Every method requires `(groupKey, groupId)` as the first two args.\n */\nexport interface MixpanelGroups {\n set(\n groupKey: string,\n groupId: string,\n properties: Record<string, unknown>,\n callback?: MixpanelCallback,\n ): void;\n set_once(\n groupKey: string,\n groupId: string,\n properties: Record<string, unknown>,\n callback?: MixpanelCallback,\n ): void;\n union(\n groupKey: string,\n groupId: string,\n data: Record<string, unknown>,\n callback?: MixpanelCallback,\n ): void;\n remove(\n groupKey: string,\n groupId: string,\n data: Record<string, unknown>,\n callback?: MixpanelCallback,\n ): void;\n unset(\n groupKey: string,\n groupId: string,\n propertyName: string | string[],\n callback?: MixpanelCallback,\n ): void;\n delete_group(\n groupKey: string,\n groupId: string,\n callback?: MixpanelCallback,\n ): void;\n}\n\n/**\n * Subset of the Mixpanel SDK instance the destination uses.\n */\nexport interface MixpanelClient {\n track(\n eventName: string,\n properties: Record<string, unknown>,\n callback?: MixpanelCallback,\n ): void;\n import(\n eventName: string,\n time: Date | number,\n properties?: Record<string, unknown>,\n callback?: MixpanelCallback,\n ): void;\n alias(distinctId: string, alias: string, callback?: MixpanelCallback): void;\n people: MixpanelPeople;\n groups: MixpanelGroups;\n}\n\nexport interface Settings {\n apiKey: string;\n secret?: string;\n host?: string;\n protocol?: string;\n keepAlive?: boolean;\n geolocate?: boolean;\n debug?: boolean;\n verbose?: boolean;\n test?: boolean;\n identify?: WalkerOSMapping.Value;\n group?: WalkerOSMapping.Value;\n include?: string[];\n useImport?: boolean;\n /** Initialized Mixpanel client instance — set during init(). */\n client?: MixpanelClient;\n}\n\nexport type InitSettings = Partial<Settings>;\n\n/**\n * Per-rule mapping settings. Keys follow Mixpanel's native method names.\n * No `reset` (not applicable server-side).\n */\nexport interface Mapping {\n identify?: WalkerOSMapping.Value;\n people?: WalkerOSMapping.Value;\n group?: WalkerOSMapping.Value;\n groupProfile?: WalkerOSMapping.Value;\n useImport?: WalkerOSMapping.Value;\n}\n\n/**\n * Environment with optional Mixpanel constructor override for testing.\n * Follows the same pattern as GCP BigQuery's `env.BigQuery`.\n */\nexport interface Env extends DestinationServer.Env {\n Mixpanel?: { init: (...args: unknown[]) => MixpanelClient };\n}\n\nexport type Types = CoreDestination.Types<Settings, Mapping, Env, InitSettings>;\n\nexport interface Destination extends DestinationServer.Destination<Types> {\n init: DestinationServer.InitFn<Types>;\n}\n\nexport type Config = {\n settings: Settings;\n} & DestinationServer.Config<Types>;\n\nexport type InitFn = DestinationServer.InitFn<Types>;\nexport type PushFn = DestinationServer.PushFn<Types>;\n\nexport type PartialConfig = DestinationServer.PartialConfig<Types>;\n\nexport type PushEvents = DestinationServer.PushEvents<Mapping>;\n\nexport type Rule = WalkerOSMapping.Rule<Mapping>;\nexport type Rules = WalkerOSMapping.Rules<Rule>;\n"],"mappings":"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","names":["Mixpanel"]}
|