Skip to content

Commit 108c77e

Browse files
authored
node: improve and document Context and Traits interface (#709)
1 parent 90b915a commit 108c77e

File tree

6 files changed

+291
-91
lines changed

6 files changed

+291
-91
lines changed

.changeset/hungry-bears-march.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@segment/analytics-core': patch
3+
---
4+
5+
Improve types for context and traits and fix SegmentEvent context type (node only ATM). Refactor context eventFactory to clarify.

packages/core/src/events/index.ts

Lines changed: 33 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,14 @@ import { ID, User } from '../user'
44
import {
55
Integrations,
66
EventProperties,
7-
Traits,
7+
CoreAnalyticsTraits,
88
CoreSegmentEvent,
99
CoreOptions,
10+
CoreExtraContext,
1011
} from './interfaces'
1112
import { pickBy } from '../utils/pick'
1213
import { validateEvent } from '../validation/assertions'
14+
import type { RemoveIndexSignature } from '../utils/ts-helpers'
1315

1416
interface EventFactorySettings {
1517
createMessageId: () => string
@@ -101,7 +103,7 @@ export class EventFactory {
101103

102104
identify(
103105
userId: ID,
104-
traits?: Traits,
106+
traits?: CoreAnalyticsTraits,
105107
options?: CoreOptions,
106108
globalIntegrations?: Integrations
107109
): CoreSegmentEvent {
@@ -117,7 +119,7 @@ export class EventFactory {
117119

118120
group(
119121
groupId: ID,
120-
traits?: Traits,
122+
traits?: CoreAnalyticsTraits,
121123
options?: CoreOptions,
122124
globalIntegrations?: Integrations
123125
): CoreSegmentEvent {
@@ -186,30 +188,42 @@ export class EventFactory {
186188
* Builds the context part of an event based on "foreign" keys that
187189
* are provided in the `Options` parameter for an Event
188190
*/
189-
private context(event: CoreSegmentEvent): [object, object] {
190-
const options = event.options ?? {}
191-
delete options['integrations']
191+
private context(
192+
options: CoreOptions
193+
): [CoreExtraContext, Partial<CoreSegmentEvent>] {
194+
type CoreOptionKeys = keyof RemoveIndexSignature<CoreOptions>
195+
/**
196+
* If the event options are known keys from this list, we move them to the top level of the event.
197+
* Any other options are moved to context.
198+
*/
199+
const eventOverrideKeys: CoreOptionKeys[] = [
200+
'userId',
201+
'anonymousId',
202+
'timestamp',
203+
]
192204

193-
const providedOptionsKeys = Object.keys(options)
205+
delete options['integrations']
206+
const providedOptionsKeys = Object.keys(options) as Exclude<
207+
CoreOptionKeys,
208+
'integrations'
209+
>[]
194210

195-
const context = event.options?.context ?? {}
196-
const overrides = {}
211+
const context = options.context ?? {}
212+
const eventOverrides = {}
197213

198214
providedOptionsKeys.forEach((key) => {
199215
if (key === 'context') {
200216
return
201217
}
202218

203-
if (
204-
['integrations', 'anonymousId', 'timestamp', 'userId'].includes(key)
205-
) {
206-
dset(overrides, key, options[key])
219+
if (eventOverrideKeys.includes(key)) {
220+
dset(eventOverrides, key, options[key])
207221
} else {
208222
dset(context, key, options[key])
209223
}
210224
})
211225

212-
return [context, overrides]
226+
return [context, eventOverrides]
213227
}
214228

215229
public normalize(event: CoreSegmentEvent): CoreSegmentEvent {
@@ -240,14 +254,17 @@ export class EventFactory {
240254
...event.options?.integrations,
241255
}
242256

243-
const [context, overrides] = this.context(event)
257+
const [context, overrides] = event.options
258+
? this.context(event.options)
259+
: []
260+
244261
const { options, ...rest } = event
245262

246263
const body = {
247264
timestamp: new Date(),
248265
...rest,
249-
context,
250266
integrations: allIntegrations,
267+
context,
251268
...overrides,
252269
}
253270

0 commit comments

Comments
 (0)