New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@jitsu/functions-lib

Package Overview
Dependencies
Maintainers
0
Versions
38
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@jitsu/functions-lib - npm Package Compare versions

Comparing version

to
1.9.13-canary.1167.20250215132227

__tests__/classic-mapping.test.ts

446

dist/index.cjs.js
'use strict';
const ACode = "A".charCodeAt(0);
const ZCode = "Z".charCodeAt(0);
const aCode = "a".charCodeAt(0);
const zCode = "z".charCodeAt(0);
const zeroCode = "0".charCodeAt(0);
const nineCode = "9".charCodeAt(0);
const spaceCode = " ".charCodeAt(0);
const underscodeCode = "_".charCodeAt(0);
function idToSnakeCaseFast(id) {
let res = "";
let concatIndex = 0;
let i = 0;
let needUnderscore = false;
for (; i < id.length; i++) {
const c = id.charCodeAt(i);
if (c >= ACode && c <= ZCode) {
res += id.substring(concatIndex, i) + (needUnderscore ? "_" : "") + id.charAt(i).toLowerCase();
concatIndex = i + 1;
}
else if (c == spaceCode) {
res += id.substring(concatIndex, i) + "_";
concatIndex = i + 1;
}
// needUnderscore is used in case next char is a capital latin letter
// we add underscore only between latin letters
needUnderscore = (c >= aCode && c <= zCode) || (c >= ACode && c <= ZCode);
}
if (concatIndex == 0) {
return id;
}
else if (concatIndex < i) {
res += id.substring(concatIndex, i);
}
return res;
}
function idToClassic(id) {
let needConvert = false;
for (let i = 0; i < id.length; i++) {
const c = id.charCodeAt(i);
if (!((c >= aCode && c <= zCode) || (c >= zeroCode && c <= nineCode) || c == underscodeCode)) {
needConvert = true;
break;
}
}
if (!needConvert) {
return id;
}
let res = "";
for (let i = 0; i < id.length; i++) {
const c = id.charCodeAt(i);
if (c >= ACode && c <= ZCode) {
res += id.charAt(i).toLowerCase();
}
else if ((c >= aCode && c <= zCode) || (c >= zeroCode && c <= nineCode)) {
res += id.charAt(i);
}
else {
res += "_";
}
}
return res;
}
function toSnakeCase(param) {
if (Array.isArray(param)) {
return param.map(toSnakeCase);
}
else if (typeof param === "object" && param !== null) {
const r = {};
for (const [key, value] of Object.entries(param)) {
r[idToSnakeCaseFast(key)] = toSnakeCase(value);
}
return r;
}
else {
return param;
}
}
function toClassic(param) {
if (Array.isArray(param)) {
return param.map(toClassic);
}
else if (typeof param === "object" && param !== null) {
const r = {};
for (const [key, value] of Object.entries(param)) {
r[idToClassic(key)] = toClassic(value);
}
return r;
}
else {
return param;
}
}
function removeUndefined(param) {
if (Array.isArray(param)) {
return param.map(removeUndefined);
}
else if (typeof param === "object" && param !== null) {
for (const [key, value] of Object.entries(param)) {
switch (typeof value) {
case "undefined":
delete param[key];
break;
case "object":
if (value !== null) {
removeUndefined(value);
}
break;
}
}
}
return param;
}
function transferAsSnakeCase(target, source, omit) {
if (typeof source !== "object") {
return;
}
for (const [k, v] of Object.entries(source)) {
if (!omit || !omit.includes(k)) {
target[idToSnakeCaseFast(k)] = toSnakeCase(v);
}
}
}
function transferAsClassic(target, source, omit) {
if (typeof source !== "object") {
return;
}
for (const [k, v] of Object.entries(source)) {
if (!omit || !omit.includes(k)) {
target[idToClassic(k)] = toClassic(v);
}
}
}
function transferValueAsSnakeCase(target, property, source) {
if (typeof source === "undefined") {
return;
}
target[property] = toSnakeCase(source);
}
function transfer(target, source, omit) {
if (typeof source !== "object") {
return;
}
for (const [k, v] of Object.entries(source)) {
if (!omit || !omit.includes(k)) {
target[k] = v;
}
}
}
function transferValue(target, property, source) {
if (typeof source === "undefined") {
return;
}
target[property] = source;
}
const TableNameParameter = "JITSU_TABLE_NAME";
const DropRetryErrorName = "Drop & RetryError";

@@ -51,2 +208,278 @@ const RetryErrorName = "RetryError";

}
function anonymizeIp(ip) {
if (!ip) {
return;
}
const parts = ip.split(".");
if (parts.length === 4) {
return `${parts[0]}.${parts[1]}.${parts[2]}.0`;
}
}
function toJitsuClassic(event, ctx) {
const keepOriginalNames = !!ctx.props.keepOriginalNames;
const fileStorage = ctx.destination.type === "s3" || ctx.destination.type === "gcs";
let transferFunc = transferAsSnakeCase;
if (keepOriginalNames) {
if (fileStorage) {
transferFunc = transfer;
}
else {
transferFunc = transferAsClassic;
}
}
let url = undefined;
const analyticsContext = event.context || {};
const urlStr = analyticsContext.page?.url || event.properties?.url;
try {
if (urlStr) {
url = new URL(urlStr);
}
}
catch (e) { }
const click_id = {};
transferFunc(click_id, analyticsContext.clientIds, ["ga4", "fbp", "fbc"]);
let ids = {};
if (Object.keys(analyticsContext.clientIds || {}).length > 0) {
ids = removeUndefined({
ga: analyticsContext.clientIds.ga4?.clientId,
fbp: analyticsContext.clientIds.fbp,
fbc: analyticsContext.clientIds.fbc,
});
}
const geo = analyticsContext.geo || {};
const ua = ctx?.ua || {};
const user = removeUndefined({
id: event.userId,
anonymous_id: event.anonymousId,
email: (analyticsContext.traits?.email || event.traits?.email || undefined),
name: (analyticsContext.traits?.name || event.traits?.name || undefined),
});
transferFunc(user, analyticsContext.traits, ["email", "name"]);
transferFunc(user, event.traits, ["email", "name"]);
const classic = {
[TableNameParameter]: event[TableNameParameter],
anon_ip: analyticsContext.ip ? anonymizeIp(analyticsContext.ip) : undefined,
api_key: event.writeKey || "",
click_id: Object.keys(click_id).length > 0 ? click_id : undefined,
doc_encoding: analyticsContext.page?.encoding ?? event.properties?.encoding,
doc_host: (analyticsContext.page?.host ?? event.properties?.host) || url?.host,
doc_path: (analyticsContext.page?.path ?? event.properties?.path) || url?.pathname,
doc_search: (analyticsContext.page?.search ?? event.properties?.search) || url?.search,
eventn_ctx_event_id: event.messageId,
event_type: event.event || event.type,
local_tz_offset: analyticsContext.page?.timezoneOffset ?? event.properties?.timezoneOffset,
page_title: analyticsContext.page?.title,
referer: analyticsContext.page?.referrer,
screen_resolution: Object.keys(analyticsContext.screen || {}).length > 0
? Math.max(analyticsContext.screen.width || 0) + "x" + Math.max(analyticsContext.screen.height || 0)
: undefined,
source_ip: analyticsContext.ip,
src: event.properties?.src || "jitsu",
url: urlStr,
user: Object.keys(user).length > 0 ? user : undefined,
location: Object.keys(geo).length > 0
? {
city: geo.city?.name,
continent: geo.continent?.name,
country: geo.country?.code,
country_name: geo.country?.name,
latitude: geo.location?.latitude,
longitude: geo.location?.longitude,
region: geo.region?.code,
zip: geo.postalCode?.code,
timezone: geo.location?.timezone,
autonomous_system_number: geo.provider?.as?.num,
autonomous_system_organization: geo.provider?.as?.name,
isp: geo.provider?.isp,
domain: geo.provider?.domain,
}
: undefined,
ids: Object.keys(ids).length > 0 ? ids : undefined,
parsed_ua: Object.keys(ua).length > 0
? {
os_family: ua.os?.name,
os_version: ua.os?.version,
ua_family: ua.browser?.name,
ua_version: ua.browser?.version,
device_brand: ua.device?.vendor,
device_type: ua.device?.type,
device_model: ua.device?.model,
bot: ua.bot,
}
: undefined,
user_agent: analyticsContext.userAgent,
user_language: analyticsContext.locale,
utc_time: event.timestamp,
_timestamp: event.receivedAt,
utm: analyticsContext.campaign,
vp_size: Object.keys(analyticsContext.screen || {}).length > 0
? Math.max(analyticsContext.screen.innerWidth || 0) + "x" + Math.max(analyticsContext.screen.innerHeight || 0)
: undefined,
};
if (event.type === "track") {
transferFunc(classic, event.properties);
}
else {
transferFunc(classic, event.properties, ["url", "title", "referrer", "search", "host", "path", "width", "height"]);
}
return removeUndefined(classic);
}
function fromJitsuClassic(event) {
let type = "track";
let eventName = undefined;
switch ((event.event_type ?? "").toLowerCase()) {
case "pageview":
case "page_view":
case "page":
type = "page";
eventName = event.event_type;
break;
case "identify":
type = "identify";
break;
case "screen":
type = "screen";
break;
case "group":
type = "group";
break;
case "alias":
type = "alias";
break;
default:
type = "track";
eventName = event.event_type;
break;
}
const clientIds = Object.keys(event.ids || event.click_id || {}).length > 0
? {
ga4: event.ids?.ga
? {
clientId: event.ids.ga,
}
: undefined,
fbp: event.ids?.fbp,
fbc: event.ids?.fbc,
...event.click_id,
}
: undefined;
const loc = event.location || {};
const geo = Object.keys(loc).length > 0
? {
city: {
name: loc.city,
},
continent: {
code: loc.continent,
},
country: {
code: loc.country,
name: loc.country_name,
},
location: {
latitude: loc.latitude,
longitude: loc.longitude,
timezone: loc.timezone,
},
region: {
code: loc.region,
},
postalCode: {
code: loc.zip,
},
provider: {
as: {
num: loc.autonomous_system_number,
name: loc.autonomous_system_organization,
},
isp: loc.isp,
domain: loc.domain,
},
}
: undefined;
const traits = {};
transfer(traits, event.user, ["id", "anonymous_id"]);
const properties = {};
transfer(properties, event, [
TableNameParameter,
"anon_ip",
"api_key",
"click_id",
"doc_encoding",
"doc_host",
"doc_path",
"doc_search",
"eventn_ctx_event_id",
"event_type",
"local_tz_offset",
"page_title",
"referer",
"screen_resolution",
"source_ip",
"url",
"user",
"location",
"parsed_ua",
"user_agent",
"user_language",
"utc_time",
"_timestamp",
"utm",
"vp_size",
]);
if (type === "page") {
properties.url = event.url;
properties.title = event.page_title;
properties.referrer = event.referer;
properties.search = event.doc_search;
properties.host = event.doc_host;
properties.path = event.doc_path;
properties.width = parseInt(event.vp_size?.split("x")[0]);
properties.height = parseInt(event.vp_size?.split("x")[1]);
}
const screen = {};
const sr = event.screen_resolution?.split("x");
if (sr?.length === 2) {
screen.width = parseInt(sr[0]);
screen.height = parseInt(sr[1]);
}
const vs = event.vp_size?.split("x");
if (vs?.length === 2) {
screen.innerWidth = parseInt(vs[0]);
screen.innerHeight = parseInt(vs[1]);
}
return removeUndefined({
[TableNameParameter]: event[TableNameParameter],
messageId: event.eventn_ctx_event_id,
userId: event.user?.id,
anonymousId: event.user?.anonymous_id,
timestamp: event.utc_time,
receivedAt: event._timestamp,
writeKey: event.api_key,
type,
event: eventName,
context: {
ip: event.source_ip,
locale: event.user_language,
userAgent: event.user_agent,
page: {
url: event.url,
title: event.page_title,
referrer: event.referer,
search: event.doc_search,
host: event.doc_host,
path: event.doc_path,
encoding: event.doc_encoding,
timezoneOffset: event.local_tz_offset,
},
screen: Object.keys(screen).length > 0 ? screen : undefined,
clientIds,
campaign: event.utm,
traits,
geo,
},
properties,
traits: type === "identify" || type === "group" ? traits : undefined,
});
}

@@ -57,1 +490,14 @@ exports.DropRetryErrorName = DropRetryErrorName;

exports.RetryErrorName = RetryErrorName;
exports.TableNameParameter = TableNameParameter;
exports.fromJitsuClassic = fromJitsuClassic;
exports.idToClassic = idToClassic;
exports.idToSnakeCaseFast = idToSnakeCaseFast;
exports.removeUndefined = removeUndefined;
exports.toClassic = toClassic;
exports.toJitsuClassic = toJitsuClassic;
exports.toSnakeCase = toSnakeCase;
exports.transfer = transfer;
exports.transferAsClassic = transferAsClassic;
exports.transferAsSnakeCase = transferAsSnakeCase;
exports.transferValue = transferValue;
exports.transferValueAsSnakeCase = transferValueAsSnakeCase;

2

dist/index.d.ts
export * from "./lib/functions";
export * from "./lib/objects";
export * from "./lib/strings";

@@ -0,1 +1,158 @@

const ACode = "A".charCodeAt(0);
const ZCode = "Z".charCodeAt(0);
const aCode = "a".charCodeAt(0);
const zCode = "z".charCodeAt(0);
const zeroCode = "0".charCodeAt(0);
const nineCode = "9".charCodeAt(0);
const spaceCode = " ".charCodeAt(0);
const underscodeCode = "_".charCodeAt(0);
function idToSnakeCaseFast(id) {
let res = "";
let concatIndex = 0;
let i = 0;
let needUnderscore = false;
for (; i < id.length; i++) {
const c = id.charCodeAt(i);
if (c >= ACode && c <= ZCode) {
res += id.substring(concatIndex, i) + (needUnderscore ? "_" : "") + id.charAt(i).toLowerCase();
concatIndex = i + 1;
}
else if (c == spaceCode) {
res += id.substring(concatIndex, i) + "_";
concatIndex = i + 1;
}
// needUnderscore is used in case next char is a capital latin letter
// we add underscore only between latin letters
needUnderscore = (c >= aCode && c <= zCode) || (c >= ACode && c <= ZCode);
}
if (concatIndex == 0) {
return id;
}
else if (concatIndex < i) {
res += id.substring(concatIndex, i);
}
return res;
}
function idToClassic(id) {
let needConvert = false;
for (let i = 0; i < id.length; i++) {
const c = id.charCodeAt(i);
if (!((c >= aCode && c <= zCode) || (c >= zeroCode && c <= nineCode) || c == underscodeCode)) {
needConvert = true;
break;
}
}
if (!needConvert) {
return id;
}
let res = "";
for (let i = 0; i < id.length; i++) {
const c = id.charCodeAt(i);
if (c >= ACode && c <= ZCode) {
res += id.charAt(i).toLowerCase();
}
else if ((c >= aCode && c <= zCode) || (c >= zeroCode && c <= nineCode)) {
res += id.charAt(i);
}
else {
res += "_";
}
}
return res;
}
function toSnakeCase(param) {
if (Array.isArray(param)) {
return param.map(toSnakeCase);
}
else if (typeof param === "object" && param !== null) {
const r = {};
for (const [key, value] of Object.entries(param)) {
r[idToSnakeCaseFast(key)] = toSnakeCase(value);
}
return r;
}
else {
return param;
}
}
function toClassic(param) {
if (Array.isArray(param)) {
return param.map(toClassic);
}
else if (typeof param === "object" && param !== null) {
const r = {};
for (const [key, value] of Object.entries(param)) {
r[idToClassic(key)] = toClassic(value);
}
return r;
}
else {
return param;
}
}
function removeUndefined(param) {
if (Array.isArray(param)) {
return param.map(removeUndefined);
}
else if (typeof param === "object" && param !== null) {
for (const [key, value] of Object.entries(param)) {
switch (typeof value) {
case "undefined":
delete param[key];
break;
case "object":
if (value !== null) {
removeUndefined(value);
}
break;
}
}
}
return param;
}
function transferAsSnakeCase(target, source, omit) {
if (typeof source !== "object") {
return;
}
for (const [k, v] of Object.entries(source)) {
if (!omit || !omit.includes(k)) {
target[idToSnakeCaseFast(k)] = toSnakeCase(v);
}
}
}
function transferAsClassic(target, source, omit) {
if (typeof source !== "object") {
return;
}
for (const [k, v] of Object.entries(source)) {
if (!omit || !omit.includes(k)) {
target[idToClassic(k)] = toClassic(v);
}
}
}
function transferValueAsSnakeCase(target, property, source) {
if (typeof source === "undefined") {
return;
}
target[property] = toSnakeCase(source);
}
function transfer(target, source, omit) {
if (typeof source !== "object") {
return;
}
for (const [k, v] of Object.entries(source)) {
if (!omit || !omit.includes(k)) {
target[k] = v;
}
}
}
function transferValue(target, property, source) {
if (typeof source === "undefined") {
return;
}
target[property] = source;
}
const TableNameParameter = "JITSU_TABLE_NAME";
const DropRetryErrorName = "Drop & RetryError";

@@ -49,3 +206,279 @@ const RetryErrorName = "RetryError";

}
function anonymizeIp(ip) {
if (!ip) {
return;
}
const parts = ip.split(".");
if (parts.length === 4) {
return `${parts[0]}.${parts[1]}.${parts[2]}.0`;
}
}
function toJitsuClassic(event, ctx) {
const keepOriginalNames = !!ctx.props.keepOriginalNames;
const fileStorage = ctx.destination.type === "s3" || ctx.destination.type === "gcs";
let transferFunc = transferAsSnakeCase;
if (keepOriginalNames) {
if (fileStorage) {
transferFunc = transfer;
}
else {
transferFunc = transferAsClassic;
}
}
let url = undefined;
const analyticsContext = event.context || {};
const urlStr = analyticsContext.page?.url || event.properties?.url;
try {
if (urlStr) {
url = new URL(urlStr);
}
}
catch (e) { }
const click_id = {};
transferFunc(click_id, analyticsContext.clientIds, ["ga4", "fbp", "fbc"]);
let ids = {};
if (Object.keys(analyticsContext.clientIds || {}).length > 0) {
ids = removeUndefined({
ga: analyticsContext.clientIds.ga4?.clientId,
fbp: analyticsContext.clientIds.fbp,
fbc: analyticsContext.clientIds.fbc,
});
}
const geo = analyticsContext.geo || {};
const ua = ctx?.ua || {};
const user = removeUndefined({
id: event.userId,
anonymous_id: event.anonymousId,
email: (analyticsContext.traits?.email || event.traits?.email || undefined),
name: (analyticsContext.traits?.name || event.traits?.name || undefined),
});
transferFunc(user, analyticsContext.traits, ["email", "name"]);
transferFunc(user, event.traits, ["email", "name"]);
const classic = {
[TableNameParameter]: event[TableNameParameter],
anon_ip: analyticsContext.ip ? anonymizeIp(analyticsContext.ip) : undefined,
api_key: event.writeKey || "",
click_id: Object.keys(click_id).length > 0 ? click_id : undefined,
doc_encoding: analyticsContext.page?.encoding ?? event.properties?.encoding,
doc_host: (analyticsContext.page?.host ?? event.properties?.host) || url?.host,
doc_path: (analyticsContext.page?.path ?? event.properties?.path) || url?.pathname,
doc_search: (analyticsContext.page?.search ?? event.properties?.search) || url?.search,
eventn_ctx_event_id: event.messageId,
event_type: event.event || event.type,
local_tz_offset: analyticsContext.page?.timezoneOffset ?? event.properties?.timezoneOffset,
page_title: analyticsContext.page?.title,
referer: analyticsContext.page?.referrer,
screen_resolution: Object.keys(analyticsContext.screen || {}).length > 0
? Math.max(analyticsContext.screen.width || 0) + "x" + Math.max(analyticsContext.screen.height || 0)
: undefined,
source_ip: analyticsContext.ip,
src: event.properties?.src || "jitsu",
url: urlStr,
user: Object.keys(user).length > 0 ? user : undefined,
location: Object.keys(geo).length > 0
? {
city: geo.city?.name,
continent: geo.continent?.name,
country: geo.country?.code,
country_name: geo.country?.name,
latitude: geo.location?.latitude,
longitude: geo.location?.longitude,
region: geo.region?.code,
zip: geo.postalCode?.code,
timezone: geo.location?.timezone,
autonomous_system_number: geo.provider?.as?.num,
autonomous_system_organization: geo.provider?.as?.name,
isp: geo.provider?.isp,
domain: geo.provider?.domain,
}
: undefined,
ids: Object.keys(ids).length > 0 ? ids : undefined,
parsed_ua: Object.keys(ua).length > 0
? {
os_family: ua.os?.name,
os_version: ua.os?.version,
ua_family: ua.browser?.name,
ua_version: ua.browser?.version,
device_brand: ua.device?.vendor,
device_type: ua.device?.type,
device_model: ua.device?.model,
bot: ua.bot,
}
: undefined,
user_agent: analyticsContext.userAgent,
user_language: analyticsContext.locale,
utc_time: event.timestamp,
_timestamp: event.receivedAt,
utm: analyticsContext.campaign,
vp_size: Object.keys(analyticsContext.screen || {}).length > 0
? Math.max(analyticsContext.screen.innerWidth || 0) + "x" + Math.max(analyticsContext.screen.innerHeight || 0)
: undefined,
};
if (event.type === "track") {
transferFunc(classic, event.properties);
}
else {
transferFunc(classic, event.properties, ["url", "title", "referrer", "search", "host", "path", "width", "height"]);
}
return removeUndefined(classic);
}
function fromJitsuClassic(event) {
let type = "track";
let eventName = undefined;
switch ((event.event_type ?? "").toLowerCase()) {
case "pageview":
case "page_view":
case "page":
type = "page";
eventName = event.event_type;
break;
case "identify":
type = "identify";
break;
case "screen":
type = "screen";
break;
case "group":
type = "group";
break;
case "alias":
type = "alias";
break;
default:
type = "track";
eventName = event.event_type;
break;
}
const clientIds = Object.keys(event.ids || event.click_id || {}).length > 0
? {
ga4: event.ids?.ga
? {
clientId: event.ids.ga,
}
: undefined,
fbp: event.ids?.fbp,
fbc: event.ids?.fbc,
...event.click_id,
}
: undefined;
const loc = event.location || {};
const geo = Object.keys(loc).length > 0
? {
city: {
name: loc.city,
},
continent: {
code: loc.continent,
},
country: {
code: loc.country,
name: loc.country_name,
},
location: {
latitude: loc.latitude,
longitude: loc.longitude,
timezone: loc.timezone,
},
region: {
code: loc.region,
},
postalCode: {
code: loc.zip,
},
provider: {
as: {
num: loc.autonomous_system_number,
name: loc.autonomous_system_organization,
},
isp: loc.isp,
domain: loc.domain,
},
}
: undefined;
const traits = {};
transfer(traits, event.user, ["id", "anonymous_id"]);
const properties = {};
transfer(properties, event, [
TableNameParameter,
"anon_ip",
"api_key",
"click_id",
"doc_encoding",
"doc_host",
"doc_path",
"doc_search",
"eventn_ctx_event_id",
"event_type",
"local_tz_offset",
"page_title",
"referer",
"screen_resolution",
"source_ip",
"url",
"user",
"location",
"parsed_ua",
"user_agent",
"user_language",
"utc_time",
"_timestamp",
"utm",
"vp_size",
]);
if (type === "page") {
properties.url = event.url;
properties.title = event.page_title;
properties.referrer = event.referer;
properties.search = event.doc_search;
properties.host = event.doc_host;
properties.path = event.doc_path;
properties.width = parseInt(event.vp_size?.split("x")[0]);
properties.height = parseInt(event.vp_size?.split("x")[1]);
}
const screen = {};
const sr = event.screen_resolution?.split("x");
if (sr?.length === 2) {
screen.width = parseInt(sr[0]);
screen.height = parseInt(sr[1]);
}
const vs = event.vp_size?.split("x");
if (vs?.length === 2) {
screen.innerWidth = parseInt(vs[0]);
screen.innerHeight = parseInt(vs[1]);
}
return removeUndefined({
[TableNameParameter]: event[TableNameParameter],
messageId: event.eventn_ctx_event_id,
userId: event.user?.id,
anonymousId: event.user?.anonymous_id,
timestamp: event.utc_time,
receivedAt: event._timestamp,
writeKey: event.api_key,
type,
event: eventName,
context: {
ip: event.source_ip,
locale: event.user_language,
userAgent: event.user_agent,
page: {
url: event.url,
title: event.page_title,
referrer: event.referer,
search: event.doc_search,
host: event.doc_host,
path: event.doc_path,
encoding: event.doc_encoding,
timezoneOffset: event.local_tz_offset,
},
screen: Object.keys(screen).length > 0 ? screen : undefined,
clientIds,
campaign: event.utm,
traits,
geo,
},
properties,
traits: type === "identify" || type === "group" ? traits : undefined,
});
}
export { DropRetryErrorName, HTTPError, RetryError, RetryErrorName };
export { DropRetryErrorName, HTTPError, RetryError, RetryErrorName, TableNameParameter, fromJitsuClassic, idToClassic, idToSnakeCaseFast, removeUndefined, toClassic, toJitsuClassic, toSnakeCase, transfer, transferAsClassic, transferAsSnakeCase, transferValue, transferValueAsSnakeCase };

@@ -0,1 +1,4 @@

import { AnyEvent, FullContext } from "@jitsu/protocols/functions";
import { AnalyticsServerEvent } from "@jitsu/protocols/analytics";
export declare const TableNameParameter = "JITSU_TABLE_NAME";
export declare const DropRetryErrorName = "Drop & RetryError";

@@ -29,1 +32,3 @@ export declare const RetryErrorName = "RetryError";

}
export declare function toJitsuClassic(event: AnalyticsServerEvent, ctx: FullContext): AnyEvent;
export declare function fromJitsuClassic(event: AnyEvent): AnyEvent;
export declare function toSnakeCase(param: any): any;
export declare function toClassic(param: any): any;
export declare function removeUndefined(param: any): any;
export declare function transferAsSnakeCase(target: Record<string, any>, source: any, omit?: string[]): void;
export declare function transferAsClassic(target: Record<string, any>, source: any, omit?: string[]): void;
export declare function transferValueAsSnakeCase(target: Record<string, any>, property: string, source: any): void;
export declare function transfer(target: Record<string, any>, source: any, omit?: string[]): void;
export declare function transferValue(target: Record<string, any>, property: string, source: any): void;
export declare function idToSnakeCaseFast(id: string): string;
export declare function idToClassic(id: string): string;

16

package.json
{
"name": "@jitsu/functions-lib",
"version": "1.9.12",
"version": "1.9.13-canary.1167.20250215132227",
"main": "dist/index.cjs.js",

@@ -17,15 +17,17 @@ "module": "dist/index.es.js",

"@rollup/plugin-typescript": "^11.1.5",
"@rollup/plugin-node-resolve": "^16.0.0",
"@rollup/plugin-commonjs": "^28.0.2",
"@types/jest": "^29.1.1",
"@types/node": "^18.15.3",
"jest": "^29.1.2",
"ts-jest": "29.0.5"
"ts-jest": "29.0.5",
"tslib": "^2.6.3",
"@jitsu/sdk-js": "^3.1.5",
"@jitsu/protocols": "1.9.13-canary.1167.20250215132227"
},
"dependencies": {
"lodash": "^4.17.21",
"tslib": "^2.6.3"
},
"scripts": {
"compile": "tsc -p .",
"build": "pnpm compile && rollup -c"
"build": "pnpm compile && rollup -c",
"test": "tsc -p . && jest --verbose"
}
}
const typescript = require("@rollup/plugin-typescript");
const resolve = require("@rollup/plugin-node-resolve");
const commonjs = require("@rollup/plugin-commonjs");
module.exports = [
{
plugins: [typescript()],
plugins: [typescript(), resolve({ preferBuiltins: false }), commonjs()],
input: ["./src/index.ts"],

@@ -7,0 +9,0 @@ output: [

export * from "./lib/functions";
export * from "./lib/objects";
export * from "./lib/strings";

@@ -0,1 +1,7 @@

import { AnyEvent, FullContext, UserAgent } from "@jitsu/protocols/functions";
import { AnalyticsServerEvent } from "@jitsu/protocols/analytics";
import { removeUndefined, transferAsSnakeCase, transfer, transferAsClassic } from "./objects";
export const TableNameParameter = "JITSU_TABLE_NAME";
export const DropRetryErrorName = "Drop & RetryError";

@@ -51,1 +57,285 @@ export const RetryErrorName = "RetryError";

}
function anonymizeIp(ip: string | undefined) {
if (!ip) {
return;
}
const parts = ip.split(".");
if (parts.length === 4) {
return `${parts[0]}.${parts[1]}.${parts[2]}.0`;
}
}
export function toJitsuClassic(event: AnalyticsServerEvent, ctx: FullContext): AnyEvent {
const keepOriginalNames = !!ctx.props.keepOriginalNames;
const fileStorage = ctx.destination.type === "s3" || ctx.destination.type === "gcs";
let transferFunc = transferAsSnakeCase;
if (keepOriginalNames) {
if (fileStorage) {
transferFunc = transfer;
} else {
transferFunc = transferAsClassic;
}
}
let url: URL | undefined = undefined;
const analyticsContext = event.context || {};
const urlStr = analyticsContext.page?.url || event.properties?.url;
try {
if (urlStr) {
url = new URL(urlStr as string);
}
} catch (e) {}
const click_id = {};
transferFunc(click_id, analyticsContext.clientIds, ["ga4", "fbp", "fbc"]);
let ids: any = {};
if (Object.keys(analyticsContext.clientIds || {}).length > 0) {
ids = removeUndefined({
ga: analyticsContext.clientIds.ga4?.clientId,
fbp: analyticsContext.clientIds.fbp,
fbc: analyticsContext.clientIds.fbc,
});
}
const geo = analyticsContext.geo || {};
const ua: UserAgent = ctx?.ua || ({} as UserAgent);
const user = removeUndefined({
id: event.userId,
anonymous_id: event.anonymousId,
email: (analyticsContext.traits?.email || event.traits?.email || undefined) as string | undefined,
name: (analyticsContext.traits?.name || event.traits?.name || undefined) as string | undefined,
});
transferFunc(user, analyticsContext.traits, ["email", "name"]);
transferFunc(user, event.traits, ["email", "name"]);
const classic = {
[TableNameParameter]: event[TableNameParameter],
anon_ip: analyticsContext.ip ? anonymizeIp(analyticsContext.ip) : undefined,
api_key: event.writeKey || "",
click_id: Object.keys(click_id).length > 0 ? click_id : undefined,
doc_encoding: analyticsContext.page?.encoding ?? event.properties?.encoding,
doc_host: (analyticsContext.page?.host ?? event.properties?.host) || url?.host,
doc_path: (analyticsContext.page?.path ?? event.properties?.path) || url?.pathname,
doc_search: (analyticsContext.page?.search ?? event.properties?.search) || url?.search,
eventn_ctx_event_id: event.messageId,
event_type: event.event || event.type,
local_tz_offset: analyticsContext.page?.timezoneOffset ?? event.properties?.timezoneOffset,
page_title: analyticsContext.page?.title,
referer: analyticsContext.page?.referrer,
screen_resolution:
Object.keys(analyticsContext.screen || {}).length > 0
? Math.max(analyticsContext.screen.width || 0) + "x" + Math.max(analyticsContext.screen.height || 0)
: undefined,
source_ip: analyticsContext.ip,
src: event.properties?.src || "jitsu",
url: urlStr as string,
user: Object.keys(user).length > 0 ? user : undefined,
location:
Object.keys(geo).length > 0
? {
city: geo.city?.name,
continent: geo.continent?.name,
country: geo.country?.code,
country_name: geo.country?.name,
latitude: geo.location?.latitude,
longitude: geo.location?.longitude,
region: geo.region?.code,
zip: geo.postalCode?.code,
timezone: geo.location?.timezone,
autonomous_system_number: geo.provider?.as?.num,
autonomous_system_organization: geo.provider?.as?.name,
isp: geo.provider?.isp,
domain: geo.provider?.domain,
}
: undefined,
ids: Object.keys(ids).length > 0 ? ids : undefined,
parsed_ua:
Object.keys(ua).length > 0
? {
os_family: ua.os?.name,
os_version: ua.os?.version,
ua_family: ua.browser?.name,
ua_version: ua.browser?.version,
device_brand: ua.device?.vendor,
device_type: ua.device?.type,
device_model: ua.device?.model,
bot: ua.bot,
}
: undefined,
user_agent: analyticsContext.userAgent,
user_language: analyticsContext.locale,
utc_time: event.timestamp,
_timestamp: event.receivedAt,
utm: analyticsContext.campaign,
vp_size:
Object.keys(analyticsContext.screen || {}).length > 0
? Math.max(analyticsContext.screen.innerWidth || 0) + "x" + Math.max(analyticsContext.screen.innerHeight || 0)
: undefined,
};
if (event.type === "track") {
transferFunc(classic, event.properties);
} else {
transferFunc(classic, event.properties, ["url", "title", "referrer", "search", "host", "path", "width", "height"]);
}
return removeUndefined(classic);
}
export function fromJitsuClassic(event: AnyEvent): AnyEvent {
let type = "track";
let eventName: string | undefined = undefined;
switch ((event.event_type ?? "").toLowerCase()) {
case "pageview":
case "page_view":
case "page":
type = "page";
eventName = event.event_type;
break;
case "identify":
type = "identify";
break;
case "screen":
type = "screen";
break;
case "group":
type = "group";
break;
case "alias":
type = "alias";
break;
default:
type = "track";
eventName = event.event_type;
break;
}
const clientIds =
Object.keys(event.ids || event.click_id || {}).length > 0
? {
ga4: event.ids?.ga
? {
clientId: event.ids.ga,
}
: undefined,
fbp: event.ids?.fbp,
fbc: event.ids?.fbc,
...event.click_id,
}
: undefined;
const loc = event.location || {};
const geo =
Object.keys(loc).length > 0
? {
city: {
name: loc.city,
},
continent: {
code: loc.continent,
},
country: {
code: loc.country,
name: loc.country_name,
},
location: {
latitude: loc.latitude,
longitude: loc.longitude,
timezone: loc.timezone,
},
region: {
code: loc.region,
},
postalCode: {
code: loc.zip,
},
provider: {
as: {
num: loc.autonomous_system_number,
name: loc.autonomous_system_organization,
},
isp: loc.isp,
domain: loc.domain,
},
}
: undefined;
const traits = {};
transfer(traits, event.user, ["id", "anonymous_id"]);
const properties: any = {};
transfer(properties, event, [
TableNameParameter,
"anon_ip",
"api_key",
"click_id",
"doc_encoding",
"doc_host",
"doc_path",
"doc_search",
"eventn_ctx_event_id",
"event_type",
"local_tz_offset",
"page_title",
"referer",
"screen_resolution",
"source_ip",
"url",
"user",
"location",
"parsed_ua",
"user_agent",
"user_language",
"utc_time",
"_timestamp",
"utm",
"vp_size",
]);
if (type === "page") {
properties.url = event.url;
properties.title = event.page_title;
properties.referrer = event.referer;
properties.search = event.doc_search;
properties.host = event.doc_host;
properties.path = event.doc_path;
properties.width = parseInt(event.vp_size?.split("x")[0]);
properties.height = parseInt(event.vp_size?.split("x")[1]);
}
const screen: any = {};
const sr = event.screen_resolution?.split("x");
if (sr?.length === 2) {
screen.width = parseInt(sr[0]);
screen.height = parseInt(sr[1]);
}
const vs = event.vp_size?.split("x");
if (vs?.length === 2) {
screen.innerWidth = parseInt(vs[0]);
screen.innerHeight = parseInt(vs[1]);
}
return removeUndefined({
[TableNameParameter]: event[TableNameParameter],
messageId: event.eventn_ctx_event_id,
userId: event.user?.id,
anonymousId: event.user?.anonymous_id,
timestamp: event.utc_time,
receivedAt: event._timestamp,
writeKey: event.api_key,
type,
event: eventName,
context: {
ip: event.source_ip,
locale: event.user_language,
userAgent: event.user_agent,
page: {
url: event.url,
title: event.page_title,
referrer: event.referer,
search: event.doc_search,
host: event.doc_host,
path: event.doc_path,
encoding: event.doc_encoding,
timezoneOffset: event.local_tz_offset,
},
screen: Object.keys(screen).length > 0 ? screen : undefined,
clientIds,
campaign: event.utm,
traits,
geo,
},
properties,
traits: type === "identify" || type === "group" ? traits : undefined,
});
}

@@ -8,2 +8,3 @@ {

"esModuleInterop": true,
"moduleResolution": "node",
"noEmit": true,

@@ -21,2 +22,2 @@ "target": "esnext",

]
}
}

Sorry, the diff of this file is not supported yet