@customerio/cdp-analytics-core 0.0.1
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 +149 -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 +41 -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 +146 -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 +37 -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 +27 -0
- package/dist/types/events/index.d.ts.map +1 -0
- package/dist/types/events/interfaces.d.ts +373 -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 +7 -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 +39 -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 +280 -0
- package/src/events/interfaces.ts +447 -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 +43 -0
- package/src/validation/helpers.ts +27 -0
|
@@ -0,0 +1,447 @@
|
|
|
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
|
+
// ugh, this is ugly, but we allow literally any property to be passed to options (which get spread onto the event)
|
|
37
|
+
[key: string]: any
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* 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.
|
|
42
|
+
*/
|
|
43
|
+
export interface CoreExtraContext {
|
|
44
|
+
/**
|
|
45
|
+
* This is usually used to flag an .identify() call to just update the trait, rather than "last seen".
|
|
46
|
+
*/
|
|
47
|
+
active?: boolean
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Current user's IP address.
|
|
51
|
+
*/
|
|
52
|
+
ip?: string
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Locale string for the current user, for example en-US.
|
|
56
|
+
* @example en-US
|
|
57
|
+
*/
|
|
58
|
+
locale?: string
|
|
59
|
+
/**
|
|
60
|
+
* Dictionary of information about the user’s current location.
|
|
61
|
+
*/
|
|
62
|
+
location?: {
|
|
63
|
+
/**
|
|
64
|
+
* @example San Francisco
|
|
65
|
+
*/
|
|
66
|
+
city?: string
|
|
67
|
+
/**
|
|
68
|
+
* @example United States
|
|
69
|
+
*/
|
|
70
|
+
country?: string
|
|
71
|
+
/**
|
|
72
|
+
* @example 40.2964197
|
|
73
|
+
*/
|
|
74
|
+
latitude?: string
|
|
75
|
+
/**
|
|
76
|
+
* @example -76.9411617
|
|
77
|
+
*/
|
|
78
|
+
longitude?: string
|
|
79
|
+
/**
|
|
80
|
+
* @example CA
|
|
81
|
+
*/
|
|
82
|
+
region?: string
|
|
83
|
+
/**
|
|
84
|
+
* @example 100
|
|
85
|
+
*/
|
|
86
|
+
speed?: number
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Dictionary of information about the current web page.
|
|
91
|
+
*/
|
|
92
|
+
page?: {
|
|
93
|
+
/**
|
|
94
|
+
* @example /academy/
|
|
95
|
+
*/
|
|
96
|
+
path?: string
|
|
97
|
+
/**
|
|
98
|
+
* @example https://www.foo.com/
|
|
99
|
+
*/
|
|
100
|
+
referrer?: string
|
|
101
|
+
/**
|
|
102
|
+
* @example projectId=123
|
|
103
|
+
*/
|
|
104
|
+
search?: string
|
|
105
|
+
/**
|
|
106
|
+
* @example Analytics Academy
|
|
107
|
+
*/
|
|
108
|
+
title?: string
|
|
109
|
+
/**
|
|
110
|
+
* @example https://foobar.com/academy/
|
|
111
|
+
*/
|
|
112
|
+
url?: string
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* User agent of the device making the request.
|
|
117
|
+
*/
|
|
118
|
+
userAgent?: string
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Information about the current library.
|
|
122
|
+
*
|
|
123
|
+
* **Automatically filled out by the library.**
|
|
124
|
+
*
|
|
125
|
+
* This type should probably be "never"
|
|
126
|
+
*/
|
|
127
|
+
library?: {
|
|
128
|
+
/**
|
|
129
|
+
* @example analytics-node-next/latest
|
|
130
|
+
*/
|
|
131
|
+
name: string
|
|
132
|
+
/**
|
|
133
|
+
* @example "1.43.1"
|
|
134
|
+
*/
|
|
135
|
+
version: string
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* This is useful in cases where you need to track an event,
|
|
140
|
+
* but also associate information from a previous identify call.
|
|
141
|
+
* You should fill this object the same way you would fill traits in an identify call.
|
|
142
|
+
*/
|
|
143
|
+
traits?: Traits
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Dictionary of information about the campaign that resulted in the API call, containing name, source, medium, term, content, and any other custom UTM parameter.
|
|
147
|
+
*/
|
|
148
|
+
campaign?: {
|
|
149
|
+
name: string
|
|
150
|
+
term: string
|
|
151
|
+
source: string
|
|
152
|
+
medium: string
|
|
153
|
+
content: string
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Dictionary of information about the way the user was referred to the website or app.
|
|
158
|
+
*/
|
|
159
|
+
referrer?: {
|
|
160
|
+
type?: string
|
|
161
|
+
name?: string
|
|
162
|
+
url?: string
|
|
163
|
+
link?: string
|
|
164
|
+
|
|
165
|
+
id?: string // undocumented
|
|
166
|
+
btid?: string // undocumented?
|
|
167
|
+
urid?: string // undocumented?
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
amp?: {
|
|
171
|
+
// undocumented?
|
|
172
|
+
id: string
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
[key: string]: any
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
export interface CoreCustomerioEvent {
|
|
179
|
+
messageId?: string
|
|
180
|
+
type: CustomerioEventType
|
|
181
|
+
|
|
182
|
+
// page specific
|
|
183
|
+
category?: string
|
|
184
|
+
name?: string
|
|
185
|
+
|
|
186
|
+
properties?: EventProperties
|
|
187
|
+
|
|
188
|
+
traits?: Traits // Traits is only defined in 'identify' and 'group', even if it can be passed in other calls.
|
|
189
|
+
|
|
190
|
+
integrations?: Integrations
|
|
191
|
+
context?: CoreExtraContext
|
|
192
|
+
options?: CoreOptions
|
|
193
|
+
|
|
194
|
+
userId?: ID
|
|
195
|
+
anonymousId?: ID
|
|
196
|
+
groupId?: ID
|
|
197
|
+
previousId?: ID
|
|
198
|
+
|
|
199
|
+
event?: string
|
|
200
|
+
|
|
201
|
+
writeKey?: string
|
|
202
|
+
|
|
203
|
+
sentAt?: Date
|
|
204
|
+
|
|
205
|
+
_metadata?: CustomerioEventMetadata
|
|
206
|
+
|
|
207
|
+
timestamp?: Timestamp
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
export interface CustomerioEventMetadata {
|
|
211
|
+
failedInitializations?: unknown[]
|
|
212
|
+
bundled?: string[]
|
|
213
|
+
unbundled?: string[]
|
|
214
|
+
nodeVersion?: string
|
|
215
|
+
bundledConfigIds?: string[]
|
|
216
|
+
unbundledConfigIds?: string[]
|
|
217
|
+
bundledIds?: string[]
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
export type Timestamp = Date | string
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* A Plan allows users to specify events and which destinations they would like them to be sent to
|
|
224
|
+
*/
|
|
225
|
+
export interface Plan {
|
|
226
|
+
track?: TrackPlan
|
|
227
|
+
identify?: TrackPlan
|
|
228
|
+
group?: TrackPlan
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
export interface TrackPlan {
|
|
232
|
+
[key: string]: PlanEvent | undefined
|
|
233
|
+
// __default SHOULD always exist, but marking as optional for extra safety.
|
|
234
|
+
__default?: PlanEvent
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
export interface PlanEvent {
|
|
238
|
+
/**
|
|
239
|
+
* Whether or not this plan event is enabled
|
|
240
|
+
*/
|
|
241
|
+
enabled: boolean
|
|
242
|
+
/**
|
|
243
|
+
* Which integrations the plan event applies to
|
|
244
|
+
*/
|
|
245
|
+
integrations?: {
|
|
246
|
+
[key: string]: boolean
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
type DbId = string | number // TODO: the docs says that this can only be a string?
|
|
251
|
+
type PhoneNumber = string | number // TODO: the docs say this can only be a string?
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* Traits are pieces of information you know about a group.
|
|
255
|
+
*/
|
|
256
|
+
type BaseGroupTraits = DeepNullable<{
|
|
257
|
+
/**
|
|
258
|
+
* Street address of a group.
|
|
259
|
+
*/
|
|
260
|
+
address?: BaseUserTraits['address']
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* URL to an avatar image for the group.
|
|
264
|
+
*/
|
|
265
|
+
avatar?: BaseUserTraits['avatar']
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* Date the group's account was first created. We recommend ISO-8601 date strings.
|
|
269
|
+
*/
|
|
270
|
+
createdAt?: BaseUserTraits['createdAt']
|
|
271
|
+
|
|
272
|
+
/**
|
|
273
|
+
* Description of a group
|
|
274
|
+
*/
|
|
275
|
+
description?: BaseUserTraits['description']
|
|
276
|
+
/**
|
|
277
|
+
* Email address of group.
|
|
278
|
+
*/
|
|
279
|
+
email?: BaseUserTraits['email']
|
|
280
|
+
/**
|
|
281
|
+
* Number of employees of a group, typically used for companies.
|
|
282
|
+
*/
|
|
283
|
+
employees?: string | number // TODO: the docs says that this must be a string?
|
|
284
|
+
|
|
285
|
+
/**
|
|
286
|
+
* Unique ID in your database for a group.
|
|
287
|
+
*/
|
|
288
|
+
id?: BaseUserTraits['id']
|
|
289
|
+
|
|
290
|
+
/**
|
|
291
|
+
* Industry a group is part of.
|
|
292
|
+
*/
|
|
293
|
+
industry?: BaseUserTraits['industry']
|
|
294
|
+
|
|
295
|
+
/**
|
|
296
|
+
* Name of a group.
|
|
297
|
+
*/
|
|
298
|
+
name?: BaseUserTraits['name']
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* Phone number of a group
|
|
302
|
+
*/
|
|
303
|
+
phone?: BaseUserTraits['phone']
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* Website of a group.
|
|
307
|
+
*/
|
|
308
|
+
website?: BaseUserTraits['website']
|
|
309
|
+
|
|
310
|
+
/**
|
|
311
|
+
* Plan that a group is in.
|
|
312
|
+
*/
|
|
313
|
+
plan?: BaseUserTraits['plan']
|
|
314
|
+
}>
|
|
315
|
+
|
|
316
|
+
/**
|
|
317
|
+
* Traits are pieces of information you know about a user.
|
|
318
|
+
*/
|
|
319
|
+
type BaseUserTraits = DeepNullable<{
|
|
320
|
+
/**
|
|
321
|
+
* Unique ID in your database for a user
|
|
322
|
+
*/
|
|
323
|
+
id?: DbId
|
|
324
|
+
|
|
325
|
+
/**
|
|
326
|
+
* Industry a user works in
|
|
327
|
+
*/
|
|
328
|
+
industry?: string
|
|
329
|
+
|
|
330
|
+
/**
|
|
331
|
+
* First name of a user.
|
|
332
|
+
*/
|
|
333
|
+
firstName?: string
|
|
334
|
+
|
|
335
|
+
/**
|
|
336
|
+
* Last name of a user.
|
|
337
|
+
*/
|
|
338
|
+
lastName?: string
|
|
339
|
+
|
|
340
|
+
/**
|
|
341
|
+
* Full name of a user. If you only pass a first and last name we will automatically fill in the full name for you.
|
|
342
|
+
*/
|
|
343
|
+
name?: string
|
|
344
|
+
|
|
345
|
+
/**
|
|
346
|
+
* Phone number of a user
|
|
347
|
+
*/
|
|
348
|
+
phone?: PhoneNumber
|
|
349
|
+
|
|
350
|
+
/**
|
|
351
|
+
* Title of a user, usually related to their position at a specific company.
|
|
352
|
+
* @example VP of Engineering
|
|
353
|
+
*/
|
|
354
|
+
title?: string
|
|
355
|
+
|
|
356
|
+
/**
|
|
357
|
+
* User's username. This should be unique to each user, like the usernames of Twitter or GitHub.
|
|
358
|
+
*/
|
|
359
|
+
username?: string
|
|
360
|
+
|
|
361
|
+
/**
|
|
362
|
+
* Website of a user.
|
|
363
|
+
*/
|
|
364
|
+
website?: string
|
|
365
|
+
|
|
366
|
+
/**
|
|
367
|
+
* Street address of a user.
|
|
368
|
+
*/
|
|
369
|
+
address?: {
|
|
370
|
+
city?: string
|
|
371
|
+
country?: string
|
|
372
|
+
postalCode?: string
|
|
373
|
+
state?: string
|
|
374
|
+
street?: string
|
|
375
|
+
}
|
|
376
|
+
/**
|
|
377
|
+
* Age of a user.
|
|
378
|
+
*/
|
|
379
|
+
age?: number
|
|
380
|
+
|
|
381
|
+
/**
|
|
382
|
+
* URL to an avatar image for the user.
|
|
383
|
+
*/
|
|
384
|
+
avatar?: string
|
|
385
|
+
|
|
386
|
+
/**
|
|
387
|
+
* User's birthday.
|
|
388
|
+
*/
|
|
389
|
+
birthday?: Timestamp
|
|
390
|
+
|
|
391
|
+
/**
|
|
392
|
+
* User's company.
|
|
393
|
+
*/
|
|
394
|
+
company?: {
|
|
395
|
+
name?: string
|
|
396
|
+
id?: DbId
|
|
397
|
+
industry?: BaseUserTraits['industry']
|
|
398
|
+
employee_count?: number
|
|
399
|
+
plan?: BaseUserTraits['plan']
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
/**
|
|
403
|
+
Plan that a user is in.
|
|
404
|
+
|
|
405
|
+
* @example enterprise
|
|
406
|
+
*/
|
|
407
|
+
plan?: string
|
|
408
|
+
|
|
409
|
+
/**
|
|
410
|
+
* Date the user's account was first created. We recommend using ISO-8601 date strings.
|
|
411
|
+
*/
|
|
412
|
+
createdAt?: Timestamp
|
|
413
|
+
|
|
414
|
+
/**
|
|
415
|
+
* Description of user, such as bio.
|
|
416
|
+
*/
|
|
417
|
+
description?: string
|
|
418
|
+
|
|
419
|
+
/**
|
|
420
|
+
* Email address of a user.
|
|
421
|
+
*/
|
|
422
|
+
email?: string
|
|
423
|
+
|
|
424
|
+
/**
|
|
425
|
+
* @example female
|
|
426
|
+
*/
|
|
427
|
+
gender?: string
|
|
428
|
+
}>
|
|
429
|
+
|
|
430
|
+
/**
|
|
431
|
+
* Traits are pieces of information you know about a group.
|
|
432
|
+
*/
|
|
433
|
+
export type GroupTraits = BaseGroupTraits & {
|
|
434
|
+
[customTrait: string]: any
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
/**
|
|
438
|
+
* Traits are pieces of information you know about a user.
|
|
439
|
+
*/
|
|
440
|
+
export type UserTraits = BaseUserTraits & {
|
|
441
|
+
[customTrait: string]: any
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
/**
|
|
445
|
+
* Traits are pieces of information you know about a user or group.
|
|
446
|
+
*/
|
|
447
|
+
export type Traits = UserTraits | GroupTraits
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export * from './emitter'
|
|
2
|
+
export * from './emitter/interface'
|
|
3
|
+
export * from './plugins'
|
|
4
|
+
export * from './events/interfaces'
|
|
5
|
+
export * from './events'
|
|
6
|
+
export * from './callback'
|
|
7
|
+
export * from './priority-queue'
|
|
8
|
+
export { backoff } from './priority-queue/backoff'
|
|
9
|
+
export * from './context'
|
|
10
|
+
export * from './queue/event-queue'
|
|
11
|
+
export * from './analytics'
|
|
12
|
+
export * from './analytics/dispatch'
|
|
13
|
+
export * from './validation/helpers'
|
|
14
|
+
export * from './validation/assertions'
|
|
15
|
+
export * from './utils/bind-all'
|
|
16
|
+
export * from './stats'
|
|
17
|
+
export { CoreLogger } from './logger'
|
|
18
|
+
export * from './queue/delivery'
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
export type LogLevel = 'debug' | 'info' | 'warn' | 'error'
|
|
2
|
+
export type LogMessage = {
|
|
3
|
+
level: LogLevel
|
|
4
|
+
message: string
|
|
5
|
+
time?: Date
|
|
6
|
+
extras?: Record<string, any>
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export interface GenericLogger {
|
|
10
|
+
log(level: LogLevel, message: string, extras?: object): void
|
|
11
|
+
flush(): void
|
|
12
|
+
logs: LogMessage[]
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export class CoreLogger implements GenericLogger {
|
|
16
|
+
private _logs: LogMessage[] = []
|
|
17
|
+
|
|
18
|
+
log(level: LogLevel, message: string, extras?: object) {
|
|
19
|
+
const time = new Date()
|
|
20
|
+
this._logs.push({
|
|
21
|
+
level,
|
|
22
|
+
message,
|
|
23
|
+
time,
|
|
24
|
+
extras,
|
|
25
|
+
})
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
public get logs(): LogMessage[] {
|
|
29
|
+
return this._logs
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
public flush(): void {
|
|
33
|
+
if (this.logs.length > 1) {
|
|
34
|
+
const formatted = this._logs.reduce((logs, log) => {
|
|
35
|
+
const line = {
|
|
36
|
+
...log,
|
|
37
|
+
json: JSON.stringify(log.extras, null, ' '),
|
|
38
|
+
extras: log.extras,
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
delete line['time']
|
|
42
|
+
|
|
43
|
+
let key = log.time?.toISOString() ?? ''
|
|
44
|
+
if (logs[key]) {
|
|
45
|
+
key = `${key}-${Math.random()}`
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return {
|
|
49
|
+
...logs,
|
|
50
|
+
[key]: line,
|
|
51
|
+
}
|
|
52
|
+
}, {} as Record<string, LogMessage>)
|
|
53
|
+
|
|
54
|
+
// ie doesn't like console.table
|
|
55
|
+
if (console.table) {
|
|
56
|
+
console.table(formatted)
|
|
57
|
+
} else {
|
|
58
|
+
console.log(formatted)
|
|
59
|
+
}
|
|
60
|
+
} else {
|
|
61
|
+
this.logs.forEach((logEntry) => {
|
|
62
|
+
const { level, message, extras } = logEntry
|
|
63
|
+
|
|
64
|
+
if (level === 'info' || level === 'debug') {
|
|
65
|
+
console.log(message, extras ?? '')
|
|
66
|
+
} else {
|
|
67
|
+
console[level](message, extras ?? '')
|
|
68
|
+
}
|
|
69
|
+
})
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
this._logs = []
|
|
73
|
+
}
|
|
74
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { CoreAnalytics } from '../analytics'
|
|
2
|
+
import type { CoreContext } from '../context'
|
|
3
|
+
|
|
4
|
+
interface CorePluginConfig {
|
|
5
|
+
options: any
|
|
6
|
+
priority: 'critical' | 'non-critical' // whether AJS should expect this plugin to be loaded before starting event delivery
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export type PluginType =
|
|
10
|
+
| 'before'
|
|
11
|
+
| 'after'
|
|
12
|
+
| 'destination'
|
|
13
|
+
| 'enrichment'
|
|
14
|
+
| 'utility'
|
|
15
|
+
|
|
16
|
+
// enrichment - modifies the event. Enrichment can happen in parallel, by reducing all changes in the final event. Failures in this stage could halt event delivery.
|
|
17
|
+
// destination - runs in parallel at the end of the lifecycle. Cannot modify the event, can fail and not halt execution.
|
|
18
|
+
// utility - do not affect lifecycle. Should be run and executed once. Their `track/identify` calls don't really do anything. example
|
|
19
|
+
|
|
20
|
+
export interface CorePlugin<
|
|
21
|
+
Ctx extends CoreContext = CoreContext,
|
|
22
|
+
Analytics extends CoreAnalytics = any
|
|
23
|
+
> {
|
|
24
|
+
name: string
|
|
25
|
+
alternativeNames?: string[]
|
|
26
|
+
version: string
|
|
27
|
+
type: PluginType
|
|
28
|
+
isLoaded: () => boolean
|
|
29
|
+
load: (
|
|
30
|
+
ctx: Ctx,
|
|
31
|
+
instance: Analytics,
|
|
32
|
+
config?: CorePluginConfig
|
|
33
|
+
) => Promise<unknown>
|
|
34
|
+
|
|
35
|
+
unload?: (ctx: Ctx, instance: Analytics) => Promise<unknown> | unknown
|
|
36
|
+
ready?: () => Promise<unknown>
|
|
37
|
+
track?: (ctx: Ctx) => Promise<Ctx> | Ctx
|
|
38
|
+
identify?: (ctx: Ctx) => Promise<Ctx> | Ctx
|
|
39
|
+
page?: (ctx: Ctx) => Promise<Ctx> | Ctx
|
|
40
|
+
group?: (ctx: Ctx) => Promise<Ctx> | Ctx
|
|
41
|
+
alias?: (ctx: Ctx) => Promise<Ctx> | Ctx
|
|
42
|
+
screen?: (ctx: Ctx) => Promise<Ctx> | Ctx
|
|
43
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
type BackoffParams = {
|
|
2
|
+
/** The number of milliseconds before starting the first retry. Default is 500 */
|
|
3
|
+
minTimeout?: number
|
|
4
|
+
|
|
5
|
+
/** The maximum number of milliseconds between two retries. Default is Infinity */
|
|
6
|
+
maxTimeout?: number
|
|
7
|
+
|
|
8
|
+
/** The exponential factor to use. Default is 2. */
|
|
9
|
+
factor?: number
|
|
10
|
+
|
|
11
|
+
/** The current attempt */
|
|
12
|
+
attempt: number
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function backoff(params: BackoffParams): number {
|
|
16
|
+
const random = Math.random() + 1
|
|
17
|
+
const {
|
|
18
|
+
minTimeout = 500,
|
|
19
|
+
factor = 2,
|
|
20
|
+
attempt,
|
|
21
|
+
maxTimeout = Infinity,
|
|
22
|
+
} = params
|
|
23
|
+
return Math.min(random * minTimeout * Math.pow(factor, attempt), maxTimeout)
|
|
24
|
+
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { Emitter } from '../emitter'
|
|
2
|
+
import { backoff } from './backoff'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @internal
|
|
6
|
+
*/
|
|
7
|
+
export const ON_REMOVE_FROM_FUTURE = 'onRemoveFromFuture'
|
|
8
|
+
|
|
9
|
+
interface QueueItem {
|
|
10
|
+
id: string
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export class PriorityQueue<Item extends QueueItem = QueueItem> extends Emitter {
|
|
14
|
+
protected future: Item[] = []
|
|
15
|
+
protected queue: Item[]
|
|
16
|
+
protected seen: Record<string, number>
|
|
17
|
+
|
|
18
|
+
public maxAttempts: number
|
|
19
|
+
|
|
20
|
+
constructor(
|
|
21
|
+
maxAttempts: number,
|
|
22
|
+
queue: Item[],
|
|
23
|
+
seen?: Record<string, number>
|
|
24
|
+
) {
|
|
25
|
+
super()
|
|
26
|
+
this.maxAttempts = maxAttempts
|
|
27
|
+
this.queue = queue
|
|
28
|
+
this.seen = seen ?? {}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
push(...items: Item[]): boolean[] {
|
|
32
|
+
const accepted = items.map((operation) => {
|
|
33
|
+
const attempts = this.updateAttempts(operation)
|
|
34
|
+
|
|
35
|
+
if (attempts > this.maxAttempts || this.includes(operation)) {
|
|
36
|
+
return false
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
this.queue.push(operation)
|
|
40
|
+
return true
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
this.queue = this.queue.sort(
|
|
44
|
+
(a, b) => this.getAttempts(a) - this.getAttempts(b)
|
|
45
|
+
)
|
|
46
|
+
return accepted
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
pushWithBackoff(item: Item): boolean {
|
|
50
|
+
if (this.getAttempts(item) === 0) {
|
|
51
|
+
return this.push(item)[0]
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const attempt = this.updateAttempts(item)
|
|
55
|
+
|
|
56
|
+
if (attempt > this.maxAttempts || this.includes(item)) {
|
|
57
|
+
return false
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const timeout = backoff({ attempt: attempt - 1 })
|
|
61
|
+
|
|
62
|
+
setTimeout(() => {
|
|
63
|
+
this.queue.push(item)
|
|
64
|
+
// remove from future list
|
|
65
|
+
this.future = this.future.filter((f) => f.id !== item.id)
|
|
66
|
+
// Lets listeners know that a 'future' message is now available in the queue
|
|
67
|
+
this.emit(ON_REMOVE_FROM_FUTURE)
|
|
68
|
+
}, timeout)
|
|
69
|
+
|
|
70
|
+
this.future.push(item)
|
|
71
|
+
return true
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
public getAttempts(item: Item): number {
|
|
75
|
+
return this.seen[item.id] ?? 0
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
public updateAttempts(item: Item): number {
|
|
79
|
+
this.seen[item.id] = this.getAttempts(item) + 1
|
|
80
|
+
return this.getAttempts(item)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
includes(item: Item): boolean {
|
|
84
|
+
return (
|
|
85
|
+
this.queue.includes(item) ||
|
|
86
|
+
this.future.includes(item) ||
|
|
87
|
+
Boolean(this.queue.find((i) => i.id === item.id)) ||
|
|
88
|
+
Boolean(this.future.find((i) => i.id === item.id))
|
|
89
|
+
)
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
pop(): Item | undefined {
|
|
93
|
+
return this.queue.shift()
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
public get length(): number {
|
|
97
|
+
return this.queue.length
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
public get todo(): number {
|
|
101
|
+
return this.queue.length + this.future.length
|
|
102
|
+
}
|
|
103
|
+
}
|