@walkeros/server-destination-posthog 4.8.1 → 4.8.2
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/CHANGELOG.md +31 -0
- package/README.md +1 -1
- package/dist/dev.d.mts +23 -5
- package/dist/dev.d.ts +23 -5
- package/dist/dev.js +1 -1
- package/dist/dev.js.map +1 -1
- package/dist/dev.mjs +1 -1
- package/dist/dev.mjs.map +1 -1
- package/dist/examples/index.d.mts +17 -3
- package/dist/examples/index.d.ts +17 -3
- package/dist/examples/index.js +37 -8
- package/dist/examples/index.mjs +38 -9
- package/dist/index.d.mts +9 -3
- package/dist/index.d.ts +9 -3
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/dist/walkerOS.json +122 -17
- package/package.json +4 -4
package/dist/examples/index.js
CHANGED
|
@@ -86,17 +86,20 @@ __export(step_exports, {
|
|
|
86
86
|
consentRevoke: () => consentRevoke,
|
|
87
87
|
defaultCapture: () => defaultCapture,
|
|
88
88
|
groupIdentifyWithProperties: () => groupIdentifyWithProperties,
|
|
89
|
-
|
|
89
|
+
groupIdentifyWithoutData: () => groupIdentifyWithoutData,
|
|
90
|
+
identifyWithSetAndSetOnce: () => identifyWithSetAndSetOnce,
|
|
91
|
+
silentRule: () => silentRule
|
|
90
92
|
});
|
|
91
93
|
var import_core = require("@walkeros/core");
|
|
92
94
|
var defaultCapture = {
|
|
93
95
|
title: "Default capture",
|
|
94
96
|
description: "A walker event becomes a PostHog capture call with the user id as distinctId and no extra properties.",
|
|
95
|
-
in: (0, import_core.getEvent)("product view", { timestamp: 1700000100 }),
|
|
97
|
+
in: (0, import_core.getEvent)("product view", { id: "ev1700000100", timestamp: 1700000100 }),
|
|
96
98
|
out: [
|
|
97
99
|
[
|
|
98
100
|
"client.capture",
|
|
99
101
|
{
|
|
102
|
+
uuid: "b8a7f21f-1a9f-8aa7-8480-8d16fb64c44c",
|
|
100
103
|
distinctId: "us3r",
|
|
101
104
|
event: "product view",
|
|
102
105
|
properties: {}
|
|
@@ -107,12 +110,13 @@ var defaultCapture = {
|
|
|
107
110
|
var captureWithInclude = {
|
|
108
111
|
title: "Capture with include",
|
|
109
112
|
description: "Destination-level include flattens data and globals sections into prefixed PostHog event properties.",
|
|
110
|
-
in: (0, import_core.getEvent)("order complete", { timestamp: 1700000101 }),
|
|
113
|
+
in: (0, import_core.getEvent)("order complete", { id: "ev1700000101", timestamp: 1700000101 }),
|
|
111
114
|
configInclude: ["data", "globals"],
|
|
112
115
|
out: [
|
|
113
116
|
[
|
|
114
117
|
"client.capture",
|
|
115
118
|
{
|
|
119
|
+
uuid: "a5a5ede9-4f3b-85f4-b30f-3da8773fabfa",
|
|
116
120
|
distinctId: "us3r",
|
|
117
121
|
event: "order complete",
|
|
118
122
|
properties: {
|
|
@@ -120,7 +124,7 @@ var captureWithInclude = {
|
|
|
120
124
|
data_currency: "EUR",
|
|
121
125
|
data_shipping: 5.22,
|
|
122
126
|
data_taxes: 73.76,
|
|
123
|
-
|
|
127
|
+
data_value: 555,
|
|
124
128
|
globals_pagegroup: "shop"
|
|
125
129
|
}
|
|
126
130
|
}
|
|
@@ -130,7 +134,8 @@ var captureWithInclude = {
|
|
|
130
134
|
var identifyWithSetAndSetOnce = {
|
|
131
135
|
title: "Identify with $set",
|
|
132
136
|
description: "A user login fires PostHog identify with $set and $set_once person properties and skips the capture.",
|
|
133
|
-
in: (0, import_core.
|
|
137
|
+
in: (0, import_core.createEvent)({
|
|
138
|
+
name: "user login",
|
|
134
139
|
timestamp: 1700000102,
|
|
135
140
|
data: {
|
|
136
141
|
user_id: "new-user-123",
|
|
@@ -180,7 +185,8 @@ var identifyWithSetAndSetOnce = {
|
|
|
180
185
|
var groupIdentifyWithProperties = {
|
|
181
186
|
title: "Group identify",
|
|
182
187
|
description: "A company update fires PostHog groupIdentify with group type, key, and associated group properties.",
|
|
183
|
-
in: (0, import_core.
|
|
188
|
+
in: (0, import_core.createEvent)({
|
|
189
|
+
name: "company update",
|
|
184
190
|
timestamp: 1700000103,
|
|
185
191
|
data: {
|
|
186
192
|
company_id: "company_123",
|
|
@@ -223,6 +229,7 @@ var captureWithGroupContext = {
|
|
|
223
229
|
title: "Capture with group",
|
|
224
230
|
description: "A destination-level group mapping attaches the resolved group context to every PostHog capture call.",
|
|
225
231
|
in: (0, import_core.getEvent)("page view", {
|
|
232
|
+
id: "ev1700000104",
|
|
226
233
|
timestamp: 1700000104,
|
|
227
234
|
globals: { pagegroup: "docs", company_id: "company_123" }
|
|
228
235
|
}),
|
|
@@ -238,6 +245,7 @@ var captureWithGroupContext = {
|
|
|
238
245
|
[
|
|
239
246
|
"client.capture",
|
|
240
247
|
{
|
|
248
|
+
uuid: "c6a47305-44fc-8835-b15f-3f494c1f9e20",
|
|
241
249
|
distinctId: "us3r",
|
|
242
250
|
event: "page view",
|
|
243
251
|
properties: {},
|
|
@@ -246,12 +254,14 @@ var captureWithGroupContext = {
|
|
|
246
254
|
]
|
|
247
255
|
]
|
|
248
256
|
};
|
|
257
|
+
var analyticsDenied = { analytics: false };
|
|
258
|
+
var analyticsGranted = { analytics: true };
|
|
249
259
|
var consentRevoke = {
|
|
250
260
|
title: "Consent revoked",
|
|
251
261
|
description: "A walker consent command with analytics denied calls client.disable on the PostHog client.",
|
|
252
262
|
command: "consent",
|
|
253
263
|
before: { analytics: true },
|
|
254
|
-
in:
|
|
264
|
+
in: analyticsDenied,
|
|
255
265
|
settings: {},
|
|
256
266
|
out: [["client.enable"], ["client.disable"]]
|
|
257
267
|
};
|
|
@@ -259,10 +269,29 @@ var consentGrant = {
|
|
|
259
269
|
title: "Consent granted",
|
|
260
270
|
description: "A walker consent command with analytics granted calls client.enable on the PostHog client.",
|
|
261
271
|
command: "consent",
|
|
262
|
-
in:
|
|
272
|
+
in: analyticsGranted,
|
|
263
273
|
settings: {},
|
|
264
274
|
out: [["client.enable"]]
|
|
265
275
|
};
|
|
276
|
+
var silentRule = {
|
|
277
|
+
public: false,
|
|
278
|
+
description: "A rule with silent: true and no identify or group mapping sends nothing to PostHog.",
|
|
279
|
+
in: (0, import_core.getEvent)("page view", { timestamp: 1700000105 }),
|
|
280
|
+
mapping: { silent: true },
|
|
281
|
+
out: []
|
|
282
|
+
};
|
|
283
|
+
var groupIdentifyWithoutData = {
|
|
284
|
+
public: false,
|
|
285
|
+
description: "A silent group rule whose key finds no data sends nothing: an unmet mapping, not a failure, so the push returns normally.",
|
|
286
|
+
in: {
|
|
287
|
+
name: "company update",
|
|
288
|
+
entity: "company",
|
|
289
|
+
action: "update",
|
|
290
|
+
timestamp: 1700000106
|
|
291
|
+
},
|
|
292
|
+
mapping: groupIdentifyWithProperties.mapping,
|
|
293
|
+
out: []
|
|
294
|
+
};
|
|
266
295
|
// Annotate the CommonJS export names for ESM import in node:
|
|
267
296
|
0 && (module.exports = {
|
|
268
297
|
env,
|
package/dist/examples/index.mjs
CHANGED
|
@@ -65,17 +65,20 @@ __export(step_exports, {
|
|
|
65
65
|
consentRevoke: () => consentRevoke,
|
|
66
66
|
defaultCapture: () => defaultCapture,
|
|
67
67
|
groupIdentifyWithProperties: () => groupIdentifyWithProperties,
|
|
68
|
-
|
|
68
|
+
groupIdentifyWithoutData: () => groupIdentifyWithoutData,
|
|
69
|
+
identifyWithSetAndSetOnce: () => identifyWithSetAndSetOnce,
|
|
70
|
+
silentRule: () => silentRule
|
|
69
71
|
});
|
|
70
|
-
import { getEvent } from "@walkeros/core";
|
|
72
|
+
import { createEvent, getEvent } from "@walkeros/core";
|
|
71
73
|
var defaultCapture = {
|
|
72
74
|
title: "Default capture",
|
|
73
75
|
description: "A walker event becomes a PostHog capture call with the user id as distinctId and no extra properties.",
|
|
74
|
-
in: getEvent("product view", { timestamp: 1700000100 }),
|
|
76
|
+
in: getEvent("product view", { id: "ev1700000100", timestamp: 1700000100 }),
|
|
75
77
|
out: [
|
|
76
78
|
[
|
|
77
79
|
"client.capture",
|
|
78
80
|
{
|
|
81
|
+
uuid: "b8a7f21f-1a9f-8aa7-8480-8d16fb64c44c",
|
|
79
82
|
distinctId: "us3r",
|
|
80
83
|
event: "product view",
|
|
81
84
|
properties: {}
|
|
@@ -86,12 +89,13 @@ var defaultCapture = {
|
|
|
86
89
|
var captureWithInclude = {
|
|
87
90
|
title: "Capture with include",
|
|
88
91
|
description: "Destination-level include flattens data and globals sections into prefixed PostHog event properties.",
|
|
89
|
-
in: getEvent("order complete", { timestamp: 1700000101 }),
|
|
92
|
+
in: getEvent("order complete", { id: "ev1700000101", timestamp: 1700000101 }),
|
|
90
93
|
configInclude: ["data", "globals"],
|
|
91
94
|
out: [
|
|
92
95
|
[
|
|
93
96
|
"client.capture",
|
|
94
97
|
{
|
|
98
|
+
uuid: "a5a5ede9-4f3b-85f4-b30f-3da8773fabfa",
|
|
95
99
|
distinctId: "us3r",
|
|
96
100
|
event: "order complete",
|
|
97
101
|
properties: {
|
|
@@ -99,7 +103,7 @@ var captureWithInclude = {
|
|
|
99
103
|
data_currency: "EUR",
|
|
100
104
|
data_shipping: 5.22,
|
|
101
105
|
data_taxes: 73.76,
|
|
102
|
-
|
|
106
|
+
data_value: 555,
|
|
103
107
|
globals_pagegroup: "shop"
|
|
104
108
|
}
|
|
105
109
|
}
|
|
@@ -109,7 +113,8 @@ var captureWithInclude = {
|
|
|
109
113
|
var identifyWithSetAndSetOnce = {
|
|
110
114
|
title: "Identify with $set",
|
|
111
115
|
description: "A user login fires PostHog identify with $set and $set_once person properties and skips the capture.",
|
|
112
|
-
in:
|
|
116
|
+
in: createEvent({
|
|
117
|
+
name: "user login",
|
|
113
118
|
timestamp: 1700000102,
|
|
114
119
|
data: {
|
|
115
120
|
user_id: "new-user-123",
|
|
@@ -159,7 +164,8 @@ var identifyWithSetAndSetOnce = {
|
|
|
159
164
|
var groupIdentifyWithProperties = {
|
|
160
165
|
title: "Group identify",
|
|
161
166
|
description: "A company update fires PostHog groupIdentify with group type, key, and associated group properties.",
|
|
162
|
-
in:
|
|
167
|
+
in: createEvent({
|
|
168
|
+
name: "company update",
|
|
163
169
|
timestamp: 1700000103,
|
|
164
170
|
data: {
|
|
165
171
|
company_id: "company_123",
|
|
@@ -202,6 +208,7 @@ var captureWithGroupContext = {
|
|
|
202
208
|
title: "Capture with group",
|
|
203
209
|
description: "A destination-level group mapping attaches the resolved group context to every PostHog capture call.",
|
|
204
210
|
in: getEvent("page view", {
|
|
211
|
+
id: "ev1700000104",
|
|
205
212
|
timestamp: 1700000104,
|
|
206
213
|
globals: { pagegroup: "docs", company_id: "company_123" }
|
|
207
214
|
}),
|
|
@@ -217,6 +224,7 @@ var captureWithGroupContext = {
|
|
|
217
224
|
[
|
|
218
225
|
"client.capture",
|
|
219
226
|
{
|
|
227
|
+
uuid: "c6a47305-44fc-8835-b15f-3f494c1f9e20",
|
|
220
228
|
distinctId: "us3r",
|
|
221
229
|
event: "page view",
|
|
222
230
|
properties: {},
|
|
@@ -225,12 +233,14 @@ var captureWithGroupContext = {
|
|
|
225
233
|
]
|
|
226
234
|
]
|
|
227
235
|
};
|
|
236
|
+
var analyticsDenied = { analytics: false };
|
|
237
|
+
var analyticsGranted = { analytics: true };
|
|
228
238
|
var consentRevoke = {
|
|
229
239
|
title: "Consent revoked",
|
|
230
240
|
description: "A walker consent command with analytics denied calls client.disable on the PostHog client.",
|
|
231
241
|
command: "consent",
|
|
232
242
|
before: { analytics: true },
|
|
233
|
-
in:
|
|
243
|
+
in: analyticsDenied,
|
|
234
244
|
settings: {},
|
|
235
245
|
out: [["client.enable"], ["client.disable"]]
|
|
236
246
|
};
|
|
@@ -238,10 +248,29 @@ var consentGrant = {
|
|
|
238
248
|
title: "Consent granted",
|
|
239
249
|
description: "A walker consent command with analytics granted calls client.enable on the PostHog client.",
|
|
240
250
|
command: "consent",
|
|
241
|
-
in:
|
|
251
|
+
in: analyticsGranted,
|
|
242
252
|
settings: {},
|
|
243
253
|
out: [["client.enable"]]
|
|
244
254
|
};
|
|
255
|
+
var silentRule = {
|
|
256
|
+
public: false,
|
|
257
|
+
description: "A rule with silent: true and no identify or group mapping sends nothing to PostHog.",
|
|
258
|
+
in: getEvent("page view", { timestamp: 1700000105 }),
|
|
259
|
+
mapping: { silent: true },
|
|
260
|
+
out: []
|
|
261
|
+
};
|
|
262
|
+
var groupIdentifyWithoutData = {
|
|
263
|
+
public: false,
|
|
264
|
+
description: "A silent group rule whose key finds no data sends nothing: an unmet mapping, not a failure, so the push returns normally.",
|
|
265
|
+
in: {
|
|
266
|
+
name: "company update",
|
|
267
|
+
entity: "company",
|
|
268
|
+
action: "update",
|
|
269
|
+
timestamp: 1700000106
|
|
270
|
+
},
|
|
271
|
+
mapping: groupIdentifyWithProperties.mapping,
|
|
272
|
+
out: []
|
|
273
|
+
};
|
|
245
274
|
export {
|
|
246
275
|
env_exports as env,
|
|
247
276
|
step_exports as step
|
package/dist/index.d.mts
CHANGED
|
@@ -11,8 +11,6 @@ interface Settings {
|
|
|
11
11
|
identify?: Mapping$1.Value;
|
|
12
12
|
/** Destination-level group mapping */
|
|
13
13
|
group?: Mapping$1.Value;
|
|
14
|
-
/** Event sections to flatten into capture properties */
|
|
15
|
-
include?: string[];
|
|
16
14
|
host?: string;
|
|
17
15
|
flushAt?: number;
|
|
18
16
|
flushInterval?: number;
|
|
@@ -25,6 +23,8 @@ interface Settings {
|
|
|
25
23
|
fetchRetryDelay?: number;
|
|
26
24
|
debug?: boolean;
|
|
27
25
|
disabled?: boolean;
|
|
26
|
+
/** The running send; the next one waits for it. Runtime only. */
|
|
27
|
+
_sending?: Promise<void>;
|
|
28
28
|
}
|
|
29
29
|
type InitSettings = Partial<Settings>;
|
|
30
30
|
interface Mapping {
|
|
@@ -40,6 +40,10 @@ interface PostHogClient {
|
|
|
40
40
|
capture(props: Parameters<PostHog['capture']>[0]): void;
|
|
41
41
|
identify(props: Parameters<PostHog['identify']>[0]): void;
|
|
42
42
|
groupIdentify(props: Parameters<PostHog['groupIdentify']>[0]): void;
|
|
43
|
+
/** Sends the queued calls; rejects when the request failed. */
|
|
44
|
+
flush(): Promise<void>;
|
|
45
|
+
/** The SDK reports a failed send as an `error` event; returns its remover. */
|
|
46
|
+
on?(event: 'error', listener: (error: unknown) => void): () => void;
|
|
43
47
|
shutdown(): Promise<void> | void;
|
|
44
48
|
enable(): Promise<void> | void;
|
|
45
49
|
disable(): Promise<void> | void;
|
|
@@ -56,6 +60,7 @@ type Config = {
|
|
|
56
60
|
} & DestinationServer.Config<Types>;
|
|
57
61
|
type InitFn = DestinationServer.InitFn<Types>;
|
|
58
62
|
type PushFn = DestinationServer.PushFn<Types>;
|
|
63
|
+
type PushBatchFn = Destination$1.PushBatchFn<Types>;
|
|
59
64
|
type PartialConfig = DestinationServer.PartialConfig<Types>;
|
|
60
65
|
type PushEvents = DestinationServer.PushEvents<Mapping>;
|
|
61
66
|
type Rule = Mapping$1.Rule<Mapping>;
|
|
@@ -69,6 +74,7 @@ type index_InitSettings = InitSettings;
|
|
|
69
74
|
type index_Mapping = Mapping;
|
|
70
75
|
type index_PartialConfig = PartialConfig;
|
|
71
76
|
type index_PostHogClient = PostHogClient;
|
|
77
|
+
type index_PushBatchFn = PushBatchFn;
|
|
72
78
|
type index_PushEvents = PushEvents;
|
|
73
79
|
type index_PushFn = PushFn;
|
|
74
80
|
type index_Rule = Rule;
|
|
@@ -76,7 +82,7 @@ type index_Rules = Rules;
|
|
|
76
82
|
type index_Settings = Settings;
|
|
77
83
|
type index_Types = Types;
|
|
78
84
|
declare namespace index {
|
|
79
|
-
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_PartialConfig as PartialConfig, index_PostHogClient as PostHogClient, index_PushEvents as PushEvents, index_PushFn as PushFn, index_Rule as Rule, index_Rules as Rules, index_Settings as Settings, index_Types as Types };
|
|
85
|
+
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_PartialConfig as PartialConfig, index_PostHogClient as PostHogClient, index_PushBatchFn as PushBatchFn, index_PushEvents as PushEvents, index_PushFn as PushFn, index_Rule as Rule, index_Rules as Rules, index_Settings as Settings, index_Types as Types };
|
|
80
86
|
}
|
|
81
87
|
|
|
82
88
|
declare const destinationPostHog: Destination;
|
package/dist/index.d.ts
CHANGED
|
@@ -11,8 +11,6 @@ interface Settings {
|
|
|
11
11
|
identify?: Mapping$1.Value;
|
|
12
12
|
/** Destination-level group mapping */
|
|
13
13
|
group?: Mapping$1.Value;
|
|
14
|
-
/** Event sections to flatten into capture properties */
|
|
15
|
-
include?: string[];
|
|
16
14
|
host?: string;
|
|
17
15
|
flushAt?: number;
|
|
18
16
|
flushInterval?: number;
|
|
@@ -25,6 +23,8 @@ interface Settings {
|
|
|
25
23
|
fetchRetryDelay?: number;
|
|
26
24
|
debug?: boolean;
|
|
27
25
|
disabled?: boolean;
|
|
26
|
+
/** The running send; the next one waits for it. Runtime only. */
|
|
27
|
+
_sending?: Promise<void>;
|
|
28
28
|
}
|
|
29
29
|
type InitSettings = Partial<Settings>;
|
|
30
30
|
interface Mapping {
|
|
@@ -40,6 +40,10 @@ interface PostHogClient {
|
|
|
40
40
|
capture(props: Parameters<PostHog['capture']>[0]): void;
|
|
41
41
|
identify(props: Parameters<PostHog['identify']>[0]): void;
|
|
42
42
|
groupIdentify(props: Parameters<PostHog['groupIdentify']>[0]): void;
|
|
43
|
+
/** Sends the queued calls; rejects when the request failed. */
|
|
44
|
+
flush(): Promise<void>;
|
|
45
|
+
/** The SDK reports a failed send as an `error` event; returns its remover. */
|
|
46
|
+
on?(event: 'error', listener: (error: unknown) => void): () => void;
|
|
43
47
|
shutdown(): Promise<void> | void;
|
|
44
48
|
enable(): Promise<void> | void;
|
|
45
49
|
disable(): Promise<void> | void;
|
|
@@ -56,6 +60,7 @@ type Config = {
|
|
|
56
60
|
} & DestinationServer.Config<Types>;
|
|
57
61
|
type InitFn = DestinationServer.InitFn<Types>;
|
|
58
62
|
type PushFn = DestinationServer.PushFn<Types>;
|
|
63
|
+
type PushBatchFn = Destination$1.PushBatchFn<Types>;
|
|
59
64
|
type PartialConfig = DestinationServer.PartialConfig<Types>;
|
|
60
65
|
type PushEvents = DestinationServer.PushEvents<Mapping>;
|
|
61
66
|
type Rule = Mapping$1.Rule<Mapping>;
|
|
@@ -69,6 +74,7 @@ type index_InitSettings = InitSettings;
|
|
|
69
74
|
type index_Mapping = Mapping;
|
|
70
75
|
type index_PartialConfig = PartialConfig;
|
|
71
76
|
type index_PostHogClient = PostHogClient;
|
|
77
|
+
type index_PushBatchFn = PushBatchFn;
|
|
72
78
|
type index_PushEvents = PushEvents;
|
|
73
79
|
type index_PushFn = PushFn;
|
|
74
80
|
type index_Rule = Rule;
|
|
@@ -76,7 +82,7 @@ type index_Rules = Rules;
|
|
|
76
82
|
type index_Settings = Settings;
|
|
77
83
|
type index_Types = Types;
|
|
78
84
|
declare namespace index {
|
|
79
|
-
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_PartialConfig as PartialConfig, index_PostHogClient as PostHogClient, index_PushEvents as PushEvents, index_PushFn as PushFn, index_Rule as Rule, index_Rules as Rules, index_Settings as Settings, index_Types as Types };
|
|
85
|
+
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_PartialConfig as PartialConfig, index_PostHogClient as PostHogClient, index_PushBatchFn as PushBatchFn, index_PushEvents as PushEvents, index_PushFn as PushFn, index_Rule as Rule, index_Rules as Rules, index_Settings as Settings, index_Types as Types };
|
|
80
86
|
}
|
|
81
87
|
|
|
82
88
|
declare const destinationPostHog: Destination;
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var mod,__defProp=Object.defineProperty,__getOwnPropDesc=Object.getOwnPropertyDescriptor,__getOwnPropNames=Object.getOwnPropertyNames,__hasOwnProp=Object.prototype.hasOwnProperty,index_exports={};((target,all)=>{for(var name in all)__defProp(target,name,{get:all[name],enumerable:!0})})(index_exports,{DestinationPostHog:()=>types_exports,default:()=>index_default,destinationPostHog:()=>destinationPostHog}),module.exports=(mod=index_exports,((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})(__defProp({},"__esModule",{value:!0}),mod));var import_posthog_node=require("posthog-node");var
|
|
1
|
+
"use strict";var mod,__defProp=Object.defineProperty,__getOwnPropDesc=Object.getOwnPropertyDescriptor,__getOwnPropNames=Object.getOwnPropertyNames,__hasOwnProp=Object.prototype.hasOwnProperty,index_exports={};((target,all)=>{for(var name in all)__defProp(target,name,{get:all[name],enumerable:!0})})(index_exports,{DestinationPostHog:()=>types_exports,default:()=>index_default,destinationPostHog:()=>destinationPostHog}),module.exports=(mod=index_exports,((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})(__defProp({},"__esModule",{value:!0}),mod));var import_core=require("@walkeros/core"),import_server_core=require("@walkeros/server-core"),import_posthog_node=require("posthog-node");var import_crypto=require("crypto"),import_core2=require("@walkeros/core"),import_server_core2=require("@walkeros/server-core");async function call(client,message,send2){let failure;const off=client.on?.("error",error=>{failure=failure??error});try{await send2()}catch(error){failure=failure??error}finally{off?.()}if(void 0!==failure)throw new import_core2.StepError(message,{code:timedOut(failure)?"timeout":"transport",cause:failure})}function timedOut(error){if("object"!=typeof error||null===error)return!1;const name=Reflect.get(error,"name");return"AbortError"===name||"TimeoutError"===name||timedOut(Reflect.get(error,"error")??Reflect.get(error,"cause"))}function skipped(logger,event,call2,key){logger.debug(`PostHog skipped ${call2}: ${key} resolved to nothing`,{event:event.name})}async function queue(message,send2){try{await send2()}catch(error){throw new import_core2.StepError(message,{code:"transport",cause:error})}}function exclusive(settings,task){const running=(settings._sending??Promise.resolve()).then(task);return settings._sending=running.catch(()=>{}),running}function clientOf(settings){const client=settings?.client;if(!settings||!client)throw new import_core2.StepError("PostHog client not initialized",{code:"not-ready"});return{settings:settings,client:client}}async function send(event,rule,data,settings,client,collector,logger){const mappingSettings=rule?.settings||{},identifyMapping=mappingSettings.identify??settings.identify;let distinctId,identifyResolved;if(void 0!==identifyMapping){const resolved=await(0,import_core2.getMappingValue)(event,identifyMapping,{collector:collector});(0,import_core2.isObject)(resolved)?(identifyResolved=resolved,(0,import_core2.isString)(identifyResolved.distinctId)&&(distinctId=identifyResolved.distinctId)):skipped(logger,event,"identify","identify")}if(distinctId||(distinctId=((0,import_core2.isString)(event.user?.id)?event.user.id:void 0)||((0,import_core2.isString)(event.user?.hash)?event.user.hash:void 0)||((0,import_core2.isString)(event.user?.session)?event.user.session:void 0)||"anonymous"),identifyResolved){const $set=(0,import_core2.isObject)(identifyResolved.$set)?identifyResolved.$set:void 0,$setOnce=(0,import_core2.isObject)(identifyResolved.$set_once)?identifyResolved.$set_once:void 0;if($set||$setOnce){const properties={};$set&&(properties.$set=$set),$setOnce&&(properties.$set_once=$setOnce),await queue("PostHog identify failed",()=>client.identify({distinctId:distinctId,properties:properties}))}}const groupMapping=mappingSettings.group??settings.group;let groups;if(void 0!==groupMapping){const resolved=await(0,import_core2.getMappingValue)(event,groupMapping,{collector:collector});if((0,import_core2.isObject)(resolved)){const groupResolved=resolved,type=groupResolved.type,key=groupResolved.key,properties=(0,import_core2.isObject)(groupResolved.properties)?groupResolved.properties:void 0;(0,import_core2.isString)(type)&&((0,import_core2.isString)(key)||"number"==typeof key)?(properties&&await queue("PostHog group identify failed",()=>client.groupIdentify({groupType:type,groupKey:String(key),properties:properties})),groups={[type]:key}):skipped(logger,event,"group","group")}else skipped(logger,event,"group","group")}if(!0!==rule?.silent){const eventName=(0,import_core2.isString)(rule?.name)?rule.name:event.name,properties=(0,import_core2.isObject)(data)?data:{},captureArgs={distinctId:distinctId,event:eventName,properties:properties};groups&&(captureArgs.groups=groups),event.id&&(captureArgs.uuid=function(id){const hex=(0,import_crypto.createHash)("sha256").update(id).digest("hex"),variant=(3&parseInt(hex[16],16)|8).toString(16);return[hex.slice(0,8),hex.slice(8,12),`8${hex.slice(13,16)}`,`${variant}${hex.slice(17,20)}`,hex.slice(20,32)].join("-")}(event.id)),await queue("PostHog capture failed",()=>client.capture(captureArgs))}}var types_exports={},destinationPostHog={type:"posthog",config:{batch:{size:20,wait:1e4}},init:async({config:partialConfig,env:env})=>function(partialConfig={},env){const settings=partialConfig.settings||{},{apiKey:apiKey}=settings;if(!apiKey)throw new import_core.StepError("Config settings apiKey missing",{code:"config"});const budget=(0,import_server_core.retryBudget)(partialConfig.timeout),options={requestTimeout:budget.attempt,fetchRetryCount:budget.retries,fetchRetryDelay:budget.wait};settings.host&&(options.host=settings.host),void 0!==settings.flushAt&&(options.flushAt=settings.flushAt),void 0!==settings.flushInterval&&(options.flushInterval=settings.flushInterval),settings.personalApiKey&&(options.personalApiKey=settings.personalApiKey),void 0!==settings.featureFlagsPollingInterval&&(options.featureFlagsPollingInterval=settings.featureFlagsPollingInterval),void 0!==settings.disableGeoip&&(options.disableGeoip=settings.disableGeoip),void 0!==settings.disableCompression&&(options.disableCompression=settings.disableCompression),void 0!==settings.requestTimeout&&(options.requestTimeout=settings.requestTimeout),void 0!==settings.fetchRetryCount&&(options.fetchRetryCount=settings.fetchRetryCount),void 0!==settings.fetchRetryDelay&&(options.fetchRetryDelay=settings.fetchRetryDelay),void 0!==settings.debug&&(options.debug=settings.debug),void 0!==settings.disabled&&(options.disabled=settings.disabled);const client=new(env?.PostHog||import_posthog_node.PostHog)(apiKey,options),settingsConfig={...settings,apiKey:apiKey,client:client};return{...partialConfig,settings:settingsConfig}}(partialConfig,env),push:async function(event,{config:config,rule:rule,data:data,collector:collector,logger:logger}){const{settings:settings,client:client}=clientOf(config.settings);await exclusive(settings,async()=>{await send(event,rule,data,settings,client,collector,logger),await call(client,"PostHog send failed",()=>client.flush())})},pushBatch:async function(batch,{config:config,collector:collector,logger:logger}){const{settings:settings,client:client}=clientOf(config.settings),failed=[];let sendError;return await exclusive(settings,async()=>{const queued=[];for(const[index,entry]of batch.entries.entries())await send(entry.event,entry.rule,entry.data,settings,client,collector,logger).then(()=>queued.push(index),error=>failed.push({index:index,error:error}));queued.length&&await call(client,"PostHog send failed",()=>client.flush()).catch(error=>{sendError=error;for(const index of queued)failed.push({index:index,error:error})})}),(0,import_server_core2.batchOutcome)(batch.entries.length,failed,sendError)},async destroy({config:config}){const client=config?.settings?.client;client&&await client.shutdown()},on(type,context){if("consent"!==type||!context?.data)return;const client=(context.config?.settings||{}).client;if(!client)return;const consent=context.data,required=context.config?.consent;if(!required||0===Object.keys(required).length)return;Object.keys(required).every(key=>!0===consent[key])?client.enable():client.disable()}},index_default=destinationPostHog;//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/config.ts","../src/push.ts","../src/types/index.ts"],"sourcesContent":["import type { WalkerOS } from '@walkeros/core';\nimport type { Destination, Env, Settings } from './types';\nimport { getConfig } from './config';\nimport { push } from './push';\n\n// Types\nexport * as DestinationPostHog from './types';\n\nexport const destinationPostHog: Destination = {\n type: 'posthog',\n\n config: {},\n\n async init({ config: partialConfig, env, logger }) {\n const config = getConfig(partialConfig, env as Env | undefined, logger);\n return config;\n },\n\n async push(event, context) {\n return await push(event, context);\n },\n\n async destroy({ config }) {\n const client = (config?.settings as Settings | undefined)?.client;\n if (client) {\n await client.shutdown();\n }\n },\n\n on(type, context) {\n if (type !== 'consent' || !context?.data) return;\n\n const settings = (context.config?.settings || {}) as Settings;\n const client = settings.client;\n if (!client) return;\n\n const consent = context.data as WalkerOS.Consent;\n const required = (context.config as { consent?: WalkerOS.Consent })\n ?.consent;\n if (!required || Object.keys(required).length === 0) return;\n\n const allGranted = Object.keys(required).every(\n (key) => consent[key] === true,\n );\n if (allGranted) {\n client.enable();\n } else {\n client.disable();\n }\n },\n};\n\nexport default destinationPostHog;\n","import type { Config, Env, PartialConfig, Settings } from './types';\nimport type { Logger } from '@walkeros/core';\nimport { PostHog } from 'posthog-node';\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 // Extract PostHog SDK options from settings\n const options: Record<string, unknown> = {};\n if (settings.host) options.host = settings.host;\n if (settings.flushAt !== undefined) options.flushAt = settings.flushAt;\n if (settings.flushInterval !== undefined)\n options.flushInterval = settings.flushInterval;\n if (settings.personalApiKey) options.personalApiKey = settings.personalApiKey;\n if (settings.featureFlagsPollingInterval !== undefined)\n options.featureFlagsPollingInterval = settings.featureFlagsPollingInterval;\n if (settings.disableGeoip !== undefined)\n options.disableGeoip = settings.disableGeoip;\n if (settings.disableCompression !== undefined)\n options.disableCompression = settings.disableCompression;\n if (settings.requestTimeout !== undefined)\n options.requestTimeout = settings.requestTimeout;\n if (settings.fetchRetryCount !== undefined)\n options.fetchRetryCount = settings.fetchRetryCount;\n if (settings.fetchRetryDelay !== undefined)\n options.fetchRetryDelay = settings.fetchRetryDelay;\n if (settings.debug !== undefined) options.debug = settings.debug;\n if (settings.disabled !== undefined) options.disabled = settings.disabled;\n\n // Use PostHog from env if available, otherwise use real PostHog\n const PostHogClass = env?.PostHog || PostHog;\n const client = new PostHogClass(apiKey, options);\n\n const settingsConfig: Settings = {\n ...settings,\n apiKey,\n client,\n };\n\n return { ...partialConfig, settings: settingsConfig };\n}\n","import type { PushFn } from './types';\nimport { getMappingValue, isObject, isString } from '@walkeros/core';\n\nexport const push: PushFn = async function (\n event,\n { config, rule, data, collector },\n) {\n const settings = config.settings!;\n const client = settings.client;\n if (!client) return;\n\n const mappingSettings = (rule?.settings || {}) as Record<string, unknown>;\n\n // Resolve distinctId: rule-level identify wins over destination-level\n const identifyMapping = mappingSettings.identify ?? settings.identify;\n let distinctId: string | undefined;\n let identifyResolved: Record<string, unknown> | undefined;\n\n if (identifyMapping !== undefined) {\n const resolved = await getMappingValue(event, identifyMapping, {\n collector,\n });\n if (isObject(resolved)) {\n identifyResolved = resolved as Record<string, unknown>;\n if (isString(identifyResolved.distinctId)) {\n distinctId = identifyResolved.distinctId as string;\n }\n }\n }\n\n // Fallback distinctId from event.user\n if (!distinctId) {\n distinctId =\n (isString(event.user?.id) ? event.user.id : undefined) ||\n (isString(event.user?.hash) ? event.user.hash : undefined) ||\n (isString(event.user?.session) ? event.user.session : undefined) ||\n 'anonymous';\n }\n\n // 1. Identity - if $set or $set_once present, call client.identify()\n if (identifyResolved) {\n const $set = isObject(identifyResolved.$set)\n ? (identifyResolved.$set as Record<string, unknown>)\n : undefined;\n const $setOnce = isObject(identifyResolved.$set_once)\n ? (identifyResolved.$set_once as Record<string, unknown>)\n : undefined;\n\n if ($set || $setOnce) {\n const properties: Record<string, unknown> = {};\n if ($set) properties.$set = $set;\n if ($setOnce) properties.$set_once = $setOnce;\n client.identify({ distinctId, properties });\n }\n }\n\n // 2. Group - resolve group mapping (rule-level wins)\n const groupMapping = mappingSettings.group ?? settings.group;\n let groups: Record<string, string | number> | undefined;\n\n if (groupMapping !== undefined) {\n const resolved = await getMappingValue(event, groupMapping, {\n collector,\n });\n if (isObject(resolved)) {\n const groupResolved = resolved as Record<string, unknown>;\n const type = groupResolved.type;\n const key = groupResolved.key;\n const properties = isObject(groupResolved.properties)\n ? (groupResolved.properties as Record<string, unknown>)\n : undefined;\n\n if (isString(type) && (isString(key) || typeof key === 'number')) {\n // If properties present, call groupIdentify\n if (properties) {\n client.groupIdentify({\n groupType: type,\n groupKey: String(key),\n properties,\n });\n }\n // Build groups object for capture\n groups = { [type]: key as string | number };\n }\n }\n }\n\n // 3. Capture - unless rule opts out via silent\n if (rule?.silent !== true) {\n const eventName = isString(rule?.name) ? rule.name : event.name;\n const properties = isObject(data) ? (data as Record<string, unknown>) : {};\n\n const captureArgs: Record<string, unknown> = {\n distinctId,\n event: eventName,\n properties,\n };\n if (groups) captureArgs.groups = groups;\n\n client.capture(captureArgs as Parameters<typeof client.capture>[0]);\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 { PostHog } from 'posthog-node';\n\nexport interface Settings {\n /** PostHog project API key (phc_...) */\n apiKey: string;\n /** PostHog client instance, populated by init */\n client?: PostHogClient;\n /** Destination-level identity mapping */\n identify?: WalkerOSMapping.Value;\n /** Destination-level group mapping */\n group?: WalkerOSMapping.Value;\n /** Event sections to flatten into capture properties */\n include?: string[];\n // PostHog SDK passthrough options\n host?: string;\n flushAt?: number;\n flushInterval?: number;\n personalApiKey?: string;\n featureFlagsPollingInterval?: number;\n disableGeoip?: boolean;\n disableCompression?: boolean;\n requestTimeout?: number;\n fetchRetryCount?: number;\n fetchRetryDelay?: number;\n debug?: boolean;\n disabled?: boolean;\n}\n\nexport type InitSettings = Partial<Settings>;\n\nexport interface Mapping {\n identify?: WalkerOSMapping.Value;\n group?: WalkerOSMapping.Value;\n}\n\n/**\n * The part of a PostHog client this destination calls. `PostHog` from\n * `posthog-node` satisfies it, and so does an injected mock (tests, simulate)\n * without a cast.\n */\nexport interface PostHogClient {\n capture(props: Parameters<PostHog['capture']>[0]): void;\n identify(props: Parameters<PostHog['identify']>[0]): void;\n groupIdentify(props: Parameters<PostHog['groupIdentify']>[0]): void;\n shutdown(): Promise<void> | void;\n enable(): Promise<void> | void;\n disable(): Promise<void> | void;\n}\n\nexport interface Env extends DestinationServer.Env {\n PostHog?: new (\n apiKey: string,\n options?: ConstructorParameters<typeof PostHog>[1],\n ) => PostHogClient;\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":[]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/config.ts","../src/push.ts","../src/types/index.ts"],"sourcesContent":["import type { WalkerOS } from '@walkeros/core';\nimport type { Destination, Env, Settings } from './types';\nimport { getConfig } from './config';\nimport { push, pushBatch } from './push';\n\n// Types\nexport * as DestinationPostHog from './types';\n\nexport const destinationPostHog: Destination = {\n type: 'posthog',\n\n // Batched by default, at the SDK's own former defaults (20 events, 10 s).\n config: { batch: { size: 20, wait: 10_000 } },\n\n async init({ config: partialConfig, env }) {\n return getConfig(partialConfig, env);\n },\n\n push,\n\n pushBatch,\n\n async destroy({ config }) {\n const client = config?.settings?.client;\n if (client) {\n await client.shutdown();\n }\n },\n\n on(type, context) {\n if (type !== 'consent' || !context?.data) return;\n\n const settings = (context.config?.settings || {}) as Settings;\n const client = settings.client;\n if (!client) return;\n\n const consent = context.data as WalkerOS.Consent;\n const required = (context.config as { consent?: WalkerOS.Consent })\n ?.consent;\n if (!required || Object.keys(required).length === 0) return;\n\n const allGranted = Object.keys(required).every(\n (key) => consent[key] === true,\n );\n if (allGranted) {\n client.enable();\n } else {\n client.disable();\n }\n },\n};\n\nexport default destinationPostHog;\n","import type { Config, Env, PartialConfig, Settings } from './types';\nimport { StepError } from '@walkeros/core';\nimport { retryBudget } from '@walkeros/server-core';\nimport { PostHog } from 'posthog-node';\n\nexport function getConfig(\n partialConfig: PartialConfig = {},\n env: Env | undefined,\n): Config {\n const settings: Partial<Settings> = partialConfig.settings || {};\n const { apiKey } = settings;\n\n if (!apiKey)\n throw new StepError('Config settings apiKey missing', { code: 'config' });\n\n // The SDK's own retry ends within config.timeout: a quarter of it per\n // request, two retries a tenth of it apart. A value set in the settings\n // wins.\n const budget = retryBudget(partialConfig.timeout);\n const options: Record<string, unknown> = {\n requestTimeout: budget.attempt,\n fetchRetryCount: budget.retries,\n fetchRetryDelay: budget.wait,\n };\n\n // Extract PostHog SDK options from settings\n if (settings.host) options.host = settings.host;\n if (settings.flushAt !== undefined) options.flushAt = settings.flushAt;\n if (settings.flushInterval !== undefined)\n options.flushInterval = settings.flushInterval;\n if (settings.personalApiKey) options.personalApiKey = settings.personalApiKey;\n if (settings.featureFlagsPollingInterval !== undefined)\n options.featureFlagsPollingInterval = settings.featureFlagsPollingInterval;\n if (settings.disableGeoip !== undefined)\n options.disableGeoip = settings.disableGeoip;\n if (settings.disableCompression !== undefined)\n options.disableCompression = settings.disableCompression;\n if (settings.requestTimeout !== undefined)\n options.requestTimeout = settings.requestTimeout;\n if (settings.fetchRetryCount !== undefined)\n options.fetchRetryCount = settings.fetchRetryCount;\n if (settings.fetchRetryDelay !== undefined)\n options.fetchRetryDelay = settings.fetchRetryDelay;\n if (settings.debug !== undefined) options.debug = settings.debug;\n if (settings.disabled !== undefined) options.disabled = settings.disabled;\n\n // Use PostHog from env if available, otherwise use real PostHog\n const PostHogClass = env?.PostHog || PostHog;\n const client = new PostHogClass(apiKey, options);\n\n const settingsConfig: Settings = {\n ...settings,\n apiKey,\n client,\n };\n\n return { ...partialConfig, settings: settingsConfig };\n}\n","import type { Collector, Destination, Logger, WalkerOS } from '@walkeros/core';\nimport type {\n PostHogClient,\n PushBatchFn,\n PushFn,\n Rule,\n Settings,\n} from './types';\nimport { createHash } from 'crypto';\nimport { getMappingValue, isObject, isString, StepError } from '@walkeros/core';\nimport { batchOutcome } from '@walkeros/server-core';\n\n/**\n * Run one flush to its end. The SDK reports a failed send as an `error`\n * event and a rejected flush; the call listens for the event while it runs.\n * Sends never overlap (`exclusive`), so the event belongs to this flush.\n */\nasync function call(\n client: PostHogClient,\n message: string,\n send: () => unknown,\n): Promise<void> {\n let failure: unknown;\n const off = client.on?.('error', (error) => {\n failure = failure ?? error;\n });\n try {\n await send();\n } catch (error) {\n failure = failure ?? error;\n } finally {\n off?.();\n }\n if (failure !== undefined)\n throw new StepError(message, {\n code: timedOut(failure) ? 'timeout' : 'transport',\n cause: failure,\n });\n}\n\n/**\n * Whether the SDK's last request timed out: it aborts a request after\n * `requestTimeout` and reports a network error carrying the abort.\n */\nfunction timedOut(error: unknown): boolean {\n if (typeof error !== 'object' || error === null) return false;\n const name: unknown = Reflect.get(error, 'name');\n if (name === 'AbortError' || name === 'TimeoutError') return true;\n return timedOut(Reflect.get(error, 'error') ?? Reflect.get(error, 'cause'));\n}\n\n/**\n * The uuid PostHog deduplicates a captured event by, derived from the event\n * id: the same event resent gets the same uuid. PostHog takes only a UUID,\n * so the id is hashed into one (RFC 9562 version 8, name based).\n */\nfunction uuidOf(id: string): string {\n const hex = createHash('sha256').update(id).digest('hex');\n const variant = ((parseInt(hex[16], 16) & 0x3) | 0x8).toString(16);\n return [\n hex.slice(0, 8),\n hex.slice(8, 12),\n `8${hex.slice(13, 16)}`,\n `${variant}${hex.slice(17, 20)}`,\n hex.slice(20, 32),\n ].join('-');\n}\n\n/**\n * A configured mapping that resolved to nothing skips its call: a declared\n * skip, said once at DEBUG with the event and the mapping key, never the\n * value, so a wrong mapping path does not look like an event without data.\n */\nfunction skipped(\n logger: Logger.Instance,\n event: WalkerOS.Event,\n call: string,\n key: string,\n): void {\n logger.debug(`PostHog skipped ${call}: ${key} resolved to nothing`, {\n event: event.name,\n });\n}\n\n/** Run one queueing call; an injected client may answer with a promise. */\nasync function queue(message: string, send: () => unknown): Promise<void> {\n try {\n await send();\n } catch (error) {\n throw new StepError(message, { code: 'transport', cause: error });\n }\n}\n\n/**\n * One send at a time per client: its calls queued, then one flush. A flush\n * sends the whole queue, so a send that overlapped another could be carried,\n * and failed, by the other's request without hearing of it.\n */\nfunction exclusive(\n settings: Partial<Settings>,\n task: () => Promise<void>,\n): Promise<void> {\n const running = (settings._sending ?? Promise.resolve()).then(task);\n settings._sending = running.catch(() => undefined);\n return running;\n}\n\n/** The settings and client init resolved, or a StepError. */\nfunction clientOf(settings: Partial<Settings> | undefined): {\n settings: Partial<Settings>;\n client: PostHogClient;\n} {\n const client = settings?.client;\n if (!settings || !client)\n throw new StepError('PostHog client not initialized', {\n code: 'not-ready',\n });\n return { settings, client };\n}\n\n/** One event: its calls queued and sent by one flush. */\nexport const push: PushFn = async function (\n event,\n { config, rule, data, collector, logger },\n) {\n const { settings, client } = clientOf(config.settings);\n await exclusive(settings, async () => {\n await send(event, rule, data, settings, client, collector, logger);\n await call(client, 'PostHog send failed', () => client.flush());\n });\n};\n\n/**\n * A flushed `config.batch` batch: every entry's calls queued, then one flush\n * sends them. An entry whose calls could not be queued fails alone; a failed\n * flush fails the batch, since PostHog answers a request as a whole.\n */\nexport const pushBatch: PushBatchFn = async function (\n batch,\n { config, collector, logger },\n) {\n const { settings, client } = clientOf(config.settings);\n const failed: Destination.BatchFailure[] = [];\n let sendError: unknown;\n\n await exclusive(settings, async () => {\n const queued: number[] = [];\n for (const [index, entry] of batch.entries.entries())\n await send(\n entry.event,\n entry.rule,\n entry.data,\n settings,\n client,\n collector,\n logger,\n ).then(\n () => queued.push(index),\n (error: unknown) => failed.push({ index, error }),\n );\n\n // One request carries every queued entry: a failed flush fails them all.\n if (queued.length)\n await call(client, 'PostHog send failed', () => client.flush()).catch(\n (error: unknown) => {\n sendError = error;\n for (const index of queued) failed.push({ index, error });\n },\n );\n });\n\n return batchOutcome(batch.entries.length, failed, sendError);\n};\n\n/** The calls of one event (identify, group identify, capture). */\nasync function send(\n event: WalkerOS.Event,\n rule: Rule | undefined,\n data: Destination.Data,\n settings: Partial<Settings>,\n client: PostHogClient,\n collector: Collector.Instance,\n logger: Logger.Instance,\n): Promise<void> {\n const mappingSettings = (rule?.settings || {}) as Record<string, unknown>;\n\n // Resolve distinctId: rule-level identify wins over destination-level\n const identifyMapping = mappingSettings.identify ?? settings.identify;\n let distinctId: string | undefined;\n let identifyResolved: Record<string, unknown> | undefined;\n\n if (identifyMapping !== undefined) {\n const resolved = await getMappingValue(event, identifyMapping, {\n collector,\n });\n if (isObject(resolved)) {\n identifyResolved = resolved as Record<string, unknown>;\n if (isString(identifyResolved.distinctId)) {\n distinctId = identifyResolved.distinctId as string;\n }\n } else skipped(logger, event, 'identify', 'identify');\n }\n\n // Fallback distinctId from event.user\n if (!distinctId) {\n distinctId =\n (isString(event.user?.id) ? event.user.id : undefined) ||\n (isString(event.user?.hash) ? event.user.hash : undefined) ||\n (isString(event.user?.session) ? event.user.session : undefined) ||\n 'anonymous';\n }\n\n // 1. Identity - if $set or $set_once present, call client.identify()\n if (identifyResolved) {\n const $set = isObject(identifyResolved.$set)\n ? (identifyResolved.$set as Record<string, unknown>)\n : undefined;\n const $setOnce = isObject(identifyResolved.$set_once)\n ? (identifyResolved.$set_once as Record<string, unknown>)\n : undefined;\n\n if ($set || $setOnce) {\n const properties: Record<string, unknown> = {};\n if ($set) properties.$set = $set;\n if ($setOnce) properties.$set_once = $setOnce;\n await queue('PostHog identify failed', () =>\n client.identify({ distinctId, properties }),\n );\n }\n }\n\n // 2. Group - resolve group mapping (rule-level wins)\n const groupMapping = mappingSettings.group ?? settings.group;\n let groups: Record<string, string | number> | undefined;\n\n if (groupMapping !== undefined) {\n const resolved = await getMappingValue(event, groupMapping, {\n collector,\n });\n if (isObject(resolved)) {\n const groupResolved = resolved as Record<string, unknown>;\n const type = groupResolved.type;\n const key = groupResolved.key;\n const properties = isObject(groupResolved.properties)\n ? (groupResolved.properties as Record<string, unknown>)\n : undefined;\n\n if (isString(type) && (isString(key) || typeof key === 'number')) {\n // If properties present, call groupIdentify\n // No immediate variant: queued, then flushed in this push.\n if (properties)\n await queue('PostHog group identify failed', () =>\n client.groupIdentify({\n groupType: type,\n groupKey: String(key),\n properties,\n }),\n );\n // Build groups object for capture\n groups = { [type]: key as string | number };\n } else skipped(logger, event, 'group', 'group');\n } else skipped(logger, event, 'group', 'group');\n }\n\n // 3. Capture - unless rule opts out via silent\n if (rule?.silent !== true) {\n const eventName = isString(rule?.name) ? rule.name : event.name;\n const properties = isObject(data) ? (data as Record<string, unknown>) : {};\n\n const captureArgs: Parameters<PostHogClient['capture']>[0] = {\n distinctId,\n event: eventName,\n properties,\n };\n if (groups) captureArgs.groups = groups;\n if (event.id) captureArgs.uuid = uuidOf(event.id);\n\n await queue('PostHog capture failed', () => client.capture(captureArgs));\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 { PostHog } from 'posthog-node';\n\nexport interface Settings {\n /** PostHog project API key (phc_...) */\n apiKey: string;\n /** PostHog client instance, populated by init */\n client?: PostHogClient;\n /** Destination-level identity mapping */\n identify?: WalkerOSMapping.Value;\n /** Destination-level group mapping */\n group?: WalkerOSMapping.Value;\n // PostHog SDK passthrough options\n host?: string;\n flushAt?: number;\n flushInterval?: number;\n personalApiKey?: string;\n featureFlagsPollingInterval?: number;\n disableGeoip?: boolean;\n disableCompression?: boolean;\n requestTimeout?: number;\n fetchRetryCount?: number;\n fetchRetryDelay?: number;\n debug?: boolean;\n disabled?: boolean;\n /** The running send; the next one waits for it. Runtime only. */\n _sending?: Promise<void>;\n}\n\nexport type InitSettings = Partial<Settings>;\n\nexport interface Mapping {\n identify?: WalkerOSMapping.Value;\n group?: WalkerOSMapping.Value;\n}\n\n/**\n * The part of a PostHog client this destination calls. `PostHog` from\n * `posthog-node` satisfies it, and so does an injected mock (tests, simulate)\n * without a cast.\n */\nexport interface PostHogClient {\n capture(props: Parameters<PostHog['capture']>[0]): void;\n identify(props: Parameters<PostHog['identify']>[0]): void;\n groupIdentify(props: Parameters<PostHog['groupIdentify']>[0]): void;\n /** Sends the queued calls; rejects when the request failed. */\n flush(): Promise<void>;\n /** The SDK reports a failed send as an `error` event; returns its remover. */\n on?(event: 'error', listener: (error: unknown) => void): () => void;\n shutdown(): Promise<void> | void;\n enable(): Promise<void> | void;\n disable(): Promise<void> | void;\n}\n\nexport interface Env extends DestinationServer.Env {\n PostHog?: new (\n apiKey: string,\n options?: ConstructorParameters<typeof PostHog>[1],\n ) => PostHogClient;\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>;\nexport type PushBatchFn = CoreDestination.PushBatchFn<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":["import_core","import_server_core","send","call"]}
|
package/dist/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{PostHog}from"posthog-node";import{getMappingValue,isObject,isString}from"@walkeros/core";
|
|
1
|
+
import{createRequire}from"module";createRequire(import.meta.url);import{StepError}from"@walkeros/core";import{retryBudget}from"@walkeros/server-core";import{PostHog}from"posthog-node";import{createHash}from"crypto";import{getMappingValue,isObject,isString,StepError as StepError2}from"@walkeros/core";import{batchOutcome}from"@walkeros/server-core";async function call(client,message,send2){let failure;const off=client.on?.("error",error=>{failure=failure??error});try{await send2()}catch(error){failure=failure??error}finally{off?.()}if(void 0!==failure)throw new StepError2(message,{code:timedOut(failure)?"timeout":"transport",cause:failure})}function timedOut(error){if("object"!=typeof error||null===error)return!1;const name=Reflect.get(error,"name");return"AbortError"===name||"TimeoutError"===name||timedOut(Reflect.get(error,"error")??Reflect.get(error,"cause"))}function skipped(logger,event,call2,key){logger.debug(`PostHog skipped ${call2}: ${key} resolved to nothing`,{event:event.name})}async function queue(message,send2){try{await send2()}catch(error){throw new StepError2(message,{code:"transport",cause:error})}}function exclusive(settings,task){const running=(settings._sending??Promise.resolve()).then(task);return settings._sending=running.catch(()=>{}),running}function clientOf(settings){const client=settings?.client;if(!settings||!client)throw new StepError2("PostHog client not initialized",{code:"not-ready"});return{settings:settings,client:client}}async function send(event,rule,data,settings,client,collector,logger){const mappingSettings=rule?.settings||{},identifyMapping=mappingSettings.identify??settings.identify;let distinctId,identifyResolved;if(void 0!==identifyMapping){const resolved=await getMappingValue(event,identifyMapping,{collector:collector});isObject(resolved)?(identifyResolved=resolved,isString(identifyResolved.distinctId)&&(distinctId=identifyResolved.distinctId)):skipped(logger,event,"identify","identify")}if(distinctId||(distinctId=(isString(event.user?.id)?event.user.id:void 0)||(isString(event.user?.hash)?event.user.hash:void 0)||(isString(event.user?.session)?event.user.session:void 0)||"anonymous"),identifyResolved){const $set=isObject(identifyResolved.$set)?identifyResolved.$set:void 0,$setOnce=isObject(identifyResolved.$set_once)?identifyResolved.$set_once:void 0;if($set||$setOnce){const properties={};$set&&(properties.$set=$set),$setOnce&&(properties.$set_once=$setOnce),await queue("PostHog identify failed",()=>client.identify({distinctId:distinctId,properties:properties}))}}const groupMapping=mappingSettings.group??settings.group;let groups;if(void 0!==groupMapping){const resolved=await getMappingValue(event,groupMapping,{collector:collector});if(isObject(resolved)){const groupResolved=resolved,type=groupResolved.type,key=groupResolved.key,properties=isObject(groupResolved.properties)?groupResolved.properties:void 0;isString(type)&&(isString(key)||"number"==typeof key)?(properties&&await queue("PostHog group identify failed",()=>client.groupIdentify({groupType:type,groupKey:String(key),properties:properties})),groups={[type]:key}):skipped(logger,event,"group","group")}else skipped(logger,event,"group","group")}if(!0!==rule?.silent){const eventName=isString(rule?.name)?rule.name:event.name,properties=isObject(data)?data:{},captureArgs={distinctId:distinctId,event:eventName,properties:properties};groups&&(captureArgs.groups=groups),event.id&&(captureArgs.uuid=function(id){const hex=createHash("sha256").update(id).digest("hex"),variant=(3&parseInt(hex[16],16)|8).toString(16);return[hex.slice(0,8),hex.slice(8,12),`8${hex.slice(13,16)}`,`${variant}${hex.slice(17,20)}`,hex.slice(20,32)].join("-")}(event.id)),await queue("PostHog capture failed",()=>client.capture(captureArgs))}}var types_exports={},destinationPostHog={type:"posthog",config:{batch:{size:20,wait:1e4}},init:async({config:partialConfig,env:env})=>function(partialConfig={},env){const settings=partialConfig.settings||{},{apiKey:apiKey}=settings;if(!apiKey)throw new StepError("Config settings apiKey missing",{code:"config"});const budget=retryBudget(partialConfig.timeout),options={requestTimeout:budget.attempt,fetchRetryCount:budget.retries,fetchRetryDelay:budget.wait};settings.host&&(options.host=settings.host),void 0!==settings.flushAt&&(options.flushAt=settings.flushAt),void 0!==settings.flushInterval&&(options.flushInterval=settings.flushInterval),settings.personalApiKey&&(options.personalApiKey=settings.personalApiKey),void 0!==settings.featureFlagsPollingInterval&&(options.featureFlagsPollingInterval=settings.featureFlagsPollingInterval),void 0!==settings.disableGeoip&&(options.disableGeoip=settings.disableGeoip),void 0!==settings.disableCompression&&(options.disableCompression=settings.disableCompression),void 0!==settings.requestTimeout&&(options.requestTimeout=settings.requestTimeout),void 0!==settings.fetchRetryCount&&(options.fetchRetryCount=settings.fetchRetryCount),void 0!==settings.fetchRetryDelay&&(options.fetchRetryDelay=settings.fetchRetryDelay),void 0!==settings.debug&&(options.debug=settings.debug),void 0!==settings.disabled&&(options.disabled=settings.disabled);const client=new(env?.PostHog||PostHog)(apiKey,options),settingsConfig={...settings,apiKey:apiKey,client:client};return{...partialConfig,settings:settingsConfig}}(partialConfig,env),push:async function(event,{config:config,rule:rule,data:data,collector:collector,logger:logger}){const{settings:settings,client:client}=clientOf(config.settings);await exclusive(settings,async()=>{await send(event,rule,data,settings,client,collector,logger),await call(client,"PostHog send failed",()=>client.flush())})},pushBatch:async function(batch,{config:config,collector:collector,logger:logger}){const{settings:settings,client:client}=clientOf(config.settings),failed=[];let sendError;return await exclusive(settings,async()=>{const queued=[];for(const[index,entry]of batch.entries.entries())await send(entry.event,entry.rule,entry.data,settings,client,collector,logger).then(()=>queued.push(index),error=>failed.push({index:index,error:error}));queued.length&&await call(client,"PostHog send failed",()=>client.flush()).catch(error=>{sendError=error;for(const index of queued)failed.push({index:index,error:error})})}),batchOutcome(batch.entries.length,failed,sendError)},async destroy({config:config}){const client=config?.settings?.client;client&&await client.shutdown()},on(type,context){if("consent"!==type||!context?.data)return;const client=(context.config?.settings||{}).client;if(!client)return;const consent=context.data,required=context.config?.consent;if(!required||0===Object.keys(required).length)return;Object.keys(required).every(key=>!0===consent[key])?client.enable():client.disable()}},index_default=destinationPostHog;export{types_exports as DestinationPostHog,index_default as default,destinationPostHog};//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/config.ts","../src/push.ts","../src/types/index.ts","../src/index.ts"],"sourcesContent":["import type { Config, Env, PartialConfig, Settings } from './types';\nimport type { Logger } from '@walkeros/core';\nimport { PostHog } from 'posthog-node';\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 // Extract PostHog SDK options from settings\n const options: Record<string, unknown> = {};\n if (settings.host) options.host = settings.host;\n if (settings.flushAt !== undefined) options.flushAt = settings.flushAt;\n if (settings.flushInterval !== undefined)\n options.flushInterval = settings.flushInterval;\n if (settings.personalApiKey) options.personalApiKey = settings.personalApiKey;\n if (settings.featureFlagsPollingInterval !== undefined)\n options.featureFlagsPollingInterval = settings.featureFlagsPollingInterval;\n if (settings.disableGeoip !== undefined)\n options.disableGeoip = settings.disableGeoip;\n if (settings.disableCompression !== undefined)\n options.disableCompression = settings.disableCompression;\n if (settings.requestTimeout !== undefined)\n options.requestTimeout = settings.requestTimeout;\n if (settings.fetchRetryCount !== undefined)\n options.fetchRetryCount = settings.fetchRetryCount;\n if (settings.fetchRetryDelay !== undefined)\n options.fetchRetryDelay = settings.fetchRetryDelay;\n if (settings.debug !== undefined) options.debug = settings.debug;\n if (settings.disabled !== undefined) options.disabled = settings.disabled;\n\n // Use PostHog from env if available, otherwise use real PostHog\n const PostHogClass = env?.PostHog || PostHog;\n const client = new PostHogClass(apiKey, options);\n\n const settingsConfig: Settings = {\n ...settings,\n apiKey,\n client,\n };\n\n return { ...partialConfig, settings: settingsConfig };\n}\n","import type { PushFn } from './types';\nimport { getMappingValue, isObject, isString } from '@walkeros/core';\n\nexport const push: PushFn = async function (\n event,\n { config, rule, data, collector },\n) {\n const settings = config.settings!;\n const client = settings.client;\n if (!client) return;\n\n const mappingSettings = (rule?.settings || {}) as Record<string, unknown>;\n\n // Resolve distinctId: rule-level identify wins over destination-level\n const identifyMapping = mappingSettings.identify ?? settings.identify;\n let distinctId: string | undefined;\n let identifyResolved: Record<string, unknown> | undefined;\n\n if (identifyMapping !== undefined) {\n const resolved = await getMappingValue(event, identifyMapping, {\n collector,\n });\n if (isObject(resolved)) {\n identifyResolved = resolved as Record<string, unknown>;\n if (isString(identifyResolved.distinctId)) {\n distinctId = identifyResolved.distinctId as string;\n }\n }\n }\n\n // Fallback distinctId from event.user\n if (!distinctId) {\n distinctId =\n (isString(event.user?.id) ? event.user.id : undefined) ||\n (isString(event.user?.hash) ? event.user.hash : undefined) ||\n (isString(event.user?.session) ? event.user.session : undefined) ||\n 'anonymous';\n }\n\n // 1. Identity - if $set or $set_once present, call client.identify()\n if (identifyResolved) {\n const $set = isObject(identifyResolved.$set)\n ? (identifyResolved.$set as Record<string, unknown>)\n : undefined;\n const $setOnce = isObject(identifyResolved.$set_once)\n ? (identifyResolved.$set_once as Record<string, unknown>)\n : undefined;\n\n if ($set || $setOnce) {\n const properties: Record<string, unknown> = {};\n if ($set) properties.$set = $set;\n if ($setOnce) properties.$set_once = $setOnce;\n client.identify({ distinctId, properties });\n }\n }\n\n // 2. Group - resolve group mapping (rule-level wins)\n const groupMapping = mappingSettings.group ?? settings.group;\n let groups: Record<string, string | number> | undefined;\n\n if (groupMapping !== undefined) {\n const resolved = await getMappingValue(event, groupMapping, {\n collector,\n });\n if (isObject(resolved)) {\n const groupResolved = resolved as Record<string, unknown>;\n const type = groupResolved.type;\n const key = groupResolved.key;\n const properties = isObject(groupResolved.properties)\n ? (groupResolved.properties as Record<string, unknown>)\n : undefined;\n\n if (isString(type) && (isString(key) || typeof key === 'number')) {\n // If properties present, call groupIdentify\n if (properties) {\n client.groupIdentify({\n groupType: type,\n groupKey: String(key),\n properties,\n });\n }\n // Build groups object for capture\n groups = { [type]: key as string | number };\n }\n }\n }\n\n // 3. Capture - unless rule opts out via silent\n if (rule?.silent !== true) {\n const eventName = isString(rule?.name) ? rule.name : event.name;\n const properties = isObject(data) ? (data as Record<string, unknown>) : {};\n\n const captureArgs: Record<string, unknown> = {\n distinctId,\n event: eventName,\n properties,\n };\n if (groups) captureArgs.groups = groups;\n\n client.capture(captureArgs as Parameters<typeof client.capture>[0]);\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 { PostHog } from 'posthog-node';\n\nexport interface Settings {\n /** PostHog project API key (phc_...) */\n apiKey: string;\n /** PostHog client instance, populated by init */\n client?: PostHogClient;\n /** Destination-level identity mapping */\n identify?: WalkerOSMapping.Value;\n /** Destination-level group mapping */\n group?: WalkerOSMapping.Value;\n /** Event sections to flatten into capture properties */\n include?: string[];\n // PostHog SDK passthrough options\n host?: string;\n flushAt?: number;\n flushInterval?: number;\n personalApiKey?: string;\n featureFlagsPollingInterval?: number;\n disableGeoip?: boolean;\n disableCompression?: boolean;\n requestTimeout?: number;\n fetchRetryCount?: number;\n fetchRetryDelay?: number;\n debug?: boolean;\n disabled?: boolean;\n}\n\nexport type InitSettings = Partial<Settings>;\n\nexport interface Mapping {\n identify?: WalkerOSMapping.Value;\n group?: WalkerOSMapping.Value;\n}\n\n/**\n * The part of a PostHog client this destination calls. `PostHog` from\n * `posthog-node` satisfies it, and so does an injected mock (tests, simulate)\n * without a cast.\n */\nexport interface PostHogClient {\n capture(props: Parameters<PostHog['capture']>[0]): void;\n identify(props: Parameters<PostHog['identify']>[0]): void;\n groupIdentify(props: Parameters<PostHog['groupIdentify']>[0]): void;\n shutdown(): Promise<void> | void;\n enable(): Promise<void> | void;\n disable(): Promise<void> | void;\n}\n\nexport interface Env extends DestinationServer.Env {\n PostHog?: new (\n apiKey: string,\n options?: ConstructorParameters<typeof PostHog>[1],\n ) => PostHogClient;\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","import type { WalkerOS } from '@walkeros/core';\nimport type { Destination, Env, Settings } from './types';\nimport { getConfig } from './config';\nimport { push } from './push';\n\n// Types\nexport * as DestinationPostHog from './types';\n\nexport const destinationPostHog: Destination = {\n type: 'posthog',\n\n config: {},\n\n async init({ config: partialConfig, env, logger }) {\n const config = getConfig(partialConfig, env as Env | undefined, logger);\n return config;\n },\n\n async push(event, context) {\n return await push(event, context);\n },\n\n async destroy({ config }) {\n const client = (config?.settings as Settings | undefined)?.client;\n if (client) {\n await client.shutdown();\n }\n },\n\n on(type, context) {\n if (type !== 'consent' || !context?.data) return;\n\n const settings = (context.config?.settings || {}) as Settings;\n const client = settings.client;\n if (!client) return;\n\n const consent = context.data as WalkerOS.Consent;\n const required = (context.config as { consent?: WalkerOS.Consent })\n ?.consent;\n if (!required || Object.keys(required).length === 0) return;\n\n const allGranted = Object.keys(required).every(\n (key) => consent[key] === true,\n );\n if (allGranted) {\n client.enable();\n } else {\n client.disable();\n }\n },\n};\n\nexport default destinationPostHog;\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/config.ts","../src/push.ts","../src/types/index.ts","../src/index.ts"],"sourcesContent":["import type { Config, Env, PartialConfig, Settings } from './types';\nimport { StepError } from '@walkeros/core';\nimport { retryBudget } from '@walkeros/server-core';\nimport { PostHog } from 'posthog-node';\n\nexport function getConfig(\n partialConfig: PartialConfig = {},\n env: Env | undefined,\n): Config {\n const settings: Partial<Settings> = partialConfig.settings || {};\n const { apiKey } = settings;\n\n if (!apiKey)\n throw new StepError('Config settings apiKey missing', { code: 'config' });\n\n // The SDK's own retry ends within config.timeout: a quarter of it per\n // request, two retries a tenth of it apart. A value set in the settings\n // wins.\n const budget = retryBudget(partialConfig.timeout);\n const options: Record<string, unknown> = {\n requestTimeout: budget.attempt,\n fetchRetryCount: budget.retries,\n fetchRetryDelay: budget.wait,\n };\n\n // Extract PostHog SDK options from settings\n if (settings.host) options.host = settings.host;\n if (settings.flushAt !== undefined) options.flushAt = settings.flushAt;\n if (settings.flushInterval !== undefined)\n options.flushInterval = settings.flushInterval;\n if (settings.personalApiKey) options.personalApiKey = settings.personalApiKey;\n if (settings.featureFlagsPollingInterval !== undefined)\n options.featureFlagsPollingInterval = settings.featureFlagsPollingInterval;\n if (settings.disableGeoip !== undefined)\n options.disableGeoip = settings.disableGeoip;\n if (settings.disableCompression !== undefined)\n options.disableCompression = settings.disableCompression;\n if (settings.requestTimeout !== undefined)\n options.requestTimeout = settings.requestTimeout;\n if (settings.fetchRetryCount !== undefined)\n options.fetchRetryCount = settings.fetchRetryCount;\n if (settings.fetchRetryDelay !== undefined)\n options.fetchRetryDelay = settings.fetchRetryDelay;\n if (settings.debug !== undefined) options.debug = settings.debug;\n if (settings.disabled !== undefined) options.disabled = settings.disabled;\n\n // Use PostHog from env if available, otherwise use real PostHog\n const PostHogClass = env?.PostHog || PostHog;\n const client = new PostHogClass(apiKey, options);\n\n const settingsConfig: Settings = {\n ...settings,\n apiKey,\n client,\n };\n\n return { ...partialConfig, settings: settingsConfig };\n}\n","import type { Collector, Destination, Logger, WalkerOS } from '@walkeros/core';\nimport type {\n PostHogClient,\n PushBatchFn,\n PushFn,\n Rule,\n Settings,\n} from './types';\nimport { createHash } from 'crypto';\nimport { getMappingValue, isObject, isString, StepError } from '@walkeros/core';\nimport { batchOutcome } from '@walkeros/server-core';\n\n/**\n * Run one flush to its end. The SDK reports a failed send as an `error`\n * event and a rejected flush; the call listens for the event while it runs.\n * Sends never overlap (`exclusive`), so the event belongs to this flush.\n */\nasync function call(\n client: PostHogClient,\n message: string,\n send: () => unknown,\n): Promise<void> {\n let failure: unknown;\n const off = client.on?.('error', (error) => {\n failure = failure ?? error;\n });\n try {\n await send();\n } catch (error) {\n failure = failure ?? error;\n } finally {\n off?.();\n }\n if (failure !== undefined)\n throw new StepError(message, {\n code: timedOut(failure) ? 'timeout' : 'transport',\n cause: failure,\n });\n}\n\n/**\n * Whether the SDK's last request timed out: it aborts a request after\n * `requestTimeout` and reports a network error carrying the abort.\n */\nfunction timedOut(error: unknown): boolean {\n if (typeof error !== 'object' || error === null) return false;\n const name: unknown = Reflect.get(error, 'name');\n if (name === 'AbortError' || name === 'TimeoutError') return true;\n return timedOut(Reflect.get(error, 'error') ?? Reflect.get(error, 'cause'));\n}\n\n/**\n * The uuid PostHog deduplicates a captured event by, derived from the event\n * id: the same event resent gets the same uuid. PostHog takes only a UUID,\n * so the id is hashed into one (RFC 9562 version 8, name based).\n */\nfunction uuidOf(id: string): string {\n const hex = createHash('sha256').update(id).digest('hex');\n const variant = ((parseInt(hex[16], 16) & 0x3) | 0x8).toString(16);\n return [\n hex.slice(0, 8),\n hex.slice(8, 12),\n `8${hex.slice(13, 16)}`,\n `${variant}${hex.slice(17, 20)}`,\n hex.slice(20, 32),\n ].join('-');\n}\n\n/**\n * A configured mapping that resolved to nothing skips its call: a declared\n * skip, said once at DEBUG with the event and the mapping key, never the\n * value, so a wrong mapping path does not look like an event without data.\n */\nfunction skipped(\n logger: Logger.Instance,\n event: WalkerOS.Event,\n call: string,\n key: string,\n): void {\n logger.debug(`PostHog skipped ${call}: ${key} resolved to nothing`, {\n event: event.name,\n });\n}\n\n/** Run one queueing call; an injected client may answer with a promise. */\nasync function queue(message: string, send: () => unknown): Promise<void> {\n try {\n await send();\n } catch (error) {\n throw new StepError(message, { code: 'transport', cause: error });\n }\n}\n\n/**\n * One send at a time per client: its calls queued, then one flush. A flush\n * sends the whole queue, so a send that overlapped another could be carried,\n * and failed, by the other's request without hearing of it.\n */\nfunction exclusive(\n settings: Partial<Settings>,\n task: () => Promise<void>,\n): Promise<void> {\n const running = (settings._sending ?? Promise.resolve()).then(task);\n settings._sending = running.catch(() => undefined);\n return running;\n}\n\n/** The settings and client init resolved, or a StepError. */\nfunction clientOf(settings: Partial<Settings> | undefined): {\n settings: Partial<Settings>;\n client: PostHogClient;\n} {\n const client = settings?.client;\n if (!settings || !client)\n throw new StepError('PostHog client not initialized', {\n code: 'not-ready',\n });\n return { settings, client };\n}\n\n/** One event: its calls queued and sent by one flush. */\nexport const push: PushFn = async function (\n event,\n { config, rule, data, collector, logger },\n) {\n const { settings, client } = clientOf(config.settings);\n await exclusive(settings, async () => {\n await send(event, rule, data, settings, client, collector, logger);\n await call(client, 'PostHog send failed', () => client.flush());\n });\n};\n\n/**\n * A flushed `config.batch` batch: every entry's calls queued, then one flush\n * sends them. An entry whose calls could not be queued fails alone; a failed\n * flush fails the batch, since PostHog answers a request as a whole.\n */\nexport const pushBatch: PushBatchFn = async function (\n batch,\n { config, collector, logger },\n) {\n const { settings, client } = clientOf(config.settings);\n const failed: Destination.BatchFailure[] = [];\n let sendError: unknown;\n\n await exclusive(settings, async () => {\n const queued: number[] = [];\n for (const [index, entry] of batch.entries.entries())\n await send(\n entry.event,\n entry.rule,\n entry.data,\n settings,\n client,\n collector,\n logger,\n ).then(\n () => queued.push(index),\n (error: unknown) => failed.push({ index, error }),\n );\n\n // One request carries every queued entry: a failed flush fails them all.\n if (queued.length)\n await call(client, 'PostHog send failed', () => client.flush()).catch(\n (error: unknown) => {\n sendError = error;\n for (const index of queued) failed.push({ index, error });\n },\n );\n });\n\n return batchOutcome(batch.entries.length, failed, sendError);\n};\n\n/** The calls of one event (identify, group identify, capture). */\nasync function send(\n event: WalkerOS.Event,\n rule: Rule | undefined,\n data: Destination.Data,\n settings: Partial<Settings>,\n client: PostHogClient,\n collector: Collector.Instance,\n logger: Logger.Instance,\n): Promise<void> {\n const mappingSettings = (rule?.settings || {}) as Record<string, unknown>;\n\n // Resolve distinctId: rule-level identify wins over destination-level\n const identifyMapping = mappingSettings.identify ?? settings.identify;\n let distinctId: string | undefined;\n let identifyResolved: Record<string, unknown> | undefined;\n\n if (identifyMapping !== undefined) {\n const resolved = await getMappingValue(event, identifyMapping, {\n collector,\n });\n if (isObject(resolved)) {\n identifyResolved = resolved as Record<string, unknown>;\n if (isString(identifyResolved.distinctId)) {\n distinctId = identifyResolved.distinctId as string;\n }\n } else skipped(logger, event, 'identify', 'identify');\n }\n\n // Fallback distinctId from event.user\n if (!distinctId) {\n distinctId =\n (isString(event.user?.id) ? event.user.id : undefined) ||\n (isString(event.user?.hash) ? event.user.hash : undefined) ||\n (isString(event.user?.session) ? event.user.session : undefined) ||\n 'anonymous';\n }\n\n // 1. Identity - if $set or $set_once present, call client.identify()\n if (identifyResolved) {\n const $set = isObject(identifyResolved.$set)\n ? (identifyResolved.$set as Record<string, unknown>)\n : undefined;\n const $setOnce = isObject(identifyResolved.$set_once)\n ? (identifyResolved.$set_once as Record<string, unknown>)\n : undefined;\n\n if ($set || $setOnce) {\n const properties: Record<string, unknown> = {};\n if ($set) properties.$set = $set;\n if ($setOnce) properties.$set_once = $setOnce;\n await queue('PostHog identify failed', () =>\n client.identify({ distinctId, properties }),\n );\n }\n }\n\n // 2. Group - resolve group mapping (rule-level wins)\n const groupMapping = mappingSettings.group ?? settings.group;\n let groups: Record<string, string | number> | undefined;\n\n if (groupMapping !== undefined) {\n const resolved = await getMappingValue(event, groupMapping, {\n collector,\n });\n if (isObject(resolved)) {\n const groupResolved = resolved as Record<string, unknown>;\n const type = groupResolved.type;\n const key = groupResolved.key;\n const properties = isObject(groupResolved.properties)\n ? (groupResolved.properties as Record<string, unknown>)\n : undefined;\n\n if (isString(type) && (isString(key) || typeof key === 'number')) {\n // If properties present, call groupIdentify\n // No immediate variant: queued, then flushed in this push.\n if (properties)\n await queue('PostHog group identify failed', () =>\n client.groupIdentify({\n groupType: type,\n groupKey: String(key),\n properties,\n }),\n );\n // Build groups object for capture\n groups = { [type]: key as string | number };\n } else skipped(logger, event, 'group', 'group');\n } else skipped(logger, event, 'group', 'group');\n }\n\n // 3. Capture - unless rule opts out via silent\n if (rule?.silent !== true) {\n const eventName = isString(rule?.name) ? rule.name : event.name;\n const properties = isObject(data) ? (data as Record<string, unknown>) : {};\n\n const captureArgs: Parameters<PostHogClient['capture']>[0] = {\n distinctId,\n event: eventName,\n properties,\n };\n if (groups) captureArgs.groups = groups;\n if (event.id) captureArgs.uuid = uuidOf(event.id);\n\n await queue('PostHog capture failed', () => client.capture(captureArgs));\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 { PostHog } from 'posthog-node';\n\nexport interface Settings {\n /** PostHog project API key (phc_...) */\n apiKey: string;\n /** PostHog client instance, populated by init */\n client?: PostHogClient;\n /** Destination-level identity mapping */\n identify?: WalkerOSMapping.Value;\n /** Destination-level group mapping */\n group?: WalkerOSMapping.Value;\n // PostHog SDK passthrough options\n host?: string;\n flushAt?: number;\n flushInterval?: number;\n personalApiKey?: string;\n featureFlagsPollingInterval?: number;\n disableGeoip?: boolean;\n disableCompression?: boolean;\n requestTimeout?: number;\n fetchRetryCount?: number;\n fetchRetryDelay?: number;\n debug?: boolean;\n disabled?: boolean;\n /** The running send; the next one waits for it. Runtime only. */\n _sending?: Promise<void>;\n}\n\nexport type InitSettings = Partial<Settings>;\n\nexport interface Mapping {\n identify?: WalkerOSMapping.Value;\n group?: WalkerOSMapping.Value;\n}\n\n/**\n * The part of a PostHog client this destination calls. `PostHog` from\n * `posthog-node` satisfies it, and so does an injected mock (tests, simulate)\n * without a cast.\n */\nexport interface PostHogClient {\n capture(props: Parameters<PostHog['capture']>[0]): void;\n identify(props: Parameters<PostHog['identify']>[0]): void;\n groupIdentify(props: Parameters<PostHog['groupIdentify']>[0]): void;\n /** Sends the queued calls; rejects when the request failed. */\n flush(): Promise<void>;\n /** The SDK reports a failed send as an `error` event; returns its remover. */\n on?(event: 'error', listener: (error: unknown) => void): () => void;\n shutdown(): Promise<void> | void;\n enable(): Promise<void> | void;\n disable(): Promise<void> | void;\n}\n\nexport interface Env extends DestinationServer.Env {\n PostHog?: new (\n apiKey: string,\n options?: ConstructorParameters<typeof PostHog>[1],\n ) => PostHogClient;\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>;\nexport type PushBatchFn = CoreDestination.PushBatchFn<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","import type { WalkerOS } from '@walkeros/core';\nimport type { Destination, Env, Settings } from './types';\nimport { getConfig } from './config';\nimport { push, pushBatch } from './push';\n\n// Types\nexport * as DestinationPostHog from './types';\n\nexport const destinationPostHog: Destination = {\n type: 'posthog',\n\n // Batched by default, at the SDK's own former defaults (20 events, 10 s).\n config: { batch: { size: 20, wait: 10_000 } },\n\n async init({ config: partialConfig, env }) {\n return getConfig(partialConfig, env);\n },\n\n push,\n\n pushBatch,\n\n async destroy({ config }) {\n const client = config?.settings?.client;\n if (client) {\n await client.shutdown();\n }\n },\n\n on(type, context) {\n if (type !== 'consent' || !context?.data) return;\n\n const settings = (context.config?.settings || {}) as Settings;\n const client = settings.client;\n if (!client) return;\n\n const consent = context.data as WalkerOS.Consent;\n const required = (context.config as { consent?: WalkerOS.Consent })\n ?.consent;\n if (!required || Object.keys(required).length === 0) return;\n\n const allGranted = Object.keys(required).every(\n (key) => consent[key] === true,\n );\n if (allGranted) {\n client.enable();\n } else {\n client.disable();\n }\n },\n};\n\nexport default destinationPostHog;\n"],"mappings":"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","names":["StepError","send","call"]}
|