@jitsu/js 0.0.1-alpha.127 → 0.0.1-alpha.174

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,15 +1,33 @@
1
- @jitsu/js:build: cache hit, replaying output 0263d5983323ab5a
2
- @jitsu/js:build: 
3
- @jitsu/js:build: > @jitsu/js@0.0.0 build /Users/ildarnurislamov/Projects/onetag/libs/jitsu-js
4
- @jitsu/js:build: > tsc -p . && rollup -c && cp compiled/src/*.d.ts dist
5
- @jitsu/js:build: 
6
- @jitsu/js:build: 
7
- @jitsu/js:build: ./compiled/src/browser.js → dist/web/p.js.txt...
8
- @jitsu/js:build: (!) Circular dependency
9
- @jitsu/js:build: compiled/src/index.js -> compiled/src/analytics-plugin.js -> compiled/src/index.js
10
- @jitsu/js:build: created dist/web/p.js.txt in 613ms
11
- @jitsu/js:build: 
12
- @jitsu/js:build: ./compiled/src/index.js, ./compiled/src/jitsu.js, ./compiled/src/analytics-plugin.js → dist/jitsu.es.js, dist/jitsu.cjs.js...
13
- @jitsu/js:build: (!) Circular dependency
14
- @jitsu/js:build: compiled/src/index.js -> compiled/src/analytics-plugin.js -> compiled/src/index.js
15
- @jitsu/js:build: created dist/jitsu.es.js, dist/jitsu.cjs.js in 532ms
1
+ @jitsu/js:build: cache hit, replaying output fd2896b82ec69198
2
+ @jitsu/js:build: 
3
+ @jitsu/js:build: > @jitsu/js@0.0.0 build /Users/ildarnurislamov/Projects/onetag/libs/jitsu-js
4
+ @jitsu/js:build: > tsc -p . && rollup -c && cp compiled/src/*.d.ts dist
5
+ @jitsu/js:build: 
6
+ @jitsu/js:build: 
7
+ @jitsu/js:build: ./compiled/src/browser.js → dist/web/p.js.txt...
8
+ @jitsu/js:build: (!) Circular dependency
9
+ @jitsu/js:build: compiled/src/index.js -> compiled/src/analytics-plugin.js -> compiled/src/index.js
10
+ @jitsu/js:build: (!) Use of eval is strongly discouraged
11
+ @jitsu/js:build: https://rollupjs.org/guide/en/#avoiding-eval
12
+ @jitsu/js:build: compiled/src/analytics-plugin.js
13
+ @jitsu/js:build: 258: })()`;
14
+ @jitsu/js:build: 259: try {
15
+ @jitsu/js:build: 260: eval(iif);
16
+ @jitsu/js:build:  ^
17
+ @jitsu/js:build: 261: }
18
+ @jitsu/js:build: 262: catch (e) {
19
+ @jitsu/js:build: created dist/web/p.js.txt in 184ms
20
+ @jitsu/js:build: 
21
+ @jitsu/js:build: ./compiled/src/index.js, ./compiled/src/jitsu.js, ./compiled/src/analytics-plugin.js → dist/jitsu.es.js, dist/jitsu.cjs.js...
22
+ @jitsu/js:build: (!) Circular dependency
23
+ @jitsu/js:build: compiled/src/index.js -> compiled/src/analytics-plugin.js -> compiled/src/index.js
24
+ @jitsu/js:build: (!) Use of eval is strongly discouraged
25
+ @jitsu/js:build: https://rollupjs.org/guide/en/#avoiding-eval
26
+ @jitsu/js:build: compiled/src/analytics-plugin.js
27
+ @jitsu/js:build: 258: })()`;
28
+ @jitsu/js:build: 259: try {
29
+ @jitsu/js:build: 260: eval(iif);
30
+ @jitsu/js:build:  ^
31
+ @jitsu/js:build: 261: }
32
+ @jitsu/js:build: 262: catch (e) {
33
+ @jitsu/js:build: created dist/jitsu.es.js, dist/jitsu.cjs.js in 126ms
@@ -1,5 +1,5 @@
1
- @jitsu/js:clean: cache hit, replaying output e0930b6eea397172
2
- @jitsu/js:clean: 
3
- @jitsu/js:clean: > @jitsu/js@0.0.0 clean /Users/ildarnurislamov/Projects/onetag/libs/jitsu-js
4
- @jitsu/js:clean: > rm -rf ./dist
5
- @jitsu/js:clean: 
1
+ @jitsu/js:clean: cache hit, replaying output cc849d2fe2e435e1
2
+ @jitsu/js:clean: 
3
+ @jitsu/js:clean: > @jitsu/js@0.0.0 clean /Users/ildarnurislamov/Projects/onetag/libs/jitsu-js
4
+ @jitsu/js:clean: > rm -rf ./dist
5
+ @jitsu/js:clean: 
@@ -90,9 +90,15 @@ function generateX509Certificate(altNames: { type: number; value: string }[]) {
90
90
 
91
91
  function shutdownFunction(server): Promise<void> {
92
92
  return new Promise<void>(resolve => {
93
- server.close(() => {
94
- resolve();
95
- });
93
+ let resolved = false;
94
+ const resolveIfNeeded = () => {
95
+ if (!resolved) {
96
+ resolved = true;
97
+ resolve();
98
+ }
99
+ };
100
+ setTimeout(resolveIfNeeded, 5000);
101
+ server.close(resolveIfNeeded);
96
102
  });
97
103
  }
98
104
 
package/dist/jitsu.cjs.js CHANGED
@@ -75,6 +75,7 @@ const config = {
75
75
  host: null,
76
76
  debug: false,
77
77
  fetch: null,
78
+ echoEvents: false,
78
79
  };
79
80
  const parseQuery = (qs) => {
80
81
  if (!qs) {
@@ -311,22 +312,81 @@ function adjustPayload(payload, config, storage) {
311
312
  },
312
313
  campaign: parseUtms(query),
313
314
  };
314
- const withContext = Object.assign(Object.assign({}, payload), { timestamp: new Date().toISOString(), sentAt: new Date().toISOString(), messageId: randomId(properties.path || (parsedUrl && parsedUrl.pathname)), context: deepMerge(context, customContext) });
315
+ const withContext = Object.assign(Object.assign({}, payload), { timestamp: new Date().toISOString(), sentAt: new Date().toISOString(), messageId: randomId(properties.path || (parsedUrl && parsedUrl.pathname)), writeKey: config.writeKey, context: deepMerge(context, customContext) });
315
316
  delete withContext.meta;
316
317
  delete withContext.options;
317
318
  return withContext;
318
319
  }
320
+ function execJs(code, event) {
321
+ const varName = `jitsu_event_${randomId()}`;
322
+ window[varName] = event;
323
+ const iif = `(function(){
324
+ ${code}
325
+ onEvent(${varName});
326
+ })()`;
327
+ try {
328
+ eval(iif);
329
+ }
330
+ catch (e) {
331
+ console.error(`[JITSU] Error executing JS code: ${e.message}`);
332
+ }
333
+ finally {
334
+ delete window[varName];
335
+ }
336
+ return iif;
337
+ }
338
+ function replaceMacro(code, event) {
339
+ return code.replace(/{{\s*event\s*}}/g, JSON.stringify(event));
340
+ }
341
+ function insertTags(tags, event, opts = {}) {
342
+ const debug = opts.debug || false;
343
+ if (isInBrowser()) {
344
+ Object.values(tags).forEach(tag => {
345
+ if (tag.mode === "javascript") {
346
+ execJs(tag.code, event);
347
+ }
348
+ else {
349
+ const codeHolder = document.createElement("span");
350
+ codeHolder.innerHTML = replaceMacro(tag.code, event);
351
+ document.body.insertAdjacentElement("beforeend", codeHolder);
352
+ const scripts = codeHolder.querySelectorAll("script");
353
+ scripts.forEach(script => {
354
+ const scriptClone = document.createElement("script");
355
+ scriptClone.type = scriptClone.type || "text/javascript";
356
+ if (script.hasAttribute("src")) {
357
+ scriptClone.src = script.src;
358
+ }
359
+ scriptClone.text = script.text;
360
+ if (debug) {
361
+ console.log(`Executing script${script.hasAttribute("src") ? ` ${script.src}` : ""}`, scriptClone.text);
362
+ }
363
+ document.head.appendChild(scriptClone);
364
+ document.head.removeChild(scriptClone);
365
+ });
366
+ }
367
+ });
368
+ }
369
+ else {
370
+ if (debug) {
371
+ console.log(`insertTags: cannot insert tags in non-browser environment`);
372
+ }
373
+ }
374
+ }
319
375
  function send(method, payload, jitsuConfig, store) {
376
+ if (jitsuConfig.echoEvents) {
377
+ console.log(`[JITSU] sending '${method}' event:`, payload);
378
+ return;
379
+ }
320
380
  const url = `${jitsuConfig.host}/api/s/${method}`;
321
381
  const fetch = jitsuConfig.fetch || globalThis.fetch;
322
382
  if (!fetch) {
323
383
  throw new Error("Please specify fetch function in jitsu plugin initialization, fetch isn't available in global scope");
324
384
  }
325
- const authHeader = jitsuConfig.writeKey ? { Authorization: `Bearer ${jitsuConfig.writeKey}` } : {};
385
+ const authHeader = {};
326
386
  const debugHeader = jitsuConfig.debug ? { "X-Enable-Debug": "true" } : {};
327
- if (jitsuConfig.debug) {
328
- console.log(`Sending jitsu event to ${url}: `, JSON.stringify(payload, null, 2));
329
- }
387
+ // if (jitsuConfig.debug) {
388
+ // console.log(`[JITSU] Sending event to ${url}: `, JSON.stringify(payload, null, 2));
389
+ // }
330
390
  const adjustedPayload = adjustPayload(payload, jitsuConfig, store);
331
391
  return fetch(url, {
332
392
  method: "POST",
@@ -335,7 +395,27 @@ function send(method, payload, jitsuConfig, store) {
335
395
  })
336
396
  .then(res => {
337
397
  if (jitsuConfig.debug) {
338
- console.debug(`Jitsu ${url} replied ${res.status}. Original payload: `, JSON.stringify(adjustedPayload, null, 2));
398
+ console.log(`[JITSU] ${url} replied ${res.status}. Original payload: `, JSON.stringify(adjustedPayload, null, 2));
399
+ }
400
+ if (res.ok) {
401
+ return res.text();
402
+ }
403
+ else {
404
+ return Promise.reject(res.text());
405
+ }
406
+ })
407
+ .then(responseText => {
408
+ try {
409
+ const response = JSON.parse(responseText);
410
+ if (response.tags) {
411
+ if (jitsuConfig.debug) {
412
+ console.log(`[JITSU] Response Tags: `, JSON.stringify(response.tags, null, 2));
413
+ }
414
+ insertTags(response.tags, payload, { debug: jitsuConfig.debug });
415
+ }
416
+ }
417
+ catch (e) {
418
+ return Promise.reject(`Can't parse JSON: ${responseText}: ${e === null || e === void 0 ? void 0 : e.message}`);
339
419
  }
340
420
  })
341
421
  .catch(err => {
@@ -370,8 +450,8 @@ const jitsuAnalyticsPlugin = (pluginConfig = {}) => {
370
450
  if (config.debug) {
371
451
  console.debug("Initializing Jitsu plugin with config: ", JSON.stringify(config));
372
452
  }
373
- if (!config.host) {
374
- throw new Error("Please specify host variable in jitsu plugin initialization");
453
+ if (!config.host && !config.echoEvents) {
454
+ throw new Error("Please specify host variable in jitsu plugin initialization, or set echoEvents to true");
375
455
  }
376
456
  },
377
457
  page: args => {
package/dist/jitsu.d.ts CHANGED
@@ -10,10 +10,33 @@ type JitsuOptions = {
10
10
  * API Host. Default value: same host as script origin
11
11
  */
12
12
  host?: string;
13
+ /**
14
+ * To enable debug logging
15
+ */
13
16
  debug?: boolean;
17
+ /**
18
+ * Explicitely specify cookie domain. If not set, cookie domain will be set to top level
19
+ * of the current domain. Example: if JS lives on "app.example.com", cookie domain will be
20
+ * set to ".example.com". If it lives on "example.com", cookie domain will be set to ".example.com" too
21
+ */
14
22
  cookieDomain?: string;
23
+ /**
24
+ * Provide fetch implementation. It is required if you want to use Jitsu in NodeJS
25
+ */
15
26
  fetch?: typeof fetch;
27
+ /**
28
+ * Which runtime to use. Runtime is used for obtaining context of the event: cookes,
29
+ * url, etc. At the moment, Jitsu supports browser runtime and NodeJS runtime, but you
30
+ * can provide your own implementation.
31
+ *
32
+ * If it's not set, the runtime will be detected automatically by presense of `window` object
33
+ */
16
34
  runtime?: RuntimeFacade;
35
+ /**
36
+ * If set to true, jitsu will output events in console. In this case you don't need to set
37
+ * writeKey / host. It's useful for debugging development environment
38
+ */
39
+ echoEvents?: boolean;
17
40
  };
18
41
  type PersistentStorage = {
19
42
  getItem: (key: string, options?: any) => any;
package/dist/jitsu.es.js CHANGED
@@ -73,6 +73,7 @@ const config = {
73
73
  host: null,
74
74
  debug: false,
75
75
  fetch: null,
76
+ echoEvents: false,
76
77
  };
77
78
  const parseQuery = (qs) => {
78
79
  if (!qs) {
@@ -309,22 +310,81 @@ function adjustPayload(payload, config, storage) {
309
310
  },
310
311
  campaign: parseUtms(query),
311
312
  };
312
- const withContext = Object.assign(Object.assign({}, payload), { timestamp: new Date().toISOString(), sentAt: new Date().toISOString(), messageId: randomId(properties.path || (parsedUrl && parsedUrl.pathname)), context: deepMerge(context, customContext) });
313
+ const withContext = Object.assign(Object.assign({}, payload), { timestamp: new Date().toISOString(), sentAt: new Date().toISOString(), messageId: randomId(properties.path || (parsedUrl && parsedUrl.pathname)), writeKey: config.writeKey, context: deepMerge(context, customContext) });
313
314
  delete withContext.meta;
314
315
  delete withContext.options;
315
316
  return withContext;
316
317
  }
318
+ function execJs(code, event) {
319
+ const varName = `jitsu_event_${randomId()}`;
320
+ window[varName] = event;
321
+ const iif = `(function(){
322
+ ${code}
323
+ onEvent(${varName});
324
+ })()`;
325
+ try {
326
+ eval(iif);
327
+ }
328
+ catch (e) {
329
+ console.error(`[JITSU] Error executing JS code: ${e.message}`);
330
+ }
331
+ finally {
332
+ delete window[varName];
333
+ }
334
+ return iif;
335
+ }
336
+ function replaceMacro(code, event) {
337
+ return code.replace(/{{\s*event\s*}}/g, JSON.stringify(event));
338
+ }
339
+ function insertTags(tags, event, opts = {}) {
340
+ const debug = opts.debug || false;
341
+ if (isInBrowser()) {
342
+ Object.values(tags).forEach(tag => {
343
+ if (tag.mode === "javascript") {
344
+ execJs(tag.code, event);
345
+ }
346
+ else {
347
+ const codeHolder = document.createElement("span");
348
+ codeHolder.innerHTML = replaceMacro(tag.code, event);
349
+ document.body.insertAdjacentElement("beforeend", codeHolder);
350
+ const scripts = codeHolder.querySelectorAll("script");
351
+ scripts.forEach(script => {
352
+ const scriptClone = document.createElement("script");
353
+ scriptClone.type = scriptClone.type || "text/javascript";
354
+ if (script.hasAttribute("src")) {
355
+ scriptClone.src = script.src;
356
+ }
357
+ scriptClone.text = script.text;
358
+ if (debug) {
359
+ console.log(`Executing script${script.hasAttribute("src") ? ` ${script.src}` : ""}`, scriptClone.text);
360
+ }
361
+ document.head.appendChild(scriptClone);
362
+ document.head.removeChild(scriptClone);
363
+ });
364
+ }
365
+ });
366
+ }
367
+ else {
368
+ if (debug) {
369
+ console.log(`insertTags: cannot insert tags in non-browser environment`);
370
+ }
371
+ }
372
+ }
317
373
  function send(method, payload, jitsuConfig, store) {
374
+ if (jitsuConfig.echoEvents) {
375
+ console.log(`[JITSU] sending '${method}' event:`, payload);
376
+ return;
377
+ }
318
378
  const url = `${jitsuConfig.host}/api/s/${method}`;
319
379
  const fetch = jitsuConfig.fetch || globalThis.fetch;
320
380
  if (!fetch) {
321
381
  throw new Error("Please specify fetch function in jitsu plugin initialization, fetch isn't available in global scope");
322
382
  }
323
- const authHeader = jitsuConfig.writeKey ? { Authorization: `Bearer ${jitsuConfig.writeKey}` } : {};
383
+ const authHeader = {};
324
384
  const debugHeader = jitsuConfig.debug ? { "X-Enable-Debug": "true" } : {};
325
- if (jitsuConfig.debug) {
326
- console.log(`Sending jitsu event to ${url}: `, JSON.stringify(payload, null, 2));
327
- }
385
+ // if (jitsuConfig.debug) {
386
+ // console.log(`[JITSU] Sending event to ${url}: `, JSON.stringify(payload, null, 2));
387
+ // }
328
388
  const adjustedPayload = adjustPayload(payload, jitsuConfig, store);
329
389
  return fetch(url, {
330
390
  method: "POST",
@@ -333,7 +393,27 @@ function send(method, payload, jitsuConfig, store) {
333
393
  })
334
394
  .then(res => {
335
395
  if (jitsuConfig.debug) {
336
- console.debug(`Jitsu ${url} replied ${res.status}. Original payload: `, JSON.stringify(adjustedPayload, null, 2));
396
+ console.log(`[JITSU] ${url} replied ${res.status}. Original payload: `, JSON.stringify(adjustedPayload, null, 2));
397
+ }
398
+ if (res.ok) {
399
+ return res.text();
400
+ }
401
+ else {
402
+ return Promise.reject(res.text());
403
+ }
404
+ })
405
+ .then(responseText => {
406
+ try {
407
+ const response = JSON.parse(responseText);
408
+ if (response.tags) {
409
+ if (jitsuConfig.debug) {
410
+ console.log(`[JITSU] Response Tags: `, JSON.stringify(response.tags, null, 2));
411
+ }
412
+ insertTags(response.tags, payload, { debug: jitsuConfig.debug });
413
+ }
414
+ }
415
+ catch (e) {
416
+ return Promise.reject(`Can't parse JSON: ${responseText}: ${e === null || e === void 0 ? void 0 : e.message}`);
337
417
  }
338
418
  })
339
419
  .catch(err => {
@@ -368,8 +448,8 @@ const jitsuAnalyticsPlugin = (pluginConfig = {}) => {
368
448
  if (config.debug) {
369
449
  console.debug("Initializing Jitsu plugin with config: ", JSON.stringify(config));
370
450
  }
371
- if (!config.host) {
372
- throw new Error("Please specify host variable in jitsu plugin initialization");
451
+ if (!config.host && !config.echoEvents) {
452
+ throw new Error("Please specify host variable in jitsu plugin initialization, or set echoEvents to true");
373
453
  }
374
454
  },
375
455
  page: args => {
package/dist/web/p.js.txt CHANGED
@@ -76,6 +76,7 @@
76
76
  host: null,
77
77
  debug: false,
78
78
  fetch: null,
79
+ echoEvents: false,
79
80
  };
80
81
  const parseQuery = (qs) => {
81
82
  if (!qs) {
@@ -312,22 +313,81 @@
312
313
  },
313
314
  campaign: parseUtms(query),
314
315
  };
315
- const withContext = Object.assign(Object.assign({}, payload), { timestamp: new Date().toISOString(), sentAt: new Date().toISOString(), messageId: randomId(properties.path || (parsedUrl && parsedUrl.pathname)), context: deepMerge(context, customContext) });
316
+ const withContext = Object.assign(Object.assign({}, payload), { timestamp: new Date().toISOString(), sentAt: new Date().toISOString(), messageId: randomId(properties.path || (parsedUrl && parsedUrl.pathname)), writeKey: config.writeKey, context: deepMerge(context, customContext) });
316
317
  delete withContext.meta;
317
318
  delete withContext.options;
318
319
  return withContext;
319
320
  }
321
+ function execJs(code, event) {
322
+ const varName = `jitsu_event_${randomId()}`;
323
+ window[varName] = event;
324
+ const iif = `(function(){
325
+ ${code}
326
+ onEvent(${varName});
327
+ })()`;
328
+ try {
329
+ eval(iif);
330
+ }
331
+ catch (e) {
332
+ console.error(`[JITSU] Error executing JS code: ${e.message}`);
333
+ }
334
+ finally {
335
+ delete window[varName];
336
+ }
337
+ return iif;
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);
348
+ }
349
+ else {
350
+ const codeHolder = document.createElement("span");
351
+ codeHolder.innerHTML = replaceMacro(tag.code, event);
352
+ document.body.insertAdjacentElement("beforeend", codeHolder);
353
+ const scripts = codeHolder.querySelectorAll("script");
354
+ scripts.forEach(script => {
355
+ const scriptClone = document.createElement("script");
356
+ scriptClone.type = scriptClone.type || "text/javascript";
357
+ if (script.hasAttribute("src")) {
358
+ scriptClone.src = script.src;
359
+ }
360
+ scriptClone.text = script.text;
361
+ if (debug) {
362
+ console.log(`Executing script${script.hasAttribute("src") ? ` ${script.src}` : ""}`, scriptClone.text);
363
+ }
364
+ document.head.appendChild(scriptClone);
365
+ document.head.removeChild(scriptClone);
366
+ });
367
+ }
368
+ });
369
+ }
370
+ else {
371
+ if (debug) {
372
+ console.log(`insertTags: cannot insert tags in non-browser environment`);
373
+ }
374
+ }
375
+ }
320
376
  function send(method, payload, jitsuConfig, store) {
377
+ if (jitsuConfig.echoEvents) {
378
+ console.log(`[JITSU] sending '${method}' event:`, payload);
379
+ return;
380
+ }
321
381
  const url = `${jitsuConfig.host}/api/s/${method}`;
322
382
  const fetch = jitsuConfig.fetch || globalThis.fetch;
323
383
  if (!fetch) {
324
384
  throw new Error("Please specify fetch function in jitsu plugin initialization, fetch isn't available in global scope");
325
385
  }
326
- const authHeader = jitsuConfig.writeKey ? { Authorization: `Bearer ${jitsuConfig.writeKey}` } : {};
386
+ const authHeader = {};
327
387
  const debugHeader = jitsuConfig.debug ? { "X-Enable-Debug": "true" } : {};
328
- if (jitsuConfig.debug) {
329
- console.log(`Sending jitsu event to ${url}: `, JSON.stringify(payload, null, 2));
330
- }
388
+ // if (jitsuConfig.debug) {
389
+ // console.log(`[JITSU] Sending event to ${url}: `, JSON.stringify(payload, null, 2));
390
+ // }
331
391
  const adjustedPayload = adjustPayload(payload, jitsuConfig, store);
332
392
  return fetch(url, {
333
393
  method: "POST",
@@ -336,7 +396,27 @@
336
396
  })
337
397
  .then(res => {
338
398
  if (jitsuConfig.debug) {
339
- console.debug(`Jitsu ${url} replied ${res.status}. Original payload: `, JSON.stringify(adjustedPayload, null, 2));
399
+ console.log(`[JITSU] ${url} replied ${res.status}. Original payload: `, JSON.stringify(adjustedPayload, null, 2));
400
+ }
401
+ if (res.ok) {
402
+ return res.text();
403
+ }
404
+ else {
405
+ return Promise.reject(res.text());
406
+ }
407
+ })
408
+ .then(responseText => {
409
+ try {
410
+ const response = JSON.parse(responseText);
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
+ }
417
+ }
418
+ catch (e) {
419
+ return Promise.reject(`Can't parse JSON: ${responseText}: ${e === null || e === void 0 ? void 0 : e.message}`);
340
420
  }
341
421
  })
342
422
  .catch(err => {
@@ -371,8 +451,8 @@
371
451
  if (config.debug) {
372
452
  console.debug("Initializing Jitsu plugin with config: ", JSON.stringify(config));
373
453
  }
374
- if (!config.host) {
375
- throw new Error("Please specify host variable in jitsu plugin initialization");
454
+ if (!config.host && !config.echoEvents) {
455
+ throw new Error("Please specify host variable in jitsu plugin initialization, or set echoEvents to true");
376
456
  }
377
457
  },
378
458
  page: args => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jitsu/js",
3
- "version": "0.0.1-alpha.127",
3
+ "version": "0.0.1-alpha.174",
4
4
  "description": "",
5
5
  "author": "Jitsu Dev Team <dev@jitsu.com>",
6
6
  "main": "dist/jitsu.cjs.js",
@@ -36,7 +36,7 @@
36
36
  },
37
37
  "dependencies": {
38
38
  "analytics": "^0.8.1",
39
- "@jitsu/protocols": "0.0.1-alpha.127"
39
+ "@jitsu/protocols": "0.0.1-alpha.174"
40
40
  },
41
41
  "scripts": {
42
42
  "clean": "rm -rf ./dist",
@@ -12,6 +12,7 @@ const config: JitsuOptions = {
12
12
  host: null,
13
13
  debug: false,
14
14
  fetch: null,
15
+ echoEvents: false,
15
16
  };
16
17
 
17
18
  export const parseQuery = (qs?: string): Record<string, string> => {
@@ -276,6 +277,7 @@ function adjustPayload(payload: any, config: JitsuOptions, storage: PersistentSt
276
277
  timestamp: new Date().toISOString(),
277
278
  sentAt: new Date().toISOString(),
278
279
  messageId: randomId(properties.path || (parsedUrl && parsedUrl.pathname)),
280
+ writeKey: config.writeKey,
279
281
  context: deepMerge(context, customContext),
280
282
  };
281
283
  delete withContext.meta;
@@ -283,7 +285,70 @@ function adjustPayload(payload: any, config: JitsuOptions, storage: PersistentSt
283
285
  return withContext;
284
286
  }
285
287
 
288
+ function execJs(code: string, event: any) {
289
+ const varName = `jitsu_event_${randomId()}`;
290
+ window[varName] = event;
291
+ const iif = `(function(){
292
+ ${code}
293
+ onEvent(${varName});
294
+ })()`;
295
+ try {
296
+ eval(iif);
297
+ } catch (e) {
298
+ console.error(`[JITSU] Error executing JS code: ${e.message}`);
299
+ } finally {
300
+ delete window[varName];
301
+ }
302
+ return iif;
303
+ }
304
+
305
+ function replaceMacro(code, event) {
306
+ return code.replace(/{{\s*event\s*}}/g, JSON.stringify(event));
307
+ }
308
+
309
+ function insertTags(
310
+ tags: Record<string, { mode: "javascript" | "html"; code }>,
311
+ event: any,
312
+ opts: { debug?: boolean } = {}
313
+ ) {
314
+ const debug = opts.debug || false;
315
+ if (isInBrowser()) {
316
+ Object.values(tags).forEach(tag => {
317
+ if (tag.mode === "javascript") {
318
+ execJs(tag.code, event);
319
+ } else {
320
+ const codeHolder = document.createElement("span");
321
+ codeHolder.innerHTML = replaceMacro(tag.code, event);
322
+ document.body.insertAdjacentElement("beforeend", codeHolder);
323
+ const scripts = codeHolder.querySelectorAll("script");
324
+ scripts.forEach(script => {
325
+ const scriptClone = document.createElement("script");
326
+ scriptClone.type = scriptClone.type || "text/javascript";
327
+ if (script.hasAttribute("src")) {
328
+ scriptClone.src = script.src;
329
+ }
330
+ scriptClone.text = script.text;
331
+ if (debug) {
332
+ console.log(`Executing script${script.hasAttribute("src") ? ` ${script.src}` : ""}`, scriptClone.text);
333
+ }
334
+ document.head.appendChild(scriptClone);
335
+ document.head.removeChild(scriptClone);
336
+ });
337
+ }
338
+ });
339
+ } else {
340
+ if (debug) {
341
+ console.log(`insertTags: cannot insert tags in non-browser environment`);
342
+ }
343
+ }
344
+ }
345
+
286
346
  function send(method, payload, jitsuConfig: Required<JitsuOptions>, store: PersistentStorage): Promise<void> {
347
+ if (jitsuConfig.echoEvents) {
348
+ console.log(`[JITSU] sending '${method}' event:`, payload);
349
+ return;
350
+ }
351
+
287
352
  const url = `${jitsuConfig.host}/api/s/${method}`;
288
353
  const fetch = jitsuConfig.fetch || globalThis.fetch;
289
354
  if (!fetch) {
@@ -291,12 +356,12 @@ function send(method, payload, jitsuConfig: Required<JitsuOptions>, store: Persi
291
356
  "Please specify fetch function in jitsu plugin initialization, fetch isn't available in global scope"
292
357
  );
293
358
  }
294
- const authHeader = jitsuConfig.writeKey ? { Authorization: `Bearer ${jitsuConfig.writeKey}` } : {};
359
+ const authHeader = {};
295
360
  const debugHeader = jitsuConfig.debug ? { "X-Enable-Debug": "true" } : {};
296
361
 
297
- if (jitsuConfig.debug) {
298
- console.log(`Sending jitsu event to ${url}: `, JSON.stringify(payload, null, 2));
299
- }
362
+ // if (jitsuConfig.debug) {
363
+ // console.log(`[JITSU] Sending event to ${url}: `, JSON.stringify(payload, null, 2));
364
+ // }
300
365
  const adjustedPayload = adjustPayload(payload, jitsuConfig, store);
301
366
  return fetch(url, {
302
367
  method: "POST",
@@ -310,11 +375,29 @@ function send(method, payload, jitsuConfig: Required<JitsuOptions>, store: Persi
310
375
  })
311
376
  .then(res => {
312
377
  if (jitsuConfig.debug) {
313
- console.debug(
314
- `Jitsu ${url} replied ${res.status}. Original payload: `,
378
+ console.log(
379
+ `[JITSU] ${url} replied ${res.status}. Original payload: `,
315
380
  JSON.stringify(adjustedPayload, null, 2)
316
381
  );
317
382
  }
383
+ if (res.ok) {
384
+ return res.text();
385
+ } else {
386
+ return Promise.reject(res.text());
387
+ }
388
+ })
389
+ .then(responseText => {
390
+ try {
391
+ const response = JSON.parse(responseText);
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
+ }
398
+ } catch (e) {
399
+ return Promise.reject(`Can't parse JSON: ${responseText}: ${e?.message}`);
400
+ }
318
401
  })
319
402
  .catch(err => {
320
403
  if (jitsuConfig.debug) {
@@ -352,8 +435,8 @@ const jitsuAnalyticsPlugin = (pluginConfig: JitsuOptions = {}): AnalyticsPlugin
352
435
  if (config.debug) {
353
436
  console.debug("Initializing Jitsu plugin with config: ", JSON.stringify(config));
354
437
  }
355
- if (!config.host) {
356
- throw new Error("Please specify host variable in jitsu plugin initialization");
438
+ if (!config.host && !config.echoEvents) {
439
+ throw new Error("Please specify host variable in jitsu plugin initialization, or set echoEvents to true");
357
440
  }
358
441
  },
359
442
  page: args => {
package/src/jitsu.ts CHANGED
@@ -11,10 +11,33 @@ type JitsuOptions = {
11
11
  * API Host. Default value: same host as script origin
12
12
  */
13
13
  host?: string;
14
+ /**
15
+ * To enable debug logging
16
+ */
14
17
  debug?: boolean;
18
+ /**
19
+ * Explicitely specify cookie domain. If not set, cookie domain will be set to top level
20
+ * of the current domain. Example: if JS lives on "app.example.com", cookie domain will be
21
+ * set to ".example.com". If it lives on "example.com", cookie domain will be set to ".example.com" too
22
+ */
15
23
  cookieDomain?: string;
24
+ /**
25
+ * Provide fetch implementation. It is required if you want to use Jitsu in NodeJS
26
+ */
16
27
  fetch?: typeof fetch;
28
+ /**
29
+ * Which runtime to use. Runtime is used for obtaining context of the event: cookes,
30
+ * url, etc. At the moment, Jitsu supports browser runtime and NodeJS runtime, but you
31
+ * can provide your own implementation.
32
+ *
33
+ * If it's not set, the runtime will be detected automatically by presense of `window` object
34
+ */
17
35
  runtime?: RuntimeFacade;
36
+ /**
37
+ * If set to true, jitsu will output events in console. In this case you don't need to set
38
+ * writeKey / host. It's useful for debugging development environment
39
+ */
40
+ echoEvents?: boolean;
18
41
  };
19
42
 
20
43
  type PersistentStorage = {