@jitsu/functions-lib 2.14.0-beta.8 → 2.14.0-beta.85

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.
@@ -1,368 +0,0 @@
1
- import { AnyEvent, FullContext, UserAgent } from "@jitsu/protocols/functions";
2
- import { AnalyticsServerEvent } from "@jitsu/protocols/analytics";
3
- import { removeUndefined, transferAsSnakeCase, transfer, transferAsClassic } from "./objects";
4
-
5
- export const TableNameParameter = "JITSU_TABLE_NAME";
6
-
7
- export const DropRetryErrorName = "Drop & RetryError";
8
- export const RetryErrorName = "RetryError";
9
- export const NoRetryErrorName = "NoRetryError";
10
-
11
- export class RetryError extends Error {
12
- status: number;
13
- response: string;
14
- message: string;
15
- constructor(message?: any, options?: { drop: boolean }) {
16
- if (typeof message === "object") {
17
- super(message.message);
18
- this.message = message.message;
19
- this.status = message.status;
20
- this.response = message.response;
21
- } else {
22
- super(message);
23
- this.message = message;
24
- }
25
- this.name = options?.drop ? `${DropRetryErrorName}` : `${RetryErrorName}`;
26
- }
27
- toJSON() {
28
- return {
29
- name: this.name,
30
- message: this.message,
31
- status: this.status,
32
- response: this.response,
33
- };
34
- }
35
- }
36
-
37
- export class NoRetryError extends Error {
38
- status: number;
39
- response: string;
40
- message: string;
41
- constructor(message?: any) {
42
- if (typeof message === "object") {
43
- super(message.message);
44
- this.message = message.message;
45
- this.status = message.status;
46
- this.response = message.response;
47
- } else {
48
- super(message);
49
- this.message = message;
50
- }
51
- this.name = "NoRetryError";
52
- }
53
- toJSON() {
54
- return {
55
- name: this.name,
56
- message: this.message,
57
- status: this.status,
58
- response: this.response,
59
- };
60
- }
61
- }
62
-
63
- export class HTTPError extends Error {
64
- status: number;
65
- response: string;
66
- message: string;
67
- constructor(message: string, status: number, response: string) {
68
- super(message);
69
- this.message = message;
70
- this.name = "HTTPError";
71
- this.status = status;
72
- this.response = response.length > 1000 ? response.slice(0, 1000) + "..." : response;
73
- }
74
-
75
- toJSON() {
76
- return {
77
- name: this.name,
78
- message: this.message,
79
- status: this.status,
80
- response: this.response,
81
- };
82
- }
83
- }
84
-
85
- function anonymizeIp(ip: string | undefined) {
86
- if (!ip) {
87
- return;
88
- }
89
- const parts = ip.split(".");
90
- if (parts.length === 4) {
91
- return `${parts[0]}.${parts[1]}.${parts[2]}.0`;
92
- }
93
- }
94
-
95
- export function toJitsuClassic(event: AnalyticsServerEvent, ctx: FullContext): AnyEvent {
96
- const keepOriginalNames = !!ctx.props.keepOriginalNames;
97
- const fileStorage = ctx.destination.type === "s3" || ctx.destination.type === "gcs";
98
- let transferFunc = transferAsSnakeCase;
99
- if (keepOriginalNames) {
100
- if (fileStorage) {
101
- transferFunc = transfer;
102
- } else {
103
- transferFunc = transferAsClassic;
104
- }
105
- }
106
- let url: URL | undefined = undefined;
107
- const analyticsContext = event.context || {};
108
- const urlStr = analyticsContext.page?.url || event.properties?.url;
109
- try {
110
- if (urlStr) {
111
- url = new URL(urlStr as string);
112
- }
113
- } catch (e) {}
114
- const click_id = {};
115
- transferFunc(click_id, analyticsContext.clientIds, ["ga4", "fbp", "fbc"]);
116
- let ids: any = {};
117
- if (Object.keys(analyticsContext.clientIds || {}).length > 0) {
118
- ids = removeUndefined({
119
- ga: analyticsContext.clientIds.ga4?.clientId,
120
- fbp: analyticsContext.clientIds.fbp,
121
- fbc: analyticsContext.clientIds.fbc,
122
- });
123
- }
124
- const geo = analyticsContext.geo || {};
125
- const ua: UserAgent = ctx?.ua || ({} as UserAgent);
126
- const user = removeUndefined({
127
- id: event.userId,
128
- anonymous_id: event.anonymousId,
129
- email: (analyticsContext.traits?.email || event.traits?.email || undefined) as string | undefined,
130
- name: (analyticsContext.traits?.name || event.traits?.name || undefined) as string | undefined,
131
- });
132
- transferFunc(user, analyticsContext.traits, ["email", "name"]);
133
- transferFunc(user, event.traits, ["email", "name"]);
134
- const classic = {
135
- [TableNameParameter]: event[TableNameParameter],
136
- anon_ip: analyticsContext.ip ? anonymizeIp(analyticsContext.ip) : undefined,
137
- api_key: event.writeKey || "",
138
- click_id: Object.keys(click_id).length > 0 ? click_id : undefined,
139
- doc_encoding: analyticsContext.page?.encoding ?? event.properties?.encoding,
140
- doc_host: (analyticsContext.page?.host ?? event.properties?.host) || url?.host,
141
- doc_path: (analyticsContext.page?.path ?? event.properties?.path) || url?.pathname,
142
- doc_search: (analyticsContext.page?.search ?? event.properties?.search) || url?.search,
143
- eventn_ctx_event_id: event.messageId,
144
- event_type: event.event || event.type,
145
- local_tz_offset: analyticsContext.page?.timezoneOffset ?? event.properties?.timezoneOffset,
146
- page_title: analyticsContext.page?.title,
147
- referer: analyticsContext.page?.referrer,
148
- screen_resolution:
149
- Object.keys(analyticsContext.screen || {}).length > 0
150
- ? Math.max(analyticsContext.screen.width || 0) + "x" + Math.max(analyticsContext.screen.height || 0)
151
- : undefined,
152
- source_ip: analyticsContext.ip,
153
- src: event.properties?.src || "jitsu",
154
- url: urlStr as string,
155
- user: Object.keys(user).length > 0 ? user : undefined,
156
- location:
157
- Object.keys(geo).length > 0
158
- ? {
159
- city: geo.city?.name,
160
- continent: geo.continent?.name,
161
- country: geo.country?.code,
162
- country_name: geo.country?.name,
163
- latitude: geo.location?.latitude,
164
- longitude: geo.location?.longitude,
165
- region: geo.region?.code,
166
- zip: geo.postalCode?.code,
167
- timezone: geo.location?.timezone,
168
- autonomous_system_number: geo.provider?.as?.num,
169
- autonomous_system_organization: geo.provider?.as?.name,
170
- isp: geo.provider?.isp,
171
- domain: geo.provider?.domain,
172
- }
173
- : undefined,
174
- ids: Object.keys(ids).length > 0 ? ids : undefined,
175
- parsed_ua:
176
- event.parsed_ua ||
177
- (Object.keys(ua).length > 0
178
- ? {
179
- os_family: ua.os?.name,
180
- os_version: ua.os?.version,
181
- ua_family: ua.browser?.name,
182
- ua_version: ua.browser?.version,
183
- device_brand: ua.device?.vendor,
184
- device_type: ua.device?.type,
185
- device_model: ua.device?.model,
186
- bot: ua.bot,
187
- }
188
- : undefined),
189
- user_agent: analyticsContext.userAgent,
190
- user_language: analyticsContext.locale,
191
- utc_time: event.timestamp,
192
- _timestamp: event.receivedAt,
193
- utm: analyticsContext.campaign,
194
- vp_size:
195
- Object.keys(analyticsContext.screen || {}).length > 0
196
- ? Math.max(analyticsContext.screen.innerWidth || 0) + "x" + Math.max(analyticsContext.screen.innerHeight || 0)
197
- : undefined,
198
- };
199
- if (event.type === "track") {
200
- transferFunc(classic, event.properties);
201
- } else {
202
- transferFunc(classic, event.properties, ["url", "title", "referrer", "search", "host", "path", "width", "height"]);
203
- }
204
-
205
- return removeUndefined(classic);
206
- }
207
-
208
- export function fromJitsuClassic(event: AnyEvent): AnyEvent {
209
- let type = "track";
210
- let eventName: string | undefined = undefined;
211
- switch ((event.event_type ?? "").toLowerCase()) {
212
- case "pageview":
213
- case "page_view":
214
- case "page":
215
- type = "page";
216
- eventName = event.event_type;
217
- break;
218
- case "identify":
219
- type = "identify";
220
- break;
221
- case "screen":
222
- type = "screen";
223
- break;
224
- case "group":
225
- type = "group";
226
- break;
227
- case "alias":
228
- type = "alias";
229
- break;
230
- default:
231
- type = "track";
232
- eventName = event.event_type;
233
- break;
234
- }
235
- const clientIds =
236
- Object.keys(event.ids || event.click_id || {}).length > 0
237
- ? {
238
- ga4: event.ids?.ga
239
- ? {
240
- clientId: event.ids.ga,
241
- }
242
- : undefined,
243
- fbp: event.ids?.fbp,
244
- fbc: event.ids?.fbc,
245
- ...event.click_id,
246
- }
247
- : undefined;
248
- const loc = event.location || {};
249
- const geo =
250
- Object.keys(loc).length > 0
251
- ? {
252
- city: {
253
- name: loc.city,
254
- },
255
- continent: {
256
- code: loc.continent,
257
- },
258
- country: {
259
- code: loc.country,
260
- name: loc.country_name,
261
- },
262
- location: {
263
- latitude: loc.latitude,
264
- longitude: loc.longitude,
265
- timezone: loc.timezone,
266
- },
267
- region: {
268
- code: loc.region,
269
- },
270
- postalCode: {
271
- code: loc.zip,
272
- },
273
- provider: {
274
- as: {
275
- num: loc.autonomous_system_number,
276
- name: loc.autonomous_system_organization,
277
- },
278
- isp: loc.isp,
279
- domain: loc.domain,
280
- },
281
- }
282
- : undefined;
283
- const traits = {};
284
- transfer(traits, event.user, ["id", "anonymous_id"]);
285
- const properties: any = {};
286
- transfer(properties, event, [
287
- TableNameParameter,
288
- "anon_ip",
289
- "api_key",
290
- "click_id",
291
- "doc_encoding",
292
- "doc_host",
293
- "doc_path",
294
- "doc_search",
295
- "eventn_ctx_event_id",
296
- "event_type",
297
- "local_tz_offset",
298
- "page_title",
299
- "referer",
300
- "screen_resolution",
301
- "source_ip",
302
- "url",
303
- "user",
304
- "location",
305
- "parsed_ua",
306
- "user_agent",
307
- "user_language",
308
- "utc_time",
309
- "_timestamp",
310
- "utm",
311
- "vp_size",
312
- ]);
313
- if (type === "page") {
314
- properties.url = event.url;
315
- properties.title = event.page_title;
316
- properties.referrer = event.referer;
317
- properties.search = event.doc_search;
318
- properties.host = event.doc_host;
319
- properties.path = event.doc_path;
320
- properties.width = parseInt(event.vp_size?.split("x")[0]);
321
- properties.height = parseInt(event.vp_size?.split("x")[1]);
322
- }
323
- const screen: any = {};
324
- const sr = event.screen_resolution?.split("x");
325
- if (sr?.length === 2) {
326
- screen.width = parseInt(sr[0]);
327
- screen.height = parseInt(sr[1]);
328
- }
329
- const vs = event.vp_size?.split("x");
330
- if (vs?.length === 2) {
331
- screen.innerWidth = parseInt(vs[0]);
332
- screen.innerHeight = parseInt(vs[1]);
333
- }
334
-
335
- return removeUndefined({
336
- [TableNameParameter]: event[TableNameParameter],
337
- messageId: event.eventn_ctx_event_id,
338
- userId: event.user?.id,
339
- anonymousId: event.user?.anonymous_id,
340
- timestamp: event.utc_time,
341
- receivedAt: event._timestamp,
342
- writeKey: event.api_key,
343
- type,
344
- event: eventName,
345
- context: {
346
- ip: event.source_ip,
347
- locale: event.user_language,
348
- userAgent: event.user_agent,
349
- page: {
350
- url: event.url,
351
- title: event.page_title,
352
- referrer: event.referer,
353
- search: event.doc_search,
354
- host: event.doc_host,
355
- path: event.doc_path,
356
- encoding: event.doc_encoding,
357
- timezoneOffset: event.local_tz_offset,
358
- },
359
- screen: Object.keys(screen).length > 0 ? screen : undefined,
360
- clientIds,
361
- campaign: event.utm,
362
- traits,
363
- geo,
364
- },
365
- properties,
366
- traits: type === "identify" || type === "group" ? traits : undefined,
367
- });
368
- }
@@ -1,96 +0,0 @@
1
- import { idToClassic, idToSnakeCaseFast } from "./strings";
2
-
3
- export function toSnakeCase(param: any): any {
4
- if (Array.isArray(param)) {
5
- return param.map(toSnakeCase);
6
- } else if (typeof param === "object" && param !== null) {
7
- const r = {};
8
- for (const [key, value] of Object.entries(param)) {
9
- r[idToSnakeCaseFast(key)] = toSnakeCase(value);
10
- }
11
- return r;
12
- } else {
13
- return param;
14
- }
15
- }
16
-
17
- export function toClassic(param: any): any {
18
- if (Array.isArray(param)) {
19
- return param.map(toClassic);
20
- } else if (typeof param === "object" && param !== null) {
21
- const r = {};
22
- for (const [key, value] of Object.entries(param)) {
23
- r[idToClassic(key)] = toClassic(value);
24
- }
25
- return r;
26
- } else {
27
- return param;
28
- }
29
- }
30
-
31
- export function removeUndefined(param: any): any {
32
- if (Array.isArray(param)) {
33
- return param.map(removeUndefined);
34
- } else if (typeof param === "object" && param !== null) {
35
- for (const [key, value] of Object.entries(param)) {
36
- switch (typeof value) {
37
- case "undefined":
38
- delete param[key];
39
- break;
40
- case "object":
41
- if (value !== null) {
42
- removeUndefined(value);
43
- }
44
- break;
45
- }
46
- }
47
- }
48
- return param;
49
- }
50
-
51
- export function transferAsSnakeCase(target: Record<string, any>, source: any, omit?: string[]) {
52
- if (typeof source !== "object") {
53
- return;
54
- }
55
- for (const [k, v] of Object.entries(source)) {
56
- if (!omit || !omit.includes(k)) {
57
- target[idToSnakeCaseFast(k)] = toSnakeCase(v);
58
- }
59
- }
60
- }
61
-
62
- export function transferAsClassic(target: Record<string, any>, source: any, omit?: string[]) {
63
- if (typeof source !== "object") {
64
- return;
65
- }
66
- for (const [k, v] of Object.entries(source)) {
67
- if (!omit || !omit.includes(k)) {
68
- target[idToClassic(k)] = toClassic(v);
69
- }
70
- }
71
- }
72
-
73
- export function transferValueAsSnakeCase(target: Record<string, any>, property: string, source: any) {
74
- if (typeof source === "undefined") {
75
- return;
76
- }
77
- target[property] = toSnakeCase(source);
78
- }
79
-
80
- export function transfer(target: Record<string, any>, source: any, omit?: string[]) {
81
- if (typeof source !== "object") {
82
- return;
83
- }
84
- for (const [k, v] of Object.entries(source)) {
85
- if (!omit || !omit.includes(k)) {
86
- target[k] = v;
87
- }
88
- }
89
- }
90
-
91
- export function transferValue(target: Record<string, any>, property: string, source: any) {
92
- if (typeof source === "undefined") {
93
- return;
94
- }
95
- target[property] = source;
96
- }
@@ -1,60 +0,0 @@
1
- const ACode = "A".charCodeAt(0);
2
- const ZCode = "Z".charCodeAt(0);
3
- const aCode = "a".charCodeAt(0);
4
- const zCode = "z".charCodeAt(0);
5
- const zeroCode = "0".charCodeAt(0);
6
- const nineCode = "9".charCodeAt(0);
7
- const spaceCode = " ".charCodeAt(0);
8
- const underscodeCode = "_".charCodeAt(0);
9
-
10
- export function idToSnakeCaseFast(id: string) {
11
- let res = "";
12
- let concatIndex = 0;
13
- let i = 0;
14
- let needUnderscore = false;
15
- for (; i < id.length; i++) {
16
- const c = id.charCodeAt(i);
17
- if (c >= ACode && c <= ZCode) {
18
- res += id.substring(concatIndex, i) + (needUnderscore ? "_" : "") + id.charAt(i).toLowerCase();
19
- concatIndex = i + 1;
20
- } else if (c == spaceCode) {
21
- res += id.substring(concatIndex, i) + "_";
22
- concatIndex = i + 1;
23
- }
24
- // needUnderscore is used in case next char is a capital latin letter
25
- // we add underscore only between latin letters
26
- needUnderscore = (c >= aCode && c <= zCode) || (c >= ACode && c <= ZCode);
27
- }
28
- if (concatIndex == 0) {
29
- return id;
30
- } else if (concatIndex < i) {
31
- res += id.substring(concatIndex, i);
32
- }
33
- return res;
34
- }
35
-
36
- export function idToClassic(id: string) {
37
- let needConvert = false;
38
- for (let i = 0; i < id.length; i++) {
39
- const c = id.charCodeAt(i);
40
- if (!((c >= aCode && c <= zCode) || (c >= zeroCode && c <= nineCode) || c == underscodeCode)) {
41
- needConvert = true;
42
- break;
43
- }
44
- }
45
- if (!needConvert) {
46
- return id;
47
- }
48
- let res = "";
49
- for (let i = 0; i < id.length; i++) {
50
- const c = id.charCodeAt(i);
51
- if (c >= ACode && c <= ZCode) {
52
- res += id.charAt(i).toLowerCase();
53
- } else if ((c >= aCode && c <= zCode) || (c >= zeroCode && c <= nineCode)) {
54
- res += id.charAt(i);
55
- } else {
56
- res += "_";
57
- }
58
- }
59
- return res;
60
- }
package/tsconfig.json DELETED
@@ -1,20 +0,0 @@
1
- {
2
- "extends": "@jitsu/common-config/tsconfig.json",
3
- "compilerOptions": {
4
- "lib": ["dom", "esnext"],
5
- "rootDir": "./src",
6
- "outDir": "./dist",
7
- "declaration": true,
8
- "noEmit": true,
9
- "strictPropertyInitialization": false,
10
- "strictNullChecks": false
11
- },
12
- "include": ["src/**/*"],
13
- "exclude": [
14
- "__tests__",
15
- "dist",
16
- "test_projects",
17
- "test",
18
- "templates"
19
- ]
20
- }
package/vitest.config.ts DELETED
@@ -1,8 +0,0 @@
1
- import { mergeConfig } from "vitest/config";
2
- import baseConfig from "@jitsu/common-config/vitest.config";
3
-
4
- export default mergeConfig(baseConfig, {
5
- test: {
6
- setupFiles: ["@jitsu/common-config/vitest.setup.ts"],
7
- },
8
- });