posthog-node 1.1.4 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -22,3 +22,5 @@ This library is largely based on the `analytics-node` package.
22
22
  ## Questions?
23
23
 
24
24
  ### [Join our Slack community.](https://posthog.com/slack)
25
+
26
+
@@ -22,6 +22,8 @@ function eventValidation(event, type) {
22
22
  return validateIdentifyEvent(event)
23
23
  case 'alias':
24
24
  return validateAliasEvent(event)
25
+ case 'groupIdentify':
26
+ return validateGroupIdentifyEvent(event)
25
27
  default:
26
28
  assert(0, 'Invalid event type: "' + type + '"')
27
29
  }
@@ -53,6 +55,15 @@ function validateAliasEvent(event) {
53
55
  assert(event.alias, 'You must pass a "alias".')
54
56
  }
55
57
 
58
+ /**
59
+ * Validate an "groupIdentify" event.
60
+ */
61
+
62
+ function validateGroupIdentifyEvent(event) {
63
+ assert(event.groupType, 'You must pass a "groupType".')
64
+ assert(event.groupKey, 'You must pass a "groupKey".')
65
+ }
66
+
56
67
  /**
57
68
  * Validation rules.
58
69
  */
package/feature-flags.js CHANGED
@@ -5,6 +5,17 @@ const version = require('./package.json').version
5
5
 
6
6
  const LONG_SCALE = 0xfffffffffffffff
7
7
 
8
+ class ClientError extends Error {
9
+ constructor(message, extra) {
10
+ super()
11
+ Error.captureStackTrace(this, this.constructor)
12
+ this.name = 'ClientError'
13
+ this.message = message
14
+ if (extra) {
15
+ this.extra = extra
16
+ }
17
+ }
18
+ }
8
19
 
9
20
  class FeatureFlagsPoller {
10
21
  constructor({ pollingInterval, personalApiKey, projectApiKey, timeout, host, featureFlagCalledCallback }) {
@@ -72,16 +83,24 @@ class FeatureFlagsPoller {
72
83
  }
73
84
  this.poller = setTimeout(() => this._loadFeatureFlags(), this.pollingInterval)
74
85
 
75
- const res = await this._request({ path: 'api/feature_flag', usePersonalApiKey: true })
86
+ try {
87
+ const res = await this._request({ path: 'api/feature_flag', usePersonalApiKey: true })
88
+ if (res && res.status === 401) {
89
+ throw new ClientError(
90
+ `Your personalApiKey is invalid. Are you sure you're not using your Project API key? More information: https://posthog.com/docs/api/overview`
91
+ )
92
+ }
93
+
94
+ this.featureFlags = res.data.results.filter(flag => flag.active)
76
95
 
77
- if (res && res.status === 401) {
78
- throw new Error(
79
- `Your personalApiKey is invalid. Are you sure you're not using your Project API key? More information: https://posthog.com/docs/api/overview`
80
- )
96
+ this.loadedSuccessfullyOnce = true
97
+ } catch (err) {
98
+ // if an error that is not an instance of ClientError is thrown
99
+ // we silently ignore the error when reloading feature flags
100
+ if (err instanceof ClientError) {
101
+ throw err
102
+ }
81
103
  }
82
-
83
- this.featureFlags = res.data.results.filter(flag => flag.active)
84
- this.loadedSuccessfullyOnce = true
85
104
  }
86
105
 
87
106
  // sha1('a.b') should equal '69f6642c9d71b463485b4faf4e989dc3fe77a8c6'
@@ -125,6 +144,7 @@ class FeatureFlagsPoller {
125
144
  req.timeout = typeof this.timeout === 'string' ? ms(this.timeout) : this.timeout
126
145
  }
127
146
 
147
+
128
148
  let res
129
149
  try {
130
150
  res = await axios(req)
package/index.d.ts CHANGED
@@ -17,6 +17,13 @@ declare module 'posthog-node' {
17
17
 
18
18
  interface EventMessage extends IdentifyMessage {
19
19
  event: string
20
+ groups?: Record<string, string | number> // Mapping of group type to group id
21
+ }
22
+
23
+ interface GroupIdentifyMessage {
24
+ groupType: string
25
+ groupKey: string // Unique identifier for the group
26
+ properties?: Record<string | number, any>
20
27
  }
21
28
 
22
29
  export default class PostHog {
@@ -28,9 +35,10 @@ declare module 'posthog-node' {
28
35
  * A capture call requires:
29
36
  * @param distinctId which uniquely identifies your user
30
37
  * @param event We recommend using [verb] [noun], like movie played or movie updated to easily identify what your events mean later on.
31
- * @param properties OPTIONAL | which can be a dict with any information you'd like to add
38
+ * @param properties OPTIONAL | which can be a object with any information you'd like to add
39
+ * @param groups OPTIONAL | object of what groups are related to this event, example: { company: 'id:5' }. Can be used to analyze companies instead of users.
32
40
  */
33
- capture({ distinctId, event, properties }: EventMessage): void
41
+ capture({ distinctId, event, properties, groups }: EventMessage): void
34
42
 
35
43
  /**
36
44
  * @description Identify lets you add metadata on your users so you can more easily identify who they are in PostHog,
@@ -56,9 +64,9 @@ declare module 'posthog-node' {
56
64
 
57
65
 
58
66
  /**
59
- * @description PostHog feature flags (https://posthog.com/docs/features/feature-flags)
67
+ * @description PostHog feature flags (https://posthog.com/docs/features/feature-flags)
60
68
  * allow you to safely deploy and roll back new features. Once you've created a feature flag in PostHog,
61
- * you can use this method to check if the flag is on for a given user, allowing you to create logic to turn
69
+ * you can use this method to check if the flag is on for a given user, allowing you to create logic to turn
62
70
  * features on and off for different user groups or individual users.
63
71
  * IMPORTANT: To use this method, you need to specify `personalApiKey` in your config! More info: https://posthog.com/docs/api/overview
64
72
  * @param key the unique key of your feature flag
@@ -69,7 +77,17 @@ declare module 'posthog-node' {
69
77
 
70
78
 
71
79
  /**
72
- * @description Force an immediate reload of the polled feature flags. Please note that they are
80
+ * @description Sets a groups properties, which allows asking questions like "Who are the most active companies"
81
+ * using my product in PostHog.
82
+ *
83
+ * @param groupType Type of group (ex: 'company'). Limited to 5 per project
84
+ * @param groupKey Unique identifier for that type of group (ex: 'id:5')
85
+ * @param properties OPTIONAL | which can be a object with any information you'd like to add
86
+ */
87
+ groupIdentify({ groupType, groupKey, properties }: GroupIdentifyMessage): void
88
+
89
+ /**
90
+ * @description Force an immediate reload of the polled feature flags. Please note that they are
73
91
  * already polled automatically at a regular interval.
74
92
  */
75
93
  reloadFeatureFlags(): Promise<void>
package/index.js CHANGED
@@ -131,13 +131,18 @@ class PostHog {
131
131
  capture(message, callback) {
132
132
  this._validate(message, 'capture')
133
133
 
134
- const apiMessage = Object.assign({}, message, {
135
- properties: Object.assign({}, message.properties, {
136
- $lib: 'posthog-node',
137
- $lib_version: version,
138
- }),
134
+ const properties = Object.assign({}, message.properties, {
135
+ $lib: 'posthog-node',
136
+ $lib_version: version,
139
137
  })
140
138
 
139
+ if ('groups' in message) {
140
+ properties.$groups = message.groups
141
+ delete message.groups
142
+ }
143
+
144
+ const apiMessage = Object.assign({}, message, { properties })
145
+
141
146
  this.enqueue('capture', apiMessage, callback)
142
147
  return this
143
148
  }
@@ -164,12 +169,36 @@ class PostHog {
164
169
  })
165
170
  delete apiMessage.alias
166
171
  delete apiMessage.distinctId
167
- apiMessage.distinct_id = null
172
+ apiMessage.distinct_id = message.distinctId || message.distinct_id
168
173
 
169
174
  this.enqueue('alias', apiMessage, callback)
170
175
  return this
171
176
  }
172
177
 
178
+ /**
179
+ * @description Sets a groups properties, which allows asking questions like "Who are the most active companies"
180
+ * using my product in PostHog.
181
+ *
182
+ * @param groupType Type of group (ex: 'company'). Limited to 5 per project
183
+ * @param groupKey Unique identifier for that type of group (ex: 'id:5')
184
+ * @param properties OPTIONAL | which can be a object with any information you'd like to add
185
+ */
186
+ groupIdentify(message, callback) {
187
+ this._validate(message, 'groupIdentify')
188
+
189
+ const captureMessage = {
190
+ event: '$groupidentify',
191
+ distinctId: `\$${message.groupType}_${message.groupKey}`,
192
+ properties: {
193
+ $group_type: message.groupType,
194
+ $group_key: message.groupKey,
195
+ $group_set: message.properties || {}
196
+ }
197
+ }
198
+
199
+ return this.capture(captureMessage, callback)
200
+ }
201
+
173
202
  /**
174
203
  * Add a `message` of type `type` to the queue and
175
204
  * check whether it should be flushed.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "posthog-node",
3
- "version": "1.1.4",
3
+ "version": "1.2.0",
4
4
  "description": "PostHog Node.js integration",
5
5
  "license": "MIT",
6
6
  "repository": "PostHog/posthog-node",
@@ -42,7 +42,7 @@
42
42
  "funnels"
43
43
  ],
44
44
  "dependencies": {
45
- "axios": "^0.21.1",
45
+ "axios": "0.24.0",
46
46
  "axios-retry": "^3.1.9",
47
47
  "component-type": "^1.2.1",
48
48
  "join-component": "^1.1.0",