Skip to content

Commit

Permalink
node: improve and document Context and Traits interface (#709)
Browse files Browse the repository at this point in the history
  • Loading branch information
silesky authored Dec 3, 2022
1 parent 90b915a commit 108c77e
Show file tree
Hide file tree
Showing 6 changed files with 291 additions and 91 deletions.
5 changes: 5 additions & 0 deletions .changeset/hungry-bears-march.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@segment/analytics-core': patch
---

Improve types for context and traits and fix SegmentEvent context type (node only ATM). Refactor context eventFactory to clarify.
49 changes: 33 additions & 16 deletions packages/core/src/events/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@ import { ID, User } from '../user'
import {
Integrations,
EventProperties,
Traits,
CoreAnalyticsTraits,
CoreSegmentEvent,
CoreOptions,
CoreExtraContext,
} from './interfaces'
import { pickBy } from '../utils/pick'
import { validateEvent } from '../validation/assertions'
import type { RemoveIndexSignature } from '../utils/ts-helpers'

interface EventFactorySettings {
createMessageId: () => string
Expand Down Expand Up @@ -101,7 +103,7 @@ export class EventFactory {

identify(
userId: ID,
traits?: Traits,
traits?: CoreAnalyticsTraits,
options?: CoreOptions,
globalIntegrations?: Integrations
): CoreSegmentEvent {
Expand All @@ -117,7 +119,7 @@ export class EventFactory {

group(
groupId: ID,
traits?: Traits,
traits?: CoreAnalyticsTraits,
options?: CoreOptions,
globalIntegrations?: Integrations
): CoreSegmentEvent {
Expand Down Expand Up @@ -186,30 +188,42 @@ export class EventFactory {
* Builds the context part of an event based on "foreign" keys that
* are provided in the `Options` parameter for an Event
*/
private context(event: CoreSegmentEvent): [object, object] {
const options = event.options ?? {}
delete options['integrations']
private context(
options: CoreOptions
): [CoreExtraContext, Partial<CoreSegmentEvent>] {
type CoreOptionKeys = keyof RemoveIndexSignature<CoreOptions>
/**
* If the event options are known keys from this list, we move them to the top level of the event.
* Any other options are moved to context.
*/
const eventOverrideKeys: CoreOptionKeys[] = [
'userId',
'anonymousId',
'timestamp',
]

const providedOptionsKeys = Object.keys(options)
delete options['integrations']
const providedOptionsKeys = Object.keys(options) as Exclude<
CoreOptionKeys,
'integrations'
>[]

const context = event.options?.context ?? {}
const overrides = {}
const context = options.context ?? {}
const eventOverrides = {}

providedOptionsKeys.forEach((key) => {
if (key === 'context') {
return
}

if (
['integrations', 'anonymousId', 'timestamp', 'userId'].includes(key)
) {
dset(overrides, key, options[key])
if (eventOverrideKeys.includes(key)) {
dset(eventOverrides, key, options[key])
} else {
dset(context, key, options[key])
}
})

return [context, overrides]
return [context, eventOverrides]
}

public normalize(event: CoreSegmentEvent): CoreSegmentEvent {
Expand Down Expand Up @@ -240,14 +254,17 @@ export class EventFactory {
...event.options?.integrations,
}

const [context, overrides] = this.context(event)
const [context, overrides] = event.options
? this.context(event.options)
: []

const { options, ...rest } = event

const body = {
timestamp: new Date(),
...rest,
context,
integrations: allIntegrations,
context,
...overrides,
}

Expand Down
Loading

0 comments on commit 108c77e

Please sign in to comment.