@customerio/cdp-analytics-core 0.0.0-test-oidc
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/LICENSE.MD +22 -0
- package/README.md +3 -0
- package/dist/cjs/analytics/dispatch.js +54 -0
- package/dist/cjs/analytics/dispatch.js.map +1 -0
- package/dist/cjs/analytics/index.js +3 -0
- package/dist/cjs/analytics/index.js.map +1 -0
- package/dist/cjs/callback/index.js +46 -0
- package/dist/cjs/callback/index.js.map +1 -0
- package/dist/cjs/connection/index.js +16 -0
- package/dist/cjs/connection/index.js.map +1 -0
- package/dist/cjs/context/index.js +87 -0
- package/dist/cjs/context/index.js.map +1 -0
- package/dist/cjs/emitter/index.js +66 -0
- package/dist/cjs/emitter/index.js.map +1 -0
- package/dist/cjs/emitter/interface.js +3 -0
- package/dist/cjs/emitter/interface.js.map +1 -0
- package/dist/cjs/events/index.js +154 -0
- package/dist/cjs/events/index.js.map +1 -0
- package/dist/cjs/events/interfaces.js +3 -0
- package/dist/cjs/events/interfaces.js.map +1 -0
- package/dist/cjs/index.js +25 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/logger/index.js +62 -0
- package/dist/cjs/logger/index.js.map +1 -0
- package/dist/cjs/plugins/index.js +3 -0
- package/dist/cjs/plugins/index.js.map +1 -0
- package/dist/cjs/priority-queue/backoff.js +10 -0
- package/dist/cjs/priority-queue/backoff.js.map +1 -0
- package/dist/cjs/priority-queue/index.js +92 -0
- package/dist/cjs/priority-queue/index.js.map +1 -0
- package/dist/cjs/queue/delivery.js +69 -0
- package/dist/cjs/queue/delivery.js.map +1 -0
- package/dist/cjs/queue/event-queue.js +340 -0
- package/dist/cjs/queue/event-queue.js.map +1 -0
- package/dist/cjs/stats/index.js +96 -0
- package/dist/cjs/stats/index.js.map +1 -0
- package/dist/cjs/task/task-group.js +24 -0
- package/dist/cjs/task/task-group.js.map +1 -0
- package/dist/cjs/user/index.js +3 -0
- package/dist/cjs/user/index.js.map +1 -0
- package/dist/cjs/utils/bind-all.js +18 -0
- package/dist/cjs/utils/bind-all.js.map +1 -0
- package/dist/cjs/utils/environment.js +12 -0
- package/dist/cjs/utils/environment.js.map +1 -0
- package/dist/cjs/utils/get-global.js +21 -0
- package/dist/cjs/utils/get-global.js.map +1 -0
- package/dist/cjs/utils/group-by.js +28 -0
- package/dist/cjs/utils/group-by.js.map +1 -0
- package/dist/cjs/utils/has-properties.js +13 -0
- package/dist/cjs/utils/has-properties.js.map +1 -0
- package/dist/cjs/utils/is-plain-object.js +28 -0
- package/dist/cjs/utils/is-plain-object.js.map +1 -0
- package/dist/cjs/utils/is-thenable.js +15 -0
- package/dist/cjs/utils/is-thenable.js.map +1 -0
- package/dist/cjs/utils/p-while.js +25 -0
- package/dist/cjs/utils/p-while.js.map +1 -0
- package/dist/cjs/utils/pick.js +10 -0
- package/dist/cjs/utils/pick.js.map +1 -0
- package/dist/cjs/utils/ts-helpers.js +3 -0
- package/dist/cjs/utils/ts-helpers.js.map +1 -0
- package/dist/cjs/validation/assertions.js +51 -0
- package/dist/cjs/validation/assertions.js.map +1 -0
- package/dist/cjs/validation/helpers.js +26 -0
- package/dist/cjs/validation/helpers.js.map +1 -0
- package/dist/esm/analytics/dispatch.js +49 -0
- package/dist/esm/analytics/dispatch.js.map +1 -0
- package/dist/esm/analytics/index.js +2 -0
- package/dist/esm/analytics/index.js.map +1 -0
- package/dist/esm/callback/index.js +40 -0
- package/dist/esm/callback/index.js.map +1 -0
- package/dist/esm/connection/index.js +11 -0
- package/dist/esm/connection/index.js.map +1 -0
- package/dist/esm/context/index.js +84 -0
- package/dist/esm/context/index.js.map +1 -0
- package/dist/esm/emitter/index.js +63 -0
- package/dist/esm/emitter/index.js.map +1 -0
- package/dist/esm/emitter/interface.js +2 -0
- package/dist/esm/emitter/interface.js.map +1 -0
- package/dist/esm/events/index.js +151 -0
- package/dist/esm/events/index.js.map +1 -0
- package/dist/esm/events/interfaces.js +2 -0
- package/dist/esm/events/interfaces.js.map +1 -0
- package/dist/esm/index.js +19 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/logger/index.js +59 -0
- package/dist/esm/logger/index.js.map +1 -0
- package/dist/esm/plugins/index.js +2 -0
- package/dist/esm/plugins/index.js.map +1 -0
- package/dist/esm/priority-queue/backoff.js +6 -0
- package/dist/esm/priority-queue/backoff.js.map +1 -0
- package/dist/esm/priority-queue/index.js +89 -0
- package/dist/esm/priority-queue/index.js.map +1 -0
- package/dist/esm/queue/delivery.js +64 -0
- package/dist/esm/queue/delivery.js.map +1 -0
- package/dist/esm/queue/event-queue.js +337 -0
- package/dist/esm/queue/event-queue.js.map +1 -0
- package/dist/esm/stats/index.js +93 -0
- package/dist/esm/stats/index.js.map +1 -0
- package/dist/esm/task/task-group.js +20 -0
- package/dist/esm/task/task-group.js.map +1 -0
- package/dist/esm/user/index.js +2 -0
- package/dist/esm/user/index.js.map +1 -0
- package/dist/esm/utils/bind-all.js +14 -0
- package/dist/esm/utils/bind-all.js.map +1 -0
- package/dist/esm/utils/environment.js +7 -0
- package/dist/esm/utils/environment.js.map +1 -0
- package/dist/esm/utils/get-global.js +17 -0
- package/dist/esm/utils/get-global.js.map +1 -0
- package/dist/esm/utils/group-by.js +24 -0
- package/dist/esm/utils/group-by.js.map +1 -0
- package/dist/esm/utils/has-properties.js +9 -0
- package/dist/esm/utils/has-properties.js.map +1 -0
- package/dist/esm/utils/is-plain-object.js +24 -0
- package/dist/esm/utils/is-plain-object.js.map +1 -0
- package/dist/esm/utils/is-thenable.js +11 -0
- package/dist/esm/utils/is-thenable.js.map +1 -0
- package/dist/esm/utils/p-while.js +21 -0
- package/dist/esm/utils/p-while.js.map +1 -0
- package/dist/esm/utils/pick.js +6 -0
- package/dist/esm/utils/pick.js.map +1 -0
- package/dist/esm/utils/ts-helpers.js +2 -0
- package/dist/esm/utils/ts-helpers.js.map +1 -0
- package/dist/esm/validation/assertions.js +46 -0
- package/dist/esm/validation/assertions.js.map +1 -0
- package/dist/esm/validation/helpers.js +18 -0
- package/dist/esm/validation/helpers.js.map +1 -0
- package/dist/types/analytics/dispatch.d.ts +20 -0
- package/dist/types/analytics/dispatch.d.ts.map +1 -0
- package/dist/types/analytics/index.d.ts +12 -0
- package/dist/types/analytics/index.d.ts.map +1 -0
- package/dist/types/callback/index.d.ts +11 -0
- package/dist/types/callback/index.d.ts.map +1 -0
- package/dist/types/connection/index.d.ts +3 -0
- package/dist/types/connection/index.d.ts.map +1 -0
- package/dist/types/context/index.d.ts +44 -0
- package/dist/types/context/index.d.ts.map +1 -0
- package/dist/types/emitter/index.d.ts +25 -0
- package/dist/types/emitter/index.d.ts.map +1 -0
- package/dist/types/emitter/interface.d.ts +27 -0
- package/dist/types/emitter/interface.d.ts.map +1 -0
- package/dist/types/events/index.d.ts +31 -0
- package/dist/types/events/index.d.ts.map +1 -0
- package/dist/types/events/interfaces.d.ts +379 -0
- package/dist/types/events/interfaces.d.ts.map +1 -0
- package/dist/types/index.d.ts +19 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/logger/index.d.ts +19 -0
- package/dist/types/logger/index.d.ts.map +1 -0
- package/dist/types/plugins/index.d.ts +25 -0
- package/dist/types/plugins/index.d.ts.map +1 -0
- package/dist/types/priority-queue/backoff.d.ts +13 -0
- package/dist/types/priority-queue/backoff.d.ts.map +1 -0
- package/dist/types/priority-queue/index.d.ts +25 -0
- package/dist/types/priority-queue/index.d.ts.map +1 -0
- package/dist/types/queue/delivery.d.ts +5 -0
- package/dist/types/queue/delivery.d.ts.map +1 -0
- package/dist/types/queue/event-queue.d.ts +43 -0
- package/dist/types/queue/event-queue.d.ts.map +1 -0
- package/dist/types/stats/index.d.ts +34 -0
- package/dist/types/stats/index.d.ts.map +1 -0
- package/dist/types/task/task-group.d.ts +6 -0
- package/dist/types/task/task-group.d.ts.map +1 -0
- package/dist/types/user/index.d.ts +6 -0
- package/dist/types/user/index.d.ts.map +1 -0
- package/dist/types/utils/bind-all.d.ts +4 -0
- package/dist/types/utils/bind-all.d.ts.map +1 -0
- package/dist/types/utils/environment.d.ts +3 -0
- package/dist/types/utils/environment.d.ts.map +1 -0
- package/dist/types/utils/get-global.d.ts +2 -0
- package/dist/types/utils/get-global.d.ts.map +1 -0
- package/dist/types/utils/group-by.d.ts +4 -0
- package/dist/types/utils/group-by.d.ts.map +1 -0
- package/dist/types/utils/has-properties.d.ts +4 -0
- package/dist/types/utils/has-properties.d.ts.map +1 -0
- package/dist/types/utils/is-plain-object.d.ts +2 -0
- package/dist/types/utils/is-plain-object.d.ts.map +1 -0
- package/dist/types/utils/is-thenable.d.ts +6 -0
- package/dist/types/utils/is-thenable.d.ts.map +1 -0
- package/dist/types/utils/p-while.d.ts +2 -0
- package/dist/types/utils/p-while.d.ts.map +1 -0
- package/dist/types/utils/pick.d.ts +2 -0
- package/dist/types/utils/pick.d.ts.map +1 -0
- package/dist/types/utils/ts-helpers.d.ts +13 -0
- package/dist/types/utils/ts-helpers.d.ts.map +1 -0
- package/dist/types/validation/assertions.d.ts +8 -0
- package/dist/types/validation/assertions.d.ts.map +1 -0
- package/dist/types/validation/helpers.d.ts +7 -0
- package/dist/types/validation/helpers.d.ts.map +1 -0
- package/package.json +40 -0
- package/src/analytics/dispatch.ts +58 -0
- package/src/analytics/index.ts +11 -0
- package/src/callback/index.ts +51 -0
- package/src/connection/index.ts +13 -0
- package/src/context/index.ts +123 -0
- package/src/emitter/index.ts +65 -0
- package/src/emitter/interface.ts +31 -0
- package/src/events/index.ts +285 -0
- package/src/events/interfaces.ts +453 -0
- package/src/index.ts +18 -0
- package/src/logger/index.ts +74 -0
- package/src/plugins/index.ts +43 -0
- package/src/priority-queue/backoff.ts +24 -0
- package/src/priority-queue/index.ts +103 -0
- package/src/queue/delivery.ts +73 -0
- package/src/queue/event-queue.ts +320 -0
- package/src/stats/index.ts +88 -0
- package/src/task/task-group.ts +31 -0
- package/src/user/index.ts +7 -0
- package/src/utils/bind-all.ts +19 -0
- package/src/utils/environment.ts +7 -0
- package/src/utils/get-global.ts +16 -0
- package/src/utils/group-by.ts +30 -0
- package/src/utils/has-properties.ts +7 -0
- package/src/utils/is-plain-object.ts +26 -0
- package/src/utils/is-thenable.ts +9 -0
- package/src/utils/p-while.ts +12 -0
- package/src/utils/pick.ts +8 -0
- package/src/utils/ts-helpers.ts +13 -0
- package/src/validation/assertions.ts +54 -0
- package/src/validation/helpers.ts +27 -0
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
export * from './interfaces'
|
|
2
|
+
import { dset } from 'dset'
|
|
3
|
+
import { ID, User } from '../user'
|
|
4
|
+
import {
|
|
5
|
+
Integrations,
|
|
6
|
+
EventProperties,
|
|
7
|
+
CoreCustomerioEvent,
|
|
8
|
+
CoreOptions,
|
|
9
|
+
CoreExtraContext,
|
|
10
|
+
UserTraits,
|
|
11
|
+
GroupTraits,
|
|
12
|
+
} from './interfaces'
|
|
13
|
+
import { pickBy } from '../utils/pick'
|
|
14
|
+
import { validateEvent } from '../validation/assertions'
|
|
15
|
+
import type { RemoveIndexSignature } from '../utils/ts-helpers'
|
|
16
|
+
|
|
17
|
+
interface EventFactorySettings {
|
|
18
|
+
createMessageId: () => string
|
|
19
|
+
user?: User
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* This is currently only used by node.js, but the original idea was to have something that could be shared between browser and node.
|
|
24
|
+
* Unfortunately, there are some differences in the way the two environments handle events, so this is not currently shared.
|
|
25
|
+
*/
|
|
26
|
+
export class EventFactory {
|
|
27
|
+
createMessageId: EventFactorySettings['createMessageId']
|
|
28
|
+
user?: User
|
|
29
|
+
|
|
30
|
+
constructor(settings: EventFactorySettings) {
|
|
31
|
+
this.user = settings.user
|
|
32
|
+
this.createMessageId = settings.createMessageId
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
track(
|
|
36
|
+
event: string,
|
|
37
|
+
properties?: EventProperties,
|
|
38
|
+
options?: CoreOptions,
|
|
39
|
+
globalIntegrations?: Integrations
|
|
40
|
+
) {
|
|
41
|
+
return this.normalize({
|
|
42
|
+
...this.baseEvent(),
|
|
43
|
+
event,
|
|
44
|
+
type: 'track',
|
|
45
|
+
properties: properties ?? {}, // TODO: why is this not a shallow copy like everywhere else?
|
|
46
|
+
options: { ...options },
|
|
47
|
+
integrations: { ...globalIntegrations },
|
|
48
|
+
})
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
page(
|
|
52
|
+
category: string | null,
|
|
53
|
+
page: string | null,
|
|
54
|
+
properties?: EventProperties,
|
|
55
|
+
options?: CoreOptions,
|
|
56
|
+
globalIntegrations?: Integrations
|
|
57
|
+
): CoreCustomerioEvent {
|
|
58
|
+
const event: CoreCustomerioEvent = {
|
|
59
|
+
type: 'page',
|
|
60
|
+
properties: { ...properties },
|
|
61
|
+
options: { ...options },
|
|
62
|
+
integrations: { ...globalIntegrations },
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (category !== null) {
|
|
66
|
+
event.category = category
|
|
67
|
+
event.properties = event.properties ?? {}
|
|
68
|
+
event.properties.category = category
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (page !== null) {
|
|
72
|
+
event.name = page
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return this.normalize({
|
|
76
|
+
...this.baseEvent(),
|
|
77
|
+
...event,
|
|
78
|
+
})
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
screen(
|
|
82
|
+
category: string | null,
|
|
83
|
+
screen: string | null,
|
|
84
|
+
properties?: EventProperties,
|
|
85
|
+
options?: CoreOptions,
|
|
86
|
+
globalIntegrations?: Integrations
|
|
87
|
+
): CoreCustomerioEvent {
|
|
88
|
+
const event: CoreCustomerioEvent = {
|
|
89
|
+
type: 'screen',
|
|
90
|
+
properties: { ...properties },
|
|
91
|
+
options: { ...options },
|
|
92
|
+
integrations: { ...globalIntegrations },
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if (category !== null) {
|
|
96
|
+
event.category = category
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
if (screen !== null) {
|
|
100
|
+
event.name = screen
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return this.normalize({
|
|
104
|
+
...this.baseEvent(),
|
|
105
|
+
...event,
|
|
106
|
+
})
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
identify(
|
|
110
|
+
userId: ID,
|
|
111
|
+
traits?: UserTraits,
|
|
112
|
+
options?: CoreOptions,
|
|
113
|
+
globalIntegrations?: Integrations
|
|
114
|
+
): CoreCustomerioEvent {
|
|
115
|
+
return this.normalize({
|
|
116
|
+
...this.baseEvent(),
|
|
117
|
+
type: 'identify',
|
|
118
|
+
userId,
|
|
119
|
+
traits: traits ?? {},
|
|
120
|
+
options: { ...options },
|
|
121
|
+
integrations: globalIntegrations,
|
|
122
|
+
})
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
group(
|
|
126
|
+
groupId: ID,
|
|
127
|
+
traits?: GroupTraits,
|
|
128
|
+
options?: CoreOptions,
|
|
129
|
+
globalIntegrations?: Integrations
|
|
130
|
+
): CoreCustomerioEvent {
|
|
131
|
+
return this.normalize({
|
|
132
|
+
...this.baseEvent(),
|
|
133
|
+
type: 'group',
|
|
134
|
+
traits: traits ?? {},
|
|
135
|
+
options: { ...options }, // this spreading is intentional
|
|
136
|
+
integrations: { ...globalIntegrations }, //
|
|
137
|
+
groupId,
|
|
138
|
+
})
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
alias(
|
|
142
|
+
to: string,
|
|
143
|
+
from: string | null, // TODO: can we make this undefined?
|
|
144
|
+
options?: CoreOptions,
|
|
145
|
+
globalIntegrations?: Integrations
|
|
146
|
+
): CoreCustomerioEvent {
|
|
147
|
+
const base: CoreCustomerioEvent = {
|
|
148
|
+
userId: to,
|
|
149
|
+
type: 'alias',
|
|
150
|
+
options: { ...options },
|
|
151
|
+
integrations: { ...globalIntegrations },
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
if (from !== null) {
|
|
155
|
+
base.previousId = from
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
if (to === undefined) {
|
|
159
|
+
return this.normalize({
|
|
160
|
+
...base,
|
|
161
|
+
...this.baseEvent(),
|
|
162
|
+
})
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
return this.normalize({
|
|
166
|
+
...this.baseEvent(),
|
|
167
|
+
...base,
|
|
168
|
+
})
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
private baseEvent(): Partial<CoreCustomerioEvent> {
|
|
172
|
+
const base: Partial<CoreCustomerioEvent> = {
|
|
173
|
+
integrations: {},
|
|
174
|
+
options: {},
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
if (!this.user) return base
|
|
178
|
+
|
|
179
|
+
const user = this.user
|
|
180
|
+
|
|
181
|
+
if (user.id()) {
|
|
182
|
+
base.userId = user.id()
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
if (user.anonymousId()) {
|
|
186
|
+
base.anonymousId = user.anonymousId()
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
return base
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Builds the context part of an event based on "foreign" keys that
|
|
194
|
+
* are provided in the `Options` parameter for an Event
|
|
195
|
+
*/
|
|
196
|
+
private context(
|
|
197
|
+
options: CoreOptions
|
|
198
|
+
): [CoreExtraContext, Partial<CoreCustomerioEvent>] {
|
|
199
|
+
type CoreOptionKeys = keyof RemoveIndexSignature<CoreOptions>
|
|
200
|
+
/**
|
|
201
|
+
* If the event options are known keys from this list, we move them to the top level of the event.
|
|
202
|
+
* Any other options are moved to context.
|
|
203
|
+
*/
|
|
204
|
+
const eventOverrideKeys: CoreOptionKeys[] = [
|
|
205
|
+
'userId',
|
|
206
|
+
'anonymousId',
|
|
207
|
+
'timestamp',
|
|
208
|
+
'messageId',
|
|
209
|
+
]
|
|
210
|
+
|
|
211
|
+
delete options['integrations']
|
|
212
|
+
const providedOptionsKeys = Object.keys(options) as Exclude<
|
|
213
|
+
CoreOptionKeys,
|
|
214
|
+
'integrations'
|
|
215
|
+
>[]
|
|
216
|
+
|
|
217
|
+
const context = options.context ?? {}
|
|
218
|
+
const eventOverrides = {}
|
|
219
|
+
|
|
220
|
+
providedOptionsKeys.forEach((key) => {
|
|
221
|
+
if (key === 'context') {
|
|
222
|
+
return
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
if (eventOverrideKeys.includes(key)) {
|
|
226
|
+
dset(eventOverrides, key, options[key])
|
|
227
|
+
} else {
|
|
228
|
+
dset(context, key, options[key])
|
|
229
|
+
}
|
|
230
|
+
})
|
|
231
|
+
|
|
232
|
+
return [context, eventOverrides]
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
public normalize(event: CoreCustomerioEvent): CoreCustomerioEvent {
|
|
236
|
+
const integrationBooleans = Object.keys(event.integrations ?? {}).reduce(
|
|
237
|
+
(integrationNames, name) => {
|
|
238
|
+
return {
|
|
239
|
+
...integrationNames,
|
|
240
|
+
[name]: Boolean(event.integrations?.[name]),
|
|
241
|
+
}
|
|
242
|
+
},
|
|
243
|
+
{} as Record<string, boolean>
|
|
244
|
+
)
|
|
245
|
+
|
|
246
|
+
// filter out any undefined options
|
|
247
|
+
event.options = pickBy(event.options || {}, (_, value) => {
|
|
248
|
+
return value !== undefined
|
|
249
|
+
})
|
|
250
|
+
|
|
251
|
+
// This is pretty trippy, but here's what's going on:
|
|
252
|
+
// - a) We don't pass initial integration options as part of the event, only if they're true or false
|
|
253
|
+
// - b) We do accept per integration overrides (like integrations.Amplitude.sessionId) at the event level
|
|
254
|
+
// Hence the need to convert base integration options to booleans, but maintain per event integration overrides
|
|
255
|
+
const allIntegrations = {
|
|
256
|
+
// Base config integrations object as booleans
|
|
257
|
+
...integrationBooleans,
|
|
258
|
+
|
|
259
|
+
// Per event overrides, for things like amplitude sessionId, for example
|
|
260
|
+
...event.options?.integrations,
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
const [context, overrides] = event.options
|
|
264
|
+
? this.context(event.options)
|
|
265
|
+
: []
|
|
266
|
+
|
|
267
|
+
const { options, ...rest } = event
|
|
268
|
+
|
|
269
|
+
const body = {
|
|
270
|
+
timestamp: new Date(),
|
|
271
|
+
...rest,
|
|
272
|
+
integrations: allIntegrations,
|
|
273
|
+
context,
|
|
274
|
+
...overrides,
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
const evt: CoreCustomerioEvent = {
|
|
278
|
+
...body,
|
|
279
|
+
messageId: options.messageId || this.createMessageId(),
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
validateEvent(evt)
|
|
283
|
+
return evt
|
|
284
|
+
}
|
|
285
|
+
}
|
|
@@ -0,0 +1,453 @@
|
|
|
1
|
+
import { CoreContext } from '../context'
|
|
2
|
+
import { ID } from '../user'
|
|
3
|
+
import { DeepNullable } from '../utils/ts-helpers'
|
|
4
|
+
|
|
5
|
+
export type Callback<Ctx extends CoreContext = CoreContext> = (
|
|
6
|
+
ctx: Ctx
|
|
7
|
+
) => Promise<unknown> | unknown
|
|
8
|
+
|
|
9
|
+
export type CustomerioEventType =
|
|
10
|
+
| 'track'
|
|
11
|
+
| 'page'
|
|
12
|
+
| 'identify'
|
|
13
|
+
| 'group'
|
|
14
|
+
| 'alias'
|
|
15
|
+
| 'screen'
|
|
16
|
+
|
|
17
|
+
export type JSONPrimitive = string | number | boolean | null
|
|
18
|
+
export type JSONValue = JSONPrimitive | JSONObject | JSONArray
|
|
19
|
+
export type JSONObject = { [member: string]: JSONValue }
|
|
20
|
+
export type JSONArray = JSONValue[]
|
|
21
|
+
|
|
22
|
+
export type EventProperties = Record<string, any>
|
|
23
|
+
|
|
24
|
+
export type Integrations = {
|
|
25
|
+
All?: boolean
|
|
26
|
+
[integration: string]: boolean | JSONObject | undefined
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface CoreOptions {
|
|
30
|
+
integrations?: Integrations
|
|
31
|
+
timestamp?: Timestamp
|
|
32
|
+
context?: CoreExtraContext
|
|
33
|
+
anonymousId?: string
|
|
34
|
+
userId?: string
|
|
35
|
+
traits?: Traits
|
|
36
|
+
/**
|
|
37
|
+
* Override the messageId. Under normal circumstances, this is not recommended -- but necessary for deduping events.
|
|
38
|
+
*
|
|
39
|
+
* **Currently, This option only works in `@customerio/cdp-analytics-node`.**
|
|
40
|
+
*/
|
|
41
|
+
messageId?: string
|
|
42
|
+
// ugh, this is ugly, but we allow literally any property to be passed to options (which get spread onto the event)
|
|
43
|
+
[key: string]: any
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Context is a dictionary of extra information that provides useful context about a datapoint, for example the user’s ip address or locale. You should only use Context fields for their intended meaning.
|
|
48
|
+
*/
|
|
49
|
+
export interface CoreExtraContext {
|
|
50
|
+
/**
|
|
51
|
+
* This is usually used to flag an .identify() call to just update the trait, rather than "last seen".
|
|
52
|
+
*/
|
|
53
|
+
active?: boolean
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Current user's IP address.
|
|
57
|
+
*/
|
|
58
|
+
ip?: string
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Locale string for the current user, for example en-US.
|
|
62
|
+
* @example en-US
|
|
63
|
+
*/
|
|
64
|
+
locale?: string
|
|
65
|
+
/**
|
|
66
|
+
* Dictionary of information about the user’s current location.
|
|
67
|
+
*/
|
|
68
|
+
location?: {
|
|
69
|
+
/**
|
|
70
|
+
* @example San Francisco
|
|
71
|
+
*/
|
|
72
|
+
city?: string
|
|
73
|
+
/**
|
|
74
|
+
* @example United States
|
|
75
|
+
*/
|
|
76
|
+
country?: string
|
|
77
|
+
/**
|
|
78
|
+
* @example 40.2964197
|
|
79
|
+
*/
|
|
80
|
+
latitude?: string
|
|
81
|
+
/**
|
|
82
|
+
* @example -76.9411617
|
|
83
|
+
*/
|
|
84
|
+
longitude?: string
|
|
85
|
+
/**
|
|
86
|
+
* @example CA
|
|
87
|
+
*/
|
|
88
|
+
region?: string
|
|
89
|
+
/**
|
|
90
|
+
* @example 100
|
|
91
|
+
*/
|
|
92
|
+
speed?: number
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Dictionary of information about the current web page.
|
|
97
|
+
*/
|
|
98
|
+
page?: {
|
|
99
|
+
/**
|
|
100
|
+
* @example /academy/
|
|
101
|
+
*/
|
|
102
|
+
path?: string
|
|
103
|
+
/**
|
|
104
|
+
* @example https://www.foo.com/
|
|
105
|
+
*/
|
|
106
|
+
referrer?: string
|
|
107
|
+
/**
|
|
108
|
+
* @example projectId=123
|
|
109
|
+
*/
|
|
110
|
+
search?: string
|
|
111
|
+
/**
|
|
112
|
+
* @example Analytics Academy
|
|
113
|
+
*/
|
|
114
|
+
title?: string
|
|
115
|
+
/**
|
|
116
|
+
* @example https://foobar.com/academy/
|
|
117
|
+
*/
|
|
118
|
+
url?: string
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* User agent of the device making the request.
|
|
123
|
+
*/
|
|
124
|
+
userAgent?: string
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Information about the current library.
|
|
128
|
+
*
|
|
129
|
+
* **Automatically filled out by the library.**
|
|
130
|
+
*
|
|
131
|
+
* This type should probably be "never"
|
|
132
|
+
*/
|
|
133
|
+
library?: {
|
|
134
|
+
/**
|
|
135
|
+
* @example analytics-node-next/latest
|
|
136
|
+
*/
|
|
137
|
+
name: string
|
|
138
|
+
/**
|
|
139
|
+
* @example "1.43.1"
|
|
140
|
+
*/
|
|
141
|
+
version: string
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* This is useful in cases where you need to track an event,
|
|
146
|
+
* but also associate information from a previous identify call.
|
|
147
|
+
* You should fill this object the same way you would fill traits in an identify call.
|
|
148
|
+
*/
|
|
149
|
+
traits?: Traits
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Dictionary of information about the campaign that resulted in the API call, containing name, source, medium, term, content, and any other custom UTM parameter.
|
|
153
|
+
*/
|
|
154
|
+
campaign?: {
|
|
155
|
+
name: string
|
|
156
|
+
term: string
|
|
157
|
+
source: string
|
|
158
|
+
medium: string
|
|
159
|
+
content: string
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Dictionary of information about the way the user was referred to the website or app.
|
|
164
|
+
*/
|
|
165
|
+
referrer?: {
|
|
166
|
+
type?: string
|
|
167
|
+
name?: string
|
|
168
|
+
url?: string
|
|
169
|
+
link?: string
|
|
170
|
+
|
|
171
|
+
id?: string // undocumented
|
|
172
|
+
btid?: string // undocumented?
|
|
173
|
+
urid?: string // undocumented?
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
amp?: {
|
|
177
|
+
// undocumented?
|
|
178
|
+
id: string
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
[key: string]: any
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
export interface CoreCustomerioEvent {
|
|
185
|
+
messageId?: string
|
|
186
|
+
type: CustomerioEventType
|
|
187
|
+
|
|
188
|
+
// page specific
|
|
189
|
+
category?: string
|
|
190
|
+
name?: string
|
|
191
|
+
|
|
192
|
+
properties?: EventProperties
|
|
193
|
+
|
|
194
|
+
traits?: Traits // Traits is only defined in 'identify' and 'group', even if it can be passed in other calls.
|
|
195
|
+
|
|
196
|
+
integrations?: Integrations
|
|
197
|
+
context?: CoreExtraContext
|
|
198
|
+
options?: CoreOptions
|
|
199
|
+
|
|
200
|
+
userId?: ID
|
|
201
|
+
anonymousId?: ID
|
|
202
|
+
groupId?: ID
|
|
203
|
+
previousId?: ID
|
|
204
|
+
|
|
205
|
+
event?: string
|
|
206
|
+
|
|
207
|
+
writeKey?: string
|
|
208
|
+
|
|
209
|
+
sentAt?: Date
|
|
210
|
+
|
|
211
|
+
_metadata?: CustomerioEventMetadata
|
|
212
|
+
|
|
213
|
+
timestamp?: Timestamp
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
export interface CustomerioEventMetadata {
|
|
217
|
+
failedInitializations?: unknown[]
|
|
218
|
+
bundled?: string[]
|
|
219
|
+
unbundled?: string[]
|
|
220
|
+
nodeVersion?: string
|
|
221
|
+
bundledConfigIds?: string[]
|
|
222
|
+
unbundledConfigIds?: string[]
|
|
223
|
+
bundledIds?: string[]
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
export type Timestamp = Date | string
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* A Plan allows users to specify events and which destinations they would like them to be sent to
|
|
230
|
+
*/
|
|
231
|
+
export interface Plan {
|
|
232
|
+
track?: TrackPlan
|
|
233
|
+
identify?: TrackPlan
|
|
234
|
+
group?: TrackPlan
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
export interface TrackPlan {
|
|
238
|
+
[key: string]: PlanEvent | undefined
|
|
239
|
+
// __default SHOULD always exist, but marking as optional for extra safety.
|
|
240
|
+
__default?: PlanEvent
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
export interface PlanEvent {
|
|
244
|
+
/**
|
|
245
|
+
* Whether or not this plan event is enabled
|
|
246
|
+
*/
|
|
247
|
+
enabled: boolean
|
|
248
|
+
/**
|
|
249
|
+
* Which integrations the plan event applies to
|
|
250
|
+
*/
|
|
251
|
+
integrations?: {
|
|
252
|
+
[key: string]: boolean
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
type DbId = string | number // TODO: the docs says that this can only be a string?
|
|
257
|
+
type PhoneNumber = string | number // TODO: the docs say this can only be a string?
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* Traits are pieces of information you know about a group.
|
|
261
|
+
*/
|
|
262
|
+
type BaseGroupTraits = DeepNullable<{
|
|
263
|
+
/**
|
|
264
|
+
* Street address of a group.
|
|
265
|
+
*/
|
|
266
|
+
address?: BaseUserTraits['address']
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* URL to an avatar image for the group.
|
|
270
|
+
*/
|
|
271
|
+
avatar?: BaseUserTraits['avatar']
|
|
272
|
+
|
|
273
|
+
/**
|
|
274
|
+
* Date the group's account was first created. We recommend ISO-8601 date strings.
|
|
275
|
+
*/
|
|
276
|
+
createdAt?: BaseUserTraits['createdAt']
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* Description of a group
|
|
280
|
+
*/
|
|
281
|
+
description?: BaseUserTraits['description']
|
|
282
|
+
/**
|
|
283
|
+
* Email address of group.
|
|
284
|
+
*/
|
|
285
|
+
email?: BaseUserTraits['email']
|
|
286
|
+
/**
|
|
287
|
+
* Number of employees of a group, typically used for companies.
|
|
288
|
+
*/
|
|
289
|
+
employees?: string | number // TODO: the docs says that this must be a string?
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* Unique ID in your database for a group.
|
|
293
|
+
*/
|
|
294
|
+
id?: BaseUserTraits['id']
|
|
295
|
+
|
|
296
|
+
/**
|
|
297
|
+
* Industry a group is part of.
|
|
298
|
+
*/
|
|
299
|
+
industry?: BaseUserTraits['industry']
|
|
300
|
+
|
|
301
|
+
/**
|
|
302
|
+
* Name of a group.
|
|
303
|
+
*/
|
|
304
|
+
name?: BaseUserTraits['name']
|
|
305
|
+
|
|
306
|
+
/**
|
|
307
|
+
* Phone number of a group
|
|
308
|
+
*/
|
|
309
|
+
phone?: BaseUserTraits['phone']
|
|
310
|
+
|
|
311
|
+
/**
|
|
312
|
+
* Website of a group.
|
|
313
|
+
*/
|
|
314
|
+
website?: BaseUserTraits['website']
|
|
315
|
+
|
|
316
|
+
/**
|
|
317
|
+
* Plan that a group is in.
|
|
318
|
+
*/
|
|
319
|
+
plan?: BaseUserTraits['plan']
|
|
320
|
+
}>
|
|
321
|
+
|
|
322
|
+
/**
|
|
323
|
+
* Traits are pieces of information you know about a user.
|
|
324
|
+
*/
|
|
325
|
+
type BaseUserTraits = DeepNullable<{
|
|
326
|
+
/**
|
|
327
|
+
* Unique ID in your database for a user
|
|
328
|
+
*/
|
|
329
|
+
id?: DbId
|
|
330
|
+
|
|
331
|
+
/**
|
|
332
|
+
* Industry a user works in
|
|
333
|
+
*/
|
|
334
|
+
industry?: string
|
|
335
|
+
|
|
336
|
+
/**
|
|
337
|
+
* First name of a user.
|
|
338
|
+
*/
|
|
339
|
+
firstName?: string
|
|
340
|
+
|
|
341
|
+
/**
|
|
342
|
+
* Last name of a user.
|
|
343
|
+
*/
|
|
344
|
+
lastName?: string
|
|
345
|
+
|
|
346
|
+
/**
|
|
347
|
+
* Full name of a user. If you only pass a first and last name we will automatically fill in the full name for you.
|
|
348
|
+
*/
|
|
349
|
+
name?: string
|
|
350
|
+
|
|
351
|
+
/**
|
|
352
|
+
* Phone number of a user
|
|
353
|
+
*/
|
|
354
|
+
phone?: PhoneNumber
|
|
355
|
+
|
|
356
|
+
/**
|
|
357
|
+
* Title of a user, usually related to their position at a specific company.
|
|
358
|
+
* @example VP of Engineering
|
|
359
|
+
*/
|
|
360
|
+
title?: string
|
|
361
|
+
|
|
362
|
+
/**
|
|
363
|
+
* User's username. This should be unique to each user, like the usernames of Twitter or GitHub.
|
|
364
|
+
*/
|
|
365
|
+
username?: string
|
|
366
|
+
|
|
367
|
+
/**
|
|
368
|
+
* Website of a user.
|
|
369
|
+
*/
|
|
370
|
+
website?: string
|
|
371
|
+
|
|
372
|
+
/**
|
|
373
|
+
* Street address of a user.
|
|
374
|
+
*/
|
|
375
|
+
address?: {
|
|
376
|
+
city?: string
|
|
377
|
+
country?: string
|
|
378
|
+
postalCode?: string
|
|
379
|
+
state?: string
|
|
380
|
+
street?: string
|
|
381
|
+
}
|
|
382
|
+
/**
|
|
383
|
+
* Age of a user.
|
|
384
|
+
*/
|
|
385
|
+
age?: number
|
|
386
|
+
|
|
387
|
+
/**
|
|
388
|
+
* URL to an avatar image for the user.
|
|
389
|
+
*/
|
|
390
|
+
avatar?: string
|
|
391
|
+
|
|
392
|
+
/**
|
|
393
|
+
* User's birthday.
|
|
394
|
+
*/
|
|
395
|
+
birthday?: Timestamp
|
|
396
|
+
|
|
397
|
+
/**
|
|
398
|
+
* User's company.
|
|
399
|
+
*/
|
|
400
|
+
company?: {
|
|
401
|
+
name?: string
|
|
402
|
+
id?: DbId
|
|
403
|
+
industry?: BaseUserTraits['industry']
|
|
404
|
+
employee_count?: number
|
|
405
|
+
plan?: BaseUserTraits['plan']
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
/**
|
|
409
|
+
Plan that a user is in.
|
|
410
|
+
|
|
411
|
+
* @example enterprise
|
|
412
|
+
*/
|
|
413
|
+
plan?: string
|
|
414
|
+
|
|
415
|
+
/**
|
|
416
|
+
* Date the user's account was first created. We recommend using ISO-8601 date strings.
|
|
417
|
+
*/
|
|
418
|
+
createdAt?: Timestamp
|
|
419
|
+
|
|
420
|
+
/**
|
|
421
|
+
* Description of user, such as bio.
|
|
422
|
+
*/
|
|
423
|
+
description?: string
|
|
424
|
+
|
|
425
|
+
/**
|
|
426
|
+
* Email address of a user.
|
|
427
|
+
*/
|
|
428
|
+
email?: string
|
|
429
|
+
|
|
430
|
+
/**
|
|
431
|
+
* @example female
|
|
432
|
+
*/
|
|
433
|
+
gender?: string
|
|
434
|
+
}>
|
|
435
|
+
|
|
436
|
+
/**
|
|
437
|
+
* Traits are pieces of information you know about a group.
|
|
438
|
+
*/
|
|
439
|
+
export type GroupTraits = BaseGroupTraits & {
|
|
440
|
+
[customTrait: string]: any
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
/**
|
|
444
|
+
* Traits are pieces of information you know about a user.
|
|
445
|
+
*/
|
|
446
|
+
export type UserTraits = BaseUserTraits & {
|
|
447
|
+
[customTrait: string]: any
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
/**
|
|
451
|
+
* Traits are pieces of information you know about a user or group.
|
|
452
|
+
*/
|
|
453
|
+
export type Traits = UserTraits | GroupTraits
|