@jitsu/js 1.0.0-canary-20230211030946 → 1.0.0-canary-20230219230011
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/.turbo/turbo-build.log +65 -33
- package/.turbo/turbo-clean.log +5 -5
- package/__tests__/node/method-queue.test.ts +66 -0
- package/__tests__/playwright/integration.test.ts +6 -12
- package/dist/analytics-plugin.d.ts +17 -0
- package/dist/destination-plugins.d.ts +13 -0
- package/dist/index.d.ts +1 -1
- package/dist/jitsu.cjs.js +238 -66
- package/dist/jitsu.es.js +238 -67
- package/dist/method-queue.d.ts +17 -0
- package/dist/script-loader.d.ts +1 -0
- package/dist/web/p.js.txt +237 -66
- package/package.json +4 -4
- package/src/analytics-plugin.ts +108 -63
- package/src/destination-plugins.ts +103 -0
- package/src/index.ts +40 -6
- package/src/method-queue.ts +70 -0
- package/src/script-loader.ts +51 -0
package/dist/web/p.js.txt
CHANGED
|
@@ -68,7 +68,151 @@
|
|
|
68
68
|
return ke(_objectSpread2(_objectSpread2({}, defaultSettings), opts));
|
|
69
69
|
}
|
|
70
70
|
|
|
71
|
+
var __awaiter$1 = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
72
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
73
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
74
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
75
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
76
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
77
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
78
|
+
});
|
|
79
|
+
};
|
|
80
|
+
function satisfyFilter(filter, subject) {
|
|
81
|
+
return filter === "*" || filter.toLowerCase().trim() === (subject || "").trim().toLowerCase();
|
|
82
|
+
}
|
|
83
|
+
function applyFilters(event, creds) {
|
|
84
|
+
const { hosts = ["*"], events = ["*"] } = creds;
|
|
85
|
+
return (!!hosts.find(hostFilter => { var _a; return satisfyFilter(hostFilter, (_a = event.context) === null || _a === void 0 ? void 0 : _a.host); }) &&
|
|
86
|
+
!!events.find(eventFilter => satisfyFilter(eventFilter, event.type)));
|
|
87
|
+
}
|
|
88
|
+
const tagPlugin = {
|
|
89
|
+
id: "tag",
|
|
90
|
+
handle(config, payload) {
|
|
91
|
+
return __awaiter$1(this, void 0, void 0, function* () {
|
|
92
|
+
if (!applyFilters(payload, config)) {
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
insertTags(config.code, payload);
|
|
96
|
+
});
|
|
97
|
+
},
|
|
98
|
+
};
|
|
99
|
+
function insertTags(code, event, opts = {}) {
|
|
100
|
+
let tag;
|
|
101
|
+
try {
|
|
102
|
+
tag = JSON.parse(code);
|
|
103
|
+
}
|
|
104
|
+
catch (e) {
|
|
105
|
+
tag = { code, lang: "javascript" };
|
|
106
|
+
}
|
|
107
|
+
const debug = opts.debug || false;
|
|
108
|
+
if (isInBrowser()) {
|
|
109
|
+
if (tag.lang === "javascript") {
|
|
110
|
+
execJs(tag.code, event);
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
const codeHolder = document.createElement("span");
|
|
114
|
+
codeHolder.innerHTML = replaceMacro(tag.code, event);
|
|
115
|
+
document.body.insertAdjacentElement("beforeend", codeHolder);
|
|
116
|
+
const scripts = codeHolder.querySelectorAll("script");
|
|
117
|
+
scripts.forEach(script => {
|
|
118
|
+
const scriptClone = document.createElement("script");
|
|
119
|
+
scriptClone.type = scriptClone.type || "text/javascript";
|
|
120
|
+
if (script.hasAttribute("src")) {
|
|
121
|
+
scriptClone.src = script.src;
|
|
122
|
+
}
|
|
123
|
+
scriptClone.text = script.text;
|
|
124
|
+
if (debug) {
|
|
125
|
+
console.log(`[JITSU] Executing script${script.hasAttribute("src") ? ` ${script.src}` : ""}`, scriptClone.text);
|
|
126
|
+
}
|
|
127
|
+
document.head.appendChild(scriptClone);
|
|
128
|
+
document.head.removeChild(scriptClone);
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
133
|
+
if (debug) {
|
|
134
|
+
console.log(`[JITSU] insertTags(): cannot insert tags in non-browser environment`);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
function execJs(code, event) {
|
|
139
|
+
const varName = `jitsu_event_${randomId()}`;
|
|
140
|
+
window[varName] = event;
|
|
141
|
+
const iif = `(function(){
|
|
142
|
+
const event = ${varName};
|
|
143
|
+
${code}
|
|
144
|
+
})()`;
|
|
145
|
+
try {
|
|
146
|
+
eval(iif);
|
|
147
|
+
}
|
|
148
|
+
catch (e) {
|
|
149
|
+
console.error(`[JITSU] Error executing JS code: ${e.message}. Code: `, iif);
|
|
150
|
+
}
|
|
151
|
+
finally {
|
|
152
|
+
delete window[varName];
|
|
153
|
+
}
|
|
154
|
+
return iif;
|
|
155
|
+
}
|
|
156
|
+
function replaceMacro(code, event) {
|
|
157
|
+
return code.replace(/{{\s*event\s*}}/g, JSON.stringify(event));
|
|
158
|
+
}
|
|
159
|
+
const internalDestinationPlugins = {
|
|
160
|
+
[tagPlugin.id]: tagPlugin,
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
function findScript(src) {
|
|
164
|
+
const scripts = Array.prototype.slice.call(window.document.querySelectorAll("script"));
|
|
165
|
+
return scripts.find(s => s.src === src);
|
|
166
|
+
}
|
|
167
|
+
function loadScript(src, attributes) {
|
|
168
|
+
const found = findScript(src);
|
|
169
|
+
if (found !== undefined) {
|
|
170
|
+
const status = found === null || found === void 0 ? void 0 : found.getAttribute("status");
|
|
171
|
+
if (status === "loaded") {
|
|
172
|
+
return Promise.resolve(found);
|
|
173
|
+
}
|
|
174
|
+
if (status === "loading") {
|
|
175
|
+
return new Promise((resolve, reject) => {
|
|
176
|
+
found.addEventListener("load", () => resolve(found));
|
|
177
|
+
found.addEventListener("error", err => reject(err));
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
return new Promise((resolve, reject) => {
|
|
182
|
+
var _a;
|
|
183
|
+
const script = window.document.createElement("script");
|
|
184
|
+
script.type = "text/javascript";
|
|
185
|
+
script.src = src;
|
|
186
|
+
script.async = true;
|
|
187
|
+
script.setAttribute("status", "loading");
|
|
188
|
+
for (const [k, v] of Object.entries(attributes !== null && attributes !== void 0 ? attributes : {})) {
|
|
189
|
+
script.setAttribute(k, v);
|
|
190
|
+
}
|
|
191
|
+
script.onload = () => {
|
|
192
|
+
script.onerror = script.onload = null;
|
|
193
|
+
script.setAttribute("status", "loaded");
|
|
194
|
+
resolve(script);
|
|
195
|
+
};
|
|
196
|
+
script.onerror = () => {
|
|
197
|
+
script.onerror = script.onload = null;
|
|
198
|
+
script.setAttribute("status", "error");
|
|
199
|
+
reject(new Error(`Failed to load ${src}`));
|
|
200
|
+
};
|
|
201
|
+
const tag = window.document.getElementsByTagName("script")[0];
|
|
202
|
+
(_a = tag.parentElement) === null || _a === void 0 ? void 0 : _a.insertBefore(script, tag);
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
|
|
71
206
|
/* global analytics */
|
|
207
|
+
var __awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
208
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
209
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
210
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
211
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
212
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
213
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
214
|
+
});
|
|
215
|
+
};
|
|
72
216
|
const config = {
|
|
73
217
|
/* Your segment writeKey */
|
|
74
218
|
writeKey: null,
|
|
@@ -280,7 +424,7 @@
|
|
|
280
424
|
}, target);
|
|
281
425
|
}
|
|
282
426
|
function isInBrowser() {
|
|
283
|
-
return typeof document !== "undefined";
|
|
427
|
+
return typeof document !== "undefined" && typeof window !== "undefined";
|
|
284
428
|
}
|
|
285
429
|
function adjustPayload(payload, config, storage) {
|
|
286
430
|
var _a, _b;
|
|
@@ -318,62 +462,62 @@
|
|
|
318
462
|
delete withContext.options;
|
|
319
463
|
return withContext;
|
|
320
464
|
}
|
|
321
|
-
function
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
}
|
|
339
|
-
function replaceMacro(code, event) {
|
|
340
|
-
return code.replace(/{{\s*event\s*}}/g, JSON.stringify(event));
|
|
341
|
-
}
|
|
342
|
-
function insertTags(tags, event, opts = {}) {
|
|
343
|
-
const debug = opts.debug || false;
|
|
344
|
-
if (isInBrowser()) {
|
|
345
|
-
Object.values(tags).forEach(tag => {
|
|
346
|
-
if (tag.mode === "javascript") {
|
|
347
|
-
execJs(tag.code, event);
|
|
465
|
+
function processDestinations(destinations, method, event, debug, analyticsInstance) {
|
|
466
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
467
|
+
const promises = [];
|
|
468
|
+
for (const destination of destinations) {
|
|
469
|
+
if (destination.deviceOptions.type === "internal-plugin") {
|
|
470
|
+
const plugin = internalDestinationPlugins[destination.deviceOptions.name];
|
|
471
|
+
if (plugin) {
|
|
472
|
+
try {
|
|
473
|
+
promises.push(plugin.handle(destination.credentials, event));
|
|
474
|
+
}
|
|
475
|
+
catch (e) {
|
|
476
|
+
console.warn(`[JITSU] Error processing event with internal plugin '${destination.deviceOptions.name}': ${e === null || e === void 0 ? void 0 : e.message}`, e);
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
else {
|
|
480
|
+
console.warn(`[JITSU] Unknown internal plugin '${destination.deviceOptions.name}' for destination '${destination.id}'`);
|
|
481
|
+
}
|
|
348
482
|
}
|
|
349
|
-
else {
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
483
|
+
else if (destination.deviceOptions.type === "analytics-plugin") {
|
|
484
|
+
yield loadScript(destination.deviceOptions.packageCdn);
|
|
485
|
+
const plugin = window[destination.deviceOptions.moduleVarName];
|
|
486
|
+
if (!plugin) {
|
|
487
|
+
console.warn(`[JITSU] Broken plugin '${destination.deviceOptions.packageCdn}' for destination '${destination.id}' - it doesn't export '${destination.deviceOptions.moduleVarName}' variable`);
|
|
488
|
+
}
|
|
489
|
+
else {
|
|
490
|
+
let pluginInstance;
|
|
491
|
+
try {
|
|
492
|
+
pluginInstance = (typeof plugin === "function" ? plugin : plugin.init)(destination.credentials);
|
|
493
|
+
}
|
|
494
|
+
catch (e) {
|
|
495
|
+
console.warn(`[JITSU] Error creating plugin '${destination.deviceOptions.moduleVarName}@${destination.deviceOptions.packageCdn}' for destination '${destination.id}': ${e === null || e === void 0 ? void 0 : e.message}`, e);
|
|
496
|
+
}
|
|
497
|
+
try {
|
|
498
|
+
if (debug) {
|
|
499
|
+
console.log(`[JITSU] Plugin '${destination.deviceOptions.moduleVarName}@${destination.deviceOptions.packageCdn}' for destination '${destination.id}' initialized with config:`, pluginInstance.config);
|
|
500
|
+
}
|
|
501
|
+
pluginInstance.initialize({ config: pluginInstance.config, instance: analyticsInstance });
|
|
359
502
|
}
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
503
|
+
catch (e) {
|
|
504
|
+
console.warn(`[JITSU] Error initializing plugin '${destination.deviceOptions.moduleVarName}@${destination.deviceOptions.packageCdn}' for destination '${destination.id}': ${e === null || e === void 0 ? void 0 : e.message}. Config: ${JSON.stringify(pluginInstance.config)}`, e);
|
|
505
|
+
continue;
|
|
363
506
|
}
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
507
|
+
if (pluginInstance[method]) {
|
|
508
|
+
try {
|
|
509
|
+
pluginInstance[method]({ payload: event, config: pluginInstance.config, instance: analyticsInstance });
|
|
510
|
+
}
|
|
511
|
+
catch (e) {
|
|
512
|
+
console.warn(`[JITSU] Error processing ${method}() with plugin '${destination.deviceOptions.moduleVarName}@${destination.deviceOptions.packageCdn}' for destination '${destination.id}': ${e === null || e === void 0 ? void 0 : e.message}`, e);
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
}
|
|
367
516
|
}
|
|
368
|
-
});
|
|
369
|
-
}
|
|
370
|
-
else {
|
|
371
|
-
if (debug) {
|
|
372
|
-
console.log(`insertTags: cannot insert tags in non-browser environment`);
|
|
373
517
|
}
|
|
374
|
-
}
|
|
518
|
+
});
|
|
375
519
|
}
|
|
376
|
-
function send(method, payload, jitsuConfig, store) {
|
|
520
|
+
function send(method, payload, jitsuConfig, instance, store) {
|
|
377
521
|
if (jitsuConfig.echoEvents) {
|
|
378
522
|
console.log(`[JITSU] sending '${method}' event:`, payload);
|
|
379
523
|
return;
|
|
@@ -406,18 +550,19 @@
|
|
|
406
550
|
}
|
|
407
551
|
})
|
|
408
552
|
.then(responseText => {
|
|
553
|
+
let response;
|
|
409
554
|
try {
|
|
410
|
-
|
|
411
|
-
if (response.tags) {
|
|
412
|
-
if (jitsuConfig.debug) {
|
|
413
|
-
console.log(`[JITSU] Response Tags: `, JSON.stringify(response.tags, null, 2));
|
|
414
|
-
}
|
|
415
|
-
insertTags(response.tags, payload, { debug: jitsuConfig.debug });
|
|
416
|
-
}
|
|
555
|
+
response = JSON.parse(responseText);
|
|
417
556
|
}
|
|
418
557
|
catch (e) {
|
|
419
558
|
return Promise.reject(`Can't parse JSON: ${responseText}: ${e === null || e === void 0 ? void 0 : e.message}`);
|
|
420
559
|
}
|
|
560
|
+
if (response.destinations) {
|
|
561
|
+
if (jitsuConfig.debug) {
|
|
562
|
+
console.log(`[JITSU] Processing device destianations: `, JSON.stringify(response.destinations, null, 2));
|
|
563
|
+
}
|
|
564
|
+
return processDestinations(response.destinations, method, adjustedPayload, !!jitsuConfig.debug, instance);
|
|
565
|
+
}
|
|
421
566
|
})
|
|
422
567
|
.catch(err => {
|
|
423
568
|
if (jitsuConfig.debug) {
|
|
@@ -447,9 +592,9 @@
|
|
|
447
592
|
name: "jitsu",
|
|
448
593
|
config: Object.assign(Object.assign({}, config), pluginConfig),
|
|
449
594
|
initialize: args => {
|
|
450
|
-
const { config
|
|
595
|
+
const { config } = args;
|
|
451
596
|
if (config.debug) {
|
|
452
|
-
console.debug("Initializing Jitsu plugin with config: ", JSON.stringify(config));
|
|
597
|
+
console.debug("[JITSU] Initializing Jitsu plugin with config: ", JSON.stringify(config));
|
|
453
598
|
}
|
|
454
599
|
if (!config.host && !config.echoEvents) {
|
|
455
600
|
throw new Error("Please specify host variable in jitsu plugin initialization, or set echoEvents to true");
|
|
@@ -457,17 +602,17 @@
|
|
|
457
602
|
},
|
|
458
603
|
page: args => {
|
|
459
604
|
const { payload, config, instance } = args;
|
|
460
|
-
return send("page", payload, config, cachingStorageWrapper(instance.storage));
|
|
605
|
+
return send("page", payload, config, instance, cachingStorageWrapper(instance.storage));
|
|
461
606
|
},
|
|
462
607
|
track: args => {
|
|
463
608
|
const { payload, config, instance } = args;
|
|
464
|
-
return send("track", payload, config, cachingStorageWrapper(instance.storage));
|
|
609
|
+
return send("track", payload, config, instance, cachingStorageWrapper(instance.storage));
|
|
465
610
|
},
|
|
466
611
|
identify: args => {
|
|
467
612
|
const { payload, config, instance } = args;
|
|
468
613
|
// Store traits in cache to be able to use them in page and track events that run asynchronously with current identify.
|
|
469
614
|
storageCache["__user_traits"] = payload.traits;
|
|
470
|
-
return send("identify", payload, config, cachingStorageWrapper(instance.storage));
|
|
615
|
+
return send("identify", payload, config, instance, cachingStorageWrapper(instance.storage));
|
|
471
616
|
},
|
|
472
617
|
reset: args => {
|
|
473
618
|
//clear storage cache
|
|
@@ -520,13 +665,12 @@
|
|
|
520
665
|
}
|
|
521
666
|
return value;
|
|
522
667
|
}
|
|
523
|
-
function
|
|
524
|
-
const rt = opts.runtime || (typeof window === "undefined" ? emptyRuntime(opts) : windowRuntime(opts));
|
|
668
|
+
function createUnderlyingAnalyticsInstance(opts, rt, plugins = []) {
|
|
525
669
|
const analytics = analyticsLib({
|
|
526
670
|
app: "test",
|
|
527
671
|
debug: !!opts.debug,
|
|
528
672
|
storage: rt.store(),
|
|
529
|
-
plugins: [jitsuAnalyticsPlugin(opts)],
|
|
673
|
+
plugins: [jitsuAnalyticsPlugin(opts), ...plugins],
|
|
530
674
|
});
|
|
531
675
|
const originalPage = analytics.page;
|
|
532
676
|
analytics.page = (...args) => {
|
|
@@ -539,6 +683,33 @@
|
|
|
539
683
|
};
|
|
540
684
|
return analytics;
|
|
541
685
|
}
|
|
686
|
+
function jitsuAnalytics(opts) {
|
|
687
|
+
const inBrowser = isInBrowser();
|
|
688
|
+
const rt = opts.runtime || (inBrowser ? windowRuntime(opts) : emptyRuntime(opts));
|
|
689
|
+
return createUnderlyingAnalyticsInstance(opts, rt);
|
|
690
|
+
// if (inBrowser) {
|
|
691
|
+
// const fetch = opts.fetch || globalThis.fetch;
|
|
692
|
+
// if (!fetch) {
|
|
693
|
+
// throw new Error(
|
|
694
|
+
// "Please specify fetch function in jitsu plugin initialization, fetch isn't available in global scope"
|
|
695
|
+
// );
|
|
696
|
+
// }
|
|
697
|
+
// const url = `${opts.host}/api/s/cfg`;
|
|
698
|
+
// const authHeader = {};
|
|
699
|
+
// const debugHeader = opts.debug ? { "X-Enable-Debug": "true" } : {};
|
|
700
|
+
// fetch(url)
|
|
701
|
+
// .then(res => res.json())
|
|
702
|
+
// .then(res => {
|
|
703
|
+
// result.loaded(createUnderlyingAnalyticsInstance(opts, rt, []));
|
|
704
|
+
// })
|
|
705
|
+
// .catch(e => {
|
|
706
|
+
// console.warn(`[JITSU] error getting device-destinations from ${url}`, e);
|
|
707
|
+
// result.loaded(createUnderlyingAnalyticsInstance(opts, rt));
|
|
708
|
+
// });
|
|
709
|
+
// } else {
|
|
710
|
+
// result.loaded(createUnderlyingAnalyticsInstance(opts, rt));
|
|
711
|
+
// }
|
|
712
|
+
}
|
|
542
713
|
|
|
543
714
|
function snakeToCamel(s) {
|
|
544
715
|
return s.replace(/([-_][a-z])/gi, $1 => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jitsu/js",
|
|
3
|
-
"version": "1.0.0-canary-
|
|
3
|
+
"version": "1.0.0-canary-20230219230011",
|
|
4
4
|
"description": "",
|
|
5
5
|
"author": "Jitsu Dev Team <dev@jitsu.com>",
|
|
6
6
|
"main": "dist/jitsu.cjs.js",
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
"license": "MIT",
|
|
13
13
|
"private": false,
|
|
14
14
|
"devDependencies": {
|
|
15
|
-
"@playwright/test": "^1.
|
|
15
|
+
"@playwright/test": "^1.30.0",
|
|
16
16
|
"@rollup/plugin-commonjs": "^23.0.2",
|
|
17
17
|
"@rollup/plugin-json": "^5.0.1",
|
|
18
18
|
"@rollup/plugin-multi-entry": "^6.0.0",
|
|
@@ -35,8 +35,8 @@
|
|
|
35
35
|
"ts-jest": "^29.0.3"
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"
|
|
39
|
-
"
|
|
38
|
+
"analytics": "^0.8.1",
|
|
39
|
+
"@jitsu/protocols": "0.0.0"
|
|
40
40
|
},
|
|
41
41
|
"scripts": {
|
|
42
42
|
"clean": "rm -rf ./dist",
|
package/src/analytics-plugin.ts
CHANGED
|
@@ -3,7 +3,9 @@
|
|
|
3
3
|
import { JitsuOptions, PersistentStorage, RuntimeFacade } from "./jitsu";
|
|
4
4
|
import { AnalyticsClientEvent } from "@jitsu/protocols/analytics";
|
|
5
5
|
import parse from "./index";
|
|
6
|
-
import { AnalyticsPlugin } from "analytics";
|
|
6
|
+
import { AnalyticsInstance, AnalyticsPlugin } from "analytics";
|
|
7
|
+
import { internalDestinationPlugins } from "./destination-plugins";
|
|
8
|
+
import { loadScript } from "./script-loader";
|
|
7
9
|
|
|
8
10
|
const config: JitsuOptions = {
|
|
9
11
|
/* Your segment writeKey */
|
|
@@ -238,8 +240,8 @@ function deepMerge(target: any, source: any) {
|
|
|
238
240
|
}, target);
|
|
239
241
|
}
|
|
240
242
|
|
|
241
|
-
function isInBrowser() {
|
|
242
|
-
return typeof document !== "undefined";
|
|
243
|
+
export function isInBrowser() {
|
|
244
|
+
return typeof document !== "undefined" && typeof window !== "undefined";
|
|
243
245
|
}
|
|
244
246
|
|
|
245
247
|
function adjustPayload(payload: any, config: JitsuOptions, storage: PersistentStorage): AnalyticsClientEvent {
|
|
@@ -285,65 +287,107 @@ function adjustPayload(payload: any, config: JitsuOptions, storage: PersistentSt
|
|
|
285
287
|
return withContext;
|
|
286
288
|
}
|
|
287
289
|
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
} finally {
|
|
300
|
-
delete window[varName];
|
|
301
|
-
}
|
|
302
|
-
return iif;
|
|
303
|
-
}
|
|
290
|
+
export type DestinationDescriptor = {
|
|
291
|
+
id: string;
|
|
292
|
+
destinationType: string;
|
|
293
|
+
credentials: any;
|
|
294
|
+
deviceOptions: DeviceOptions;
|
|
295
|
+
};
|
|
296
|
+
export type AnalyticsPluginDescriptor = {
|
|
297
|
+
type: "analytics-plugin";
|
|
298
|
+
packageCdn: string;
|
|
299
|
+
moduleVarName: string;
|
|
300
|
+
};
|
|
304
301
|
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
302
|
+
export type InternalPluginDescriptor = {
|
|
303
|
+
type: "internal-plugin";
|
|
304
|
+
name: string;
|
|
305
|
+
};
|
|
306
|
+
|
|
307
|
+
export type DeviceOptions = AnalyticsPluginDescriptor | InternalPluginDescriptor;
|
|
308
308
|
|
|
309
|
-
function
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
309
|
+
async function processDestinations(
|
|
310
|
+
destinations: DestinationDescriptor[],
|
|
311
|
+
method: string,
|
|
312
|
+
event: AnalyticsClientEvent,
|
|
313
|
+
debug: boolean,
|
|
314
|
+
analyticsInstance: AnalyticsInstance
|
|
313
315
|
) {
|
|
314
|
-
const
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
316
|
+
const promises: Promise<any>[] = [];
|
|
317
|
+
for (const destination of destinations) {
|
|
318
|
+
if (destination.deviceOptions.type === "internal-plugin") {
|
|
319
|
+
const plugin = internalDestinationPlugins[destination.deviceOptions.name];
|
|
320
|
+
if (plugin) {
|
|
321
|
+
try {
|
|
322
|
+
promises.push(plugin.handle(destination.credentials, event));
|
|
323
|
+
} catch (e) {
|
|
324
|
+
console.warn(
|
|
325
|
+
`[JITSU] Error processing event with internal plugin '${destination.deviceOptions.name}': ${e?.message}`,
|
|
326
|
+
e
|
|
327
|
+
);
|
|
328
|
+
}
|
|
319
329
|
} else {
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
}
|
|
330
|
-
|
|
330
|
+
console.warn(
|
|
331
|
+
`[JITSU] Unknown internal plugin '${destination.deviceOptions.name}' for destination '${destination.id}'`
|
|
332
|
+
);
|
|
333
|
+
}
|
|
334
|
+
} else if (destination.deviceOptions.type === "analytics-plugin") {
|
|
335
|
+
await loadScript(destination.deviceOptions.packageCdn);
|
|
336
|
+
const plugin = window[destination.deviceOptions.moduleVarName];
|
|
337
|
+
if (!plugin) {
|
|
338
|
+
console.warn(
|
|
339
|
+
`[JITSU] Broken plugin '${destination.deviceOptions.packageCdn}' for destination '${destination.id}' - it doesn't export '${destination.deviceOptions.moduleVarName}' variable`
|
|
340
|
+
);
|
|
341
|
+
} else {
|
|
342
|
+
let pluginInstance: any;
|
|
343
|
+
try {
|
|
344
|
+
pluginInstance = (typeof plugin === "function" ? plugin : plugin.init)(destination.credentials);
|
|
345
|
+
} catch (e) {
|
|
346
|
+
console.warn(
|
|
347
|
+
`[JITSU] Error creating plugin '${destination.deviceOptions.moduleVarName}@${destination.deviceOptions.packageCdn}' for destination '${destination.id}': ${e?.message}`,
|
|
348
|
+
e
|
|
349
|
+
);
|
|
350
|
+
}
|
|
351
|
+
try {
|
|
331
352
|
if (debug) {
|
|
332
|
-
console.log(
|
|
353
|
+
console.log(
|
|
354
|
+
`[JITSU] Plugin '${destination.deviceOptions.moduleVarName}@${destination.deviceOptions.packageCdn}' for destination '${destination.id}' initialized with config:`,
|
|
355
|
+
pluginInstance.config
|
|
356
|
+
);
|
|
333
357
|
}
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
358
|
+
pluginInstance.initialize({ config: pluginInstance.config, instance: analyticsInstance });
|
|
359
|
+
} catch (e) {
|
|
360
|
+
console.warn(
|
|
361
|
+
`[JITSU] Error initializing plugin '${destination.deviceOptions.moduleVarName}@${
|
|
362
|
+
destination.deviceOptions.packageCdn
|
|
363
|
+
}' for destination '${destination.id}': ${e?.message}. Config: ${JSON.stringify(pluginInstance.config)}`,
|
|
364
|
+
e
|
|
365
|
+
);
|
|
366
|
+
continue;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
if (pluginInstance[method]) {
|
|
370
|
+
try {
|
|
371
|
+
pluginInstance[method]({ payload: event, config: pluginInstance.config, instance: analyticsInstance });
|
|
372
|
+
} catch (e) {
|
|
373
|
+
console.warn(
|
|
374
|
+
`[JITSU] Error processing ${method}() with plugin '${destination.deviceOptions.moduleVarName}@${destination.deviceOptions.packageCdn}' for destination '${destination.id}': ${e?.message}`,
|
|
375
|
+
e
|
|
376
|
+
);
|
|
377
|
+
}
|
|
378
|
+
}
|
|
337
379
|
}
|
|
338
|
-
});
|
|
339
|
-
} else {
|
|
340
|
-
if (debug) {
|
|
341
|
-
console.log(`insertTags: cannot insert tags in non-browser environment`);
|
|
342
380
|
}
|
|
343
381
|
}
|
|
344
382
|
}
|
|
345
383
|
|
|
346
|
-
function send(
|
|
384
|
+
function send(
|
|
385
|
+
method,
|
|
386
|
+
payload,
|
|
387
|
+
jitsuConfig: Required<JitsuOptions>,
|
|
388
|
+
instance: AnalyticsInstance,
|
|
389
|
+
store: PersistentStorage
|
|
390
|
+
): Promise<void> {
|
|
347
391
|
if (jitsuConfig.echoEvents) {
|
|
348
392
|
console.log(`[JITSU] sending '${method}' event:`, payload);
|
|
349
393
|
return;
|
|
@@ -387,17 +431,18 @@ function send(method, payload, jitsuConfig: Required<JitsuOptions>, store: Persi
|
|
|
387
431
|
}
|
|
388
432
|
})
|
|
389
433
|
.then(responseText => {
|
|
434
|
+
let response: any;
|
|
390
435
|
try {
|
|
391
|
-
|
|
392
|
-
if (response.tags) {
|
|
393
|
-
if (jitsuConfig.debug) {
|
|
394
|
-
console.log(`[JITSU] Response Tags: `, JSON.stringify(response.tags, null, 2));
|
|
395
|
-
}
|
|
396
|
-
insertTags(response.tags, payload, { debug: jitsuConfig.debug });
|
|
397
|
-
}
|
|
436
|
+
response = JSON.parse(responseText);
|
|
398
437
|
} catch (e) {
|
|
399
438
|
return Promise.reject(`Can't parse JSON: ${responseText}: ${e?.message}`);
|
|
400
439
|
}
|
|
440
|
+
if (response.destinations) {
|
|
441
|
+
if (jitsuConfig.debug) {
|
|
442
|
+
console.log(`[JITSU] Processing device destianations: `, JSON.stringify(response.destinations, null, 2));
|
|
443
|
+
}
|
|
444
|
+
return processDestinations(response.destinations, method, adjustedPayload, !!jitsuConfig.debug, instance);
|
|
445
|
+
}
|
|
401
446
|
})
|
|
402
447
|
.catch(err => {
|
|
403
448
|
if (jitsuConfig.debug) {
|
|
@@ -431,9 +476,9 @@ const jitsuAnalyticsPlugin = (pluginConfig: JitsuOptions = {}): AnalyticsPlugin
|
|
|
431
476
|
...pluginConfig,
|
|
432
477
|
},
|
|
433
478
|
initialize: args => {
|
|
434
|
-
const { config
|
|
479
|
+
const { config } = args;
|
|
435
480
|
if (config.debug) {
|
|
436
|
-
console.debug("Initializing Jitsu plugin with config: ", JSON.stringify(config));
|
|
481
|
+
console.debug("[JITSU] Initializing Jitsu plugin with config: ", JSON.stringify(config));
|
|
437
482
|
}
|
|
438
483
|
if (!config.host && !config.echoEvents) {
|
|
439
484
|
throw new Error("Please specify host variable in jitsu plugin initialization, or set echoEvents to true");
|
|
@@ -441,17 +486,17 @@ const jitsuAnalyticsPlugin = (pluginConfig: JitsuOptions = {}): AnalyticsPlugin
|
|
|
441
486
|
},
|
|
442
487
|
page: args => {
|
|
443
488
|
const { payload, config, instance } = args;
|
|
444
|
-
return send("page", payload, config, cachingStorageWrapper(instance.storage));
|
|
489
|
+
return send("page", payload, config, instance, cachingStorageWrapper(instance.storage));
|
|
445
490
|
},
|
|
446
491
|
track: args => {
|
|
447
492
|
const { payload, config, instance } = args;
|
|
448
|
-
return send("track", payload, config, cachingStorageWrapper(instance.storage));
|
|
493
|
+
return send("track", payload, config, instance, cachingStorageWrapper(instance.storage));
|
|
449
494
|
},
|
|
450
495
|
identify: args => {
|
|
451
496
|
const { payload, config, instance } = args;
|
|
452
497
|
// Store traits in cache to be able to use them in page and track events that run asynchronously with current identify.
|
|
453
498
|
storageCache["__user_traits"] = payload.traits;
|
|
454
|
-
return send("identify", payload, config, cachingStorageWrapper(instance.storage));
|
|
499
|
+
return send("identify", payload, config, instance, cachingStorageWrapper(instance.storage));
|
|
455
500
|
},
|
|
456
501
|
reset: args => {
|
|
457
502
|
//clear storage cache
|