@mhubcloud/tms_core 2.0.0-beta.1 → 2.0.0-beta.3
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/dist/index.js +39 -24
- package/package.json +1 -1
- package/releasePlan.md +1 -2
- package/src/index.ts +2 -1
- package/src/utils/testUtils.ts +18 -0
- package/src/utils/utils.ts +5 -5
- package/tests/AffiliatePort.js +1 -1
- package/tests/CJ.js +1 -1
- package/tests/Facebook.js +1 -1
- package/tests/GoogleAnalytics4.js +1 -1
- package/tests/Piano.js +1 -1
- package/tests/UniversalAnalytics.js +1 -1
- package/js/lib/defaultPublisher.js +0 -116
- package/js/lib/utils.js +0 -349
- package/js/publishers/AffiliatePort.js +0 -78
- package/js/publishers/CJ.js +0 -68
- package/js/publishers/Facebook.js +0 -64
- package/js/publishers/GoogleAnalytics4.js +0 -76
- package/js/publishers/HttpPublisher.js +0 -64
- package/js/publishers/Piano.js +0 -68
- package/js/publishers/UniversalAnalytics.js +0 -75
- package/tests/testUtils.js +0 -7
package/dist/index.js
CHANGED
|
@@ -32,6 +32,7 @@ var src_exports = {};
|
|
|
32
32
|
__export(src_exports, {
|
|
33
33
|
DefaultPublisher: () => defaultPublisher,
|
|
34
34
|
publisher: () => publisher,
|
|
35
|
+
testUtils: () => testUtils_exports,
|
|
35
36
|
utils: () => utils_exports
|
|
36
37
|
});
|
|
37
38
|
module.exports = __toCommonJS(src_exports);
|
|
@@ -79,16 +80,16 @@ var EventPublisherBase = class {
|
|
|
79
80
|
);
|
|
80
81
|
}
|
|
81
82
|
};
|
|
82
|
-
function log(
|
|
83
|
-
|
|
83
|
+
function log(log3, level, message, properties) {
|
|
84
|
+
log3.warn(message);
|
|
84
85
|
aiClient?.trackTrace({
|
|
85
86
|
message,
|
|
86
87
|
severity: level,
|
|
87
88
|
properties
|
|
88
89
|
});
|
|
89
90
|
}
|
|
90
|
-
function logException(
|
|
91
|
-
|
|
91
|
+
function logException(log3, exception) {
|
|
92
|
+
log3.warn(exception);
|
|
92
93
|
aiClient?.trackException({
|
|
93
94
|
exception
|
|
94
95
|
});
|
|
@@ -263,7 +264,7 @@ async function defaultPublisher(azureFunctionContext, eventHubMessages, source,
|
|
|
263
264
|
}
|
|
264
265
|
}
|
|
265
266
|
}
|
|
266
|
-
async function processMessage(message,
|
|
267
|
+
async function processMessage(message, log3, platfromPublisher, trigger) {
|
|
267
268
|
const logProperties = {
|
|
268
269
|
source: platfromPublisher.source,
|
|
269
270
|
data: JSON.stringify(message)
|
|
@@ -271,7 +272,7 @@ async function processMessage(message, log2, platfromPublisher, trigger) {
|
|
|
271
272
|
const publishers = trigger(message);
|
|
272
273
|
if (!publishers.length) {
|
|
273
274
|
log(
|
|
274
|
-
|
|
275
|
+
log3,
|
|
275
276
|
1,
|
|
276
277
|
"Message excluded by filter (no publishers determined)",
|
|
277
278
|
logProperties
|
|
@@ -283,7 +284,7 @@ async function processMessage(message, log2, platfromPublisher, trigger) {
|
|
|
283
284
|
for (const eventPublisher of publishers) {
|
|
284
285
|
const mapped = await eventPublisher.map(message);
|
|
285
286
|
const res = await publishMessage(
|
|
286
|
-
|
|
287
|
+
log3,
|
|
287
288
|
mapped,
|
|
288
289
|
eventPublisher.config,
|
|
289
290
|
platfromPublisher,
|
|
@@ -293,7 +294,7 @@ async function processMessage(message, log2, platfromPublisher, trigger) {
|
|
|
293
294
|
publishedAny = true;
|
|
294
295
|
} else {
|
|
295
296
|
logException(
|
|
296
|
-
|
|
297
|
+
log3,
|
|
297
298
|
new Error(
|
|
298
299
|
`The message has not been published. Source: ${platfromPublisher.source}`
|
|
299
300
|
)
|
|
@@ -303,7 +304,7 @@ async function processMessage(message, log2, platfromPublisher, trigger) {
|
|
|
303
304
|
}
|
|
304
305
|
if (!publishedAny) {
|
|
305
306
|
logException(
|
|
306
|
-
|
|
307
|
+
log3,
|
|
307
308
|
new Error(
|
|
308
309
|
"The message has not been published to any publisher configuration"
|
|
309
310
|
)
|
|
@@ -312,8 +313,8 @@ async function processMessage(message, log2, platfromPublisher, trigger) {
|
|
|
312
313
|
}
|
|
313
314
|
return !failedToPublishAll;
|
|
314
315
|
}
|
|
315
|
-
async function publishMessage(
|
|
316
|
-
await platformPublisher.publish(
|
|
316
|
+
async function publishMessage(log3, mapped, config, platformPublisher, event) {
|
|
317
|
+
await platformPublisher.publish(log3, config, mapped, event);
|
|
317
318
|
return true;
|
|
318
319
|
}
|
|
319
320
|
|
|
@@ -327,7 +328,7 @@ var affiliatePort = {
|
|
|
327
328
|
* @param data Data in publisher-friendly format to be published
|
|
328
329
|
* @param event Event for which the function is triggered
|
|
329
330
|
*/
|
|
330
|
-
async publish(
|
|
331
|
+
async publish(log3, config, data, event) {
|
|
331
332
|
if (data.products instanceof Array && (typeof config.offerId === "string" || typeof config.offerId === "number")) {
|
|
332
333
|
const affiliatePortData = removeUndefined(
|
|
333
334
|
data
|
|
@@ -346,7 +347,7 @@ var affiliatePort = {
|
|
|
346
347
|
query,
|
|
347
348
|
requestOptions,
|
|
348
349
|
event,
|
|
349
|
-
logger:
|
|
350
|
+
logger: log3
|
|
350
351
|
});
|
|
351
352
|
}
|
|
352
353
|
} else {
|
|
@@ -365,9 +366,9 @@ var cj = {
|
|
|
365
366
|
* @param data Data in publisher-friendly format to be published
|
|
366
367
|
* @param event Event for which the function is triggered
|
|
367
368
|
*/
|
|
368
|
-
async publish(
|
|
369
|
+
async publish(log3, config, data, event) {
|
|
369
370
|
if (!data.cjevent) {
|
|
370
|
-
log(
|
|
371
|
+
log(log3, 1, `CJ - ${event} - skipped because CJEVENT is missing`);
|
|
371
372
|
} else {
|
|
372
373
|
if (typeof config.cid === "string" && typeof config.type === "string") {
|
|
373
374
|
const cjData = removeUndefined(data);
|
|
@@ -393,7 +394,7 @@ var cj = {
|
|
|
393
394
|
query,
|
|
394
395
|
requestOptions,
|
|
395
396
|
event,
|
|
396
|
-
logger:
|
|
397
|
+
logger: log3
|
|
397
398
|
});
|
|
398
399
|
} else {
|
|
399
400
|
throw new Error("Invalid config for platform " + this.source);
|
|
@@ -412,7 +413,7 @@ var facebook = {
|
|
|
412
413
|
* @param data Data in publisher-friendly format to be published
|
|
413
414
|
* @param event Event for which the function is triggered
|
|
414
415
|
*/
|
|
415
|
-
async publish(
|
|
416
|
+
async publish(log3, config, data, event) {
|
|
416
417
|
if (typeof config.id === "string" && typeof config.access_token === "string") {
|
|
417
418
|
const requestOptions = {
|
|
418
419
|
method: "POST",
|
|
@@ -432,7 +433,7 @@ var facebook = {
|
|
|
432
433
|
query,
|
|
433
434
|
requestOptions,
|
|
434
435
|
event,
|
|
435
|
-
logger:
|
|
436
|
+
logger: log3
|
|
436
437
|
});
|
|
437
438
|
} else {
|
|
438
439
|
throw new Error("Invalid config for platform " + this.source);
|
|
@@ -450,7 +451,7 @@ var googleAnalytics4 = {
|
|
|
450
451
|
* @param data Data in publisher-friendly format to be published
|
|
451
452
|
* @param event Event for which the function is triggered
|
|
452
453
|
*/
|
|
453
|
-
async publish(
|
|
454
|
+
async publish(log3, config, data, event) {
|
|
454
455
|
if (config.trackingId) {
|
|
455
456
|
const ga4Data = removeUndefined(data);
|
|
456
457
|
ga4Data.v = 2;
|
|
@@ -481,7 +482,7 @@ var googleAnalytics4 = {
|
|
|
481
482
|
query,
|
|
482
483
|
requestOptions,
|
|
483
484
|
event,
|
|
484
|
-
logger:
|
|
485
|
+
logger: log3
|
|
485
486
|
});
|
|
486
487
|
} else {
|
|
487
488
|
throw new Error("Invalid config for platform " + this.source);
|
|
@@ -499,7 +500,7 @@ var piano = {
|
|
|
499
500
|
* @param data Data in publisher-friendly format to be published
|
|
500
501
|
* @param event Event for which the function is triggered
|
|
501
502
|
*/
|
|
502
|
-
async publish(
|
|
503
|
+
async publish(log3, config, data, event) {
|
|
503
504
|
if (typeof config.siteId === "string" && typeof config.collectionDomain === "string") {
|
|
504
505
|
const pianoData = removeUndefined(data);
|
|
505
506
|
let query = "";
|
|
@@ -526,7 +527,7 @@ var piano = {
|
|
|
526
527
|
query,
|
|
527
528
|
requestOptions,
|
|
528
529
|
event,
|
|
529
|
-
logger:
|
|
530
|
+
logger: log3
|
|
530
531
|
});
|
|
531
532
|
} else {
|
|
532
533
|
throw new Error("Invalid config for platform " + this.source);
|
|
@@ -544,7 +545,7 @@ var universalAnalytics = {
|
|
|
544
545
|
* @param data Data in publisher-friendly format to be published
|
|
545
546
|
* @param event Event for which the function is triggered
|
|
546
547
|
*/
|
|
547
|
-
async publish(
|
|
548
|
+
async publish(log3, config, data, event) {
|
|
548
549
|
if (config.trackingId) {
|
|
549
550
|
const uaData = removeUndefined(data);
|
|
550
551
|
uaData.v = 1;
|
|
@@ -578,7 +579,7 @@ var universalAnalytics = {
|
|
|
578
579
|
query,
|
|
579
580
|
requestOptions,
|
|
580
581
|
event,
|
|
581
|
-
logger:
|
|
582
|
+
logger: log3
|
|
582
583
|
});
|
|
583
584
|
} else {
|
|
584
585
|
throw new Error("Invalid config for platform " + this.source);
|
|
@@ -586,6 +587,19 @@ var universalAnalytics = {
|
|
|
586
587
|
}
|
|
587
588
|
};
|
|
588
589
|
|
|
590
|
+
// src/utils/testUtils.ts
|
|
591
|
+
var testUtils_exports = {};
|
|
592
|
+
__export(testUtils_exports, {
|
|
593
|
+
context: () => context
|
|
594
|
+
});
|
|
595
|
+
var context = {};
|
|
596
|
+
context.log = function log2(str) {
|
|
597
|
+
console.log(str);
|
|
598
|
+
};
|
|
599
|
+
context.log.warn = function warn(str) {
|
|
600
|
+
console.warn(str);
|
|
601
|
+
};
|
|
602
|
+
|
|
589
603
|
// src/index.ts
|
|
590
604
|
var publisher = {
|
|
591
605
|
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
@@ -605,5 +619,6 @@ var publisher = {
|
|
|
605
619
|
0 && (module.exports = {
|
|
606
620
|
DefaultPublisher,
|
|
607
621
|
publisher,
|
|
622
|
+
testUtils,
|
|
608
623
|
utils
|
|
609
624
|
});
|
package/package.json
CHANGED
package/releasePlan.md
CHANGED
|
@@ -1,3 +1,2 @@
|
|
|
1
1
|
To test after release:
|
|
2
|
-
- Zkontrolovat event_time posílaný do FB, že chodí ve správném formátu a že obsahuje správný údaj.
|
|
3
|
-
- Když použiju utils.log tak to do appinsights zaloguje dvakrát? Máme totiž podezření, že ano.
|
|
2
|
+
- Zkontrolovat event_time posílaný do FB, že chodí ve správném formátu a že obsahuje správný údaj.
|
package/src/index.ts
CHANGED
|
@@ -5,6 +5,7 @@ import { facebook } from './publishers/facebook';
|
|
|
5
5
|
import { googleAnalytics4 } from './publishers/googleAnalytics4';
|
|
6
6
|
import { piano } from './publishers/piano';
|
|
7
7
|
import { universalAnalytics } from './publishers/universalAnalytics';
|
|
8
|
+
import * as testUtils from './utils/testUtils';
|
|
8
9
|
import * as utils from './utils/utils';
|
|
9
10
|
|
|
10
11
|
export const publisher = {
|
|
@@ -22,4 +23,4 @@ export const publisher = {
|
|
|
22
23
|
AffiliatePort: affiliatePort,
|
|
23
24
|
};
|
|
24
25
|
|
|
25
|
-
export { utils, defaultPublisher as DefaultPublisher };
|
|
26
|
+
export { utils, defaultPublisher as DefaultPublisher, testUtils };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
interface LogFunction {
|
|
2
|
+
(str: string): void;
|
|
3
|
+
warn: (str: string) => void;
|
|
4
|
+
}
|
|
5
|
+
// TODO tohle by se mělo dát spíš do nějakých obecných types asi
|
|
6
|
+
interface Context {
|
|
7
|
+
log: LogFunction;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const context: Context = {} as Context;
|
|
11
|
+
context.log = function log(str: string) {
|
|
12
|
+
console.log(str);
|
|
13
|
+
} as LogFunction;
|
|
14
|
+
context.log.warn = function warn(str: string) {
|
|
15
|
+
console.warn(str);
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export { context };
|
package/src/utils/utils.ts
CHANGED
|
@@ -63,11 +63,11 @@ export function log(
|
|
|
63
63
|
properties?: Telemetry['properties'],
|
|
64
64
|
): void {
|
|
65
65
|
log.warn(message);
|
|
66
|
-
aiClient?.trackTrace({
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
});
|
|
66
|
+
// aiClient?.trackTrace({
|
|
67
|
+
// message,
|
|
68
|
+
// severity: level,
|
|
69
|
+
// properties,
|
|
70
|
+
// });
|
|
71
71
|
}
|
|
72
72
|
|
|
73
73
|
/**
|
package/tests/AffiliatePort.js
CHANGED
|
@@ -2,7 +2,7 @@ const publisher = require('../dist/index.js').publisher.AffiliatePort;
|
|
|
2
2
|
const defaultPublisher = require('../dist/index.js').DefaultPublisher;
|
|
3
3
|
const utils = require('../dist/index.js').utils;
|
|
4
4
|
var assert = require('assert');
|
|
5
|
-
const testUtils = require('
|
|
5
|
+
const testUtils = require('../dist/index.js').testUtils;
|
|
6
6
|
|
|
7
7
|
describe('test AffiliatePort publisher', function () {
|
|
8
8
|
it('purchase', async function () {
|
package/tests/CJ.js
CHANGED
|
@@ -2,7 +2,7 @@ const publisher = require('../dist/index.js').publisher.CJ;
|
|
|
2
2
|
const defaultPublisher = require('../dist/index.js').DefaultPublisher;
|
|
3
3
|
const utils = require('../dist/index.js').utils;
|
|
4
4
|
var assert = require('assert');
|
|
5
|
-
const testUtils = require('
|
|
5
|
+
const testUtils = require('../dist/index.js').testUtils;
|
|
6
6
|
|
|
7
7
|
describe('test CJ publisher', function () {
|
|
8
8
|
it('purchase', async function () {
|
package/tests/Facebook.js
CHANGED
|
@@ -2,7 +2,7 @@ const publisher = require('../dist/index.js').publisher.Facebook;
|
|
|
2
2
|
const defaultPublisher = require('../dist/index.js').DefaultPublisher;
|
|
3
3
|
const utils = require('../dist/index.js').utils;
|
|
4
4
|
var assert = require('assert');
|
|
5
|
-
const testUtils = require('
|
|
5
|
+
const testUtils = require('../dist/index.js').testUtils;
|
|
6
6
|
|
|
7
7
|
describe('test Facebook publisher', function () {
|
|
8
8
|
it('purchase', async function () {
|
|
@@ -2,7 +2,7 @@ const publisher = require('../dist/index.js').publisher.GoogleAnalytics4;
|
|
|
2
2
|
const defaultPublisher = require('../dist/index.js').DefaultPublisher;
|
|
3
3
|
const utils = require('../dist/index.js').utils;
|
|
4
4
|
var assert = require('assert');
|
|
5
|
-
const testUtils = require('
|
|
5
|
+
const testUtils = require('../dist/index.js').testUtils;
|
|
6
6
|
|
|
7
7
|
describe('test GoogleAnalytics4 publisher', function () {
|
|
8
8
|
it('purchase', async function () {
|
package/tests/Piano.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
const publisher = require('../dist/index.js').publisher.Piano;
|
|
2
2
|
const defaultPublisher = require('../dist/index.js').DefaultPublisher;
|
|
3
3
|
const utils = require('../dist/index.js').utils;
|
|
4
|
+
const testUtils = require('../dist/index.js').testUtils;
|
|
4
5
|
var assert = require('assert');
|
|
5
|
-
const testUtils = require('./testUtils');
|
|
6
6
|
|
|
7
7
|
describe('test Piano publisher', function () {
|
|
8
8
|
it('purchase', async function () {
|
|
@@ -2,7 +2,7 @@ const publisher = require('../dist/index.js').publisher.UniversalAnalytics;
|
|
|
2
2
|
const defaultPublisher = require('../dist/index.js').DefaultPublisher;
|
|
3
3
|
const utils = require('../dist/index.js').utils;
|
|
4
4
|
var assert = require('assert');
|
|
5
|
-
const testUtils = require('
|
|
5
|
+
const testUtils = require('../dist/index.js').testUtils;
|
|
6
6
|
|
|
7
7
|
describe('test UniversalAnalytics publisher', function () {
|
|
8
8
|
it('pageview', async function () {
|
|
@@ -1,116 +0,0 @@
|
|
|
1
|
-
//Default common implementation of each publisher's index.js
|
|
2
|
-
const utils = require("./utils");
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Implements the Azure Function, called for set of events received via Event Hub
|
|
6
|
-
* @param {FunctionContext} log Azure Function context.log.warn
|
|
7
|
-
* @param {Object[]} eventHubMessages Array of messages received from Event Hub
|
|
8
|
-
* @param {string} source Name of the publisher (it's folder name in which it's implemented)
|
|
9
|
-
* @param {PlatformPublisher} publisher Publisher implementation instance (from <publisher>/publisher.js)
|
|
10
|
-
* @param {Trigger} trigger Publisher-specific trigger function (from <publisher>/customizable/trigger.js)
|
|
11
|
-
* @returns {Promise<void|ReqResTestData[]>} When run in test mode (@param context.test is true), returns collected array of requests (otherwise) sent to platform. When additionaly run as test with publication (@param context.tests and @param context.testPublish) the response contains both - request and response data.
|
|
12
|
-
*/
|
|
13
|
-
module.exports = async function DefaultPublisher(azureFunctionContext, eventHubMessages, source, publisher, trigger) {
|
|
14
|
-
|
|
15
|
-
azureFunctionContext.log.warn(`JavaScript eventhub trigger function called for message array [${eventHubMessages.length}]`);
|
|
16
|
-
let mi = 0;
|
|
17
|
-
|
|
18
|
-
let processMessagePromises = [];
|
|
19
|
-
for (const message of eventHubMessages) {
|
|
20
|
-
processMessagePromises.push(processMessage(message, azureFunctionContext.log.warn, azureFunctionContext.test, azureFunctionContext.debug, azureFunctionContext.testPublish, source, publisher, trigger, mi++));
|
|
21
|
-
}
|
|
22
|
-
let results = await Promise.allSettled(processMessagePromises);
|
|
23
|
-
for (const result of results) {
|
|
24
|
-
if(result.status === "rejected"){
|
|
25
|
-
utils.logException(azureFunctionContext.log.warn, result.reason);
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Processes single message
|
|
32
|
-
* @param {Object} message A message received from Event Hub
|
|
33
|
-
* @param {FunctionContext} log Azure Function context.log.warn
|
|
34
|
-
* @param {FunctionContext} test Azure Function context.test
|
|
35
|
-
* @param {string} source Name of the publisher (it's folder name in which it's implemented)
|
|
36
|
-
* @param {PlatformPublisher} platfromPublisher Publisher implementation instance (from <publisher>/publisher.js)
|
|
37
|
-
* @param {Trigger} trigger Publisher-specific trigger function (from <publisher>/customizable/trigger.js)
|
|
38
|
-
* @param {number} mi Messae index (0-based), only for logging purposes
|
|
39
|
-
* @returns {Promise<boolean|ReqResTestData[]>} In normal mode returns true/false indicating if the message has been successfully published to any platform. In (unit) test mode returns array of publication requests (or even results if it's not unit test), fulse just in case the were no publishers configured.
|
|
40
|
-
*/
|
|
41
|
-
async function processMessage(message, log, test, debug, testPublish, source, platfromPublisher, trigger, mi) {
|
|
42
|
-
|
|
43
|
-
let ret = test ? [] : false;
|
|
44
|
-
if (debug)
|
|
45
|
-
log(`Processing message №${mi + 1} ${JSON.stringify(message, null, "")}`);
|
|
46
|
-
|
|
47
|
-
const data = platfromPublisher.parse(message, context);
|
|
48
|
-
const logProp = {
|
|
49
|
-
source: source,
|
|
50
|
-
data: JSON.stringify(data)
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
/** @type {EventPublisher[]} */
|
|
54
|
-
const publishers = trigger(data);
|
|
55
|
-
if (!publishers?.length) {
|
|
56
|
-
utils.log2(log, 1, "Message excluded by filter (no publishers determined)", logProp);
|
|
57
|
-
return false;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
let prevPublisher = null;
|
|
61
|
-
let prevMappedData = null;
|
|
62
|
-
let prevValidionResult = null;
|
|
63
|
-
let passedAnyValidation = false;
|
|
64
|
-
let published = false;
|
|
65
|
-
for (const eventPublisher of publishers) {
|
|
66
|
-
if (prevPublisher === eventPublisher ? prevValidionResult : (prevValidionResult = eventPublisher.validate(data))) { //Optimization
|
|
67
|
-
passedAnyValidation = true;
|
|
68
|
-
} else {
|
|
69
|
-
utils.log2(log, 1, "Message excluded by validation", logProp);
|
|
70
|
-
continue;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
const mapped = logProp.mapped = prevMappedData = (prevPublisher === eventPublisher ? prevMappedData : await eventPublisher.map(data)); //Optimization
|
|
74
|
-
|
|
75
|
-
prevPublisher = eventPublisher;
|
|
76
|
-
|
|
77
|
-
const res = await publishMessage(log, mapped, eventPublisher.config, test, testPublish, platfromPublisher, message.event.code + (message.event.name ? "/"+ message.event.name : ""));
|
|
78
|
-
if (res) published = true;
|
|
79
|
-
if (test && res instanceof Array) ret.push(...res);
|
|
80
|
-
if (res && !test) ret = true;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
if (!passedAnyValidation) {
|
|
84
|
-
utils.log2(log, 2, "Message excluded by all publishers' validations", logProp);
|
|
85
|
-
return false;
|
|
86
|
-
}
|
|
87
|
-
if (!published) {
|
|
88
|
-
utils.log2(log, 2, "The message has not been published to any publisher configuration", logProp);
|
|
89
|
-
return false;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
return ret;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
/**
|
|
96
|
-
* Publishes a message to configured publisher
|
|
97
|
-
* @param {Object} mapped Mapped message data
|
|
98
|
-
* @param {Object} config Platform-specific platform publisher configuration
|
|
99
|
-
* @param {FunctionContext} test Azure Function context.test
|
|
100
|
-
* @param {PlatformPublisher} platfromPublisher Publisher implementation instance (from <publisher>/publisher.js)
|
|
101
|
-
* @param {string} event for which logic was triggered
|
|
102
|
-
* @returns {Promise<boolean|ReqResTestData[]>} In normal mode returns true/false indicating if the message has been successfully published to any platform. In (unit) test mode returns array of publication requests (or even results if it's not unit test), fulse just in case the were no publishers configured.
|
|
103
|
-
*/
|
|
104
|
-
async function publishMessage(log, mapped, config, test, testPublish, platfromPublisher, event) {
|
|
105
|
-
let ret = test ? [] : true;
|
|
106
|
-
if (test)
|
|
107
|
-
ret.push({ req: mapped, config: config });
|
|
108
|
-
|
|
109
|
-
if (!test || testPublish) {
|
|
110
|
-
const res = await platfromPublisher.publish(log, config, mapped, event);
|
|
111
|
-
if (context.test) ret[ret.length - 1].res = res;
|
|
112
|
-
return ret; //true
|
|
113
|
-
} else {
|
|
114
|
-
return ret; //true
|
|
115
|
-
}
|
|
116
|
-
}
|
package/js/lib/utils.js
DELETED
|
@@ -1,349 +0,0 @@
|
|
|
1
|
-
const crypto = require('crypto');
|
|
2
|
-
const fs = require('fs');
|
|
3
|
-
const https = require('https');
|
|
4
|
-
const Ajv = require('ajv');
|
|
5
|
-
|
|
6
|
-
let aiClient;
|
|
7
|
-
if (process.env.APPINSIGHTS_INSTRUMENTATIONKEY) {
|
|
8
|
-
const appInsights = require('applicationinsights');
|
|
9
|
-
appInsights
|
|
10
|
-
.setup() // Set einvironmet variable APPINSIGHTS_INSTRUMENTATIONKEY, so setup() can be called w/o parameters
|
|
11
|
-
.setAutoCollectDependencies(false)
|
|
12
|
-
.setAutoCollectConsole(true, true)
|
|
13
|
-
.setSendLiveMetrics(false)
|
|
14
|
-
.setAutoCollectRequests(false)
|
|
15
|
-
.setAutoCollectPerformance(false)
|
|
16
|
-
.setUseDiskRetryCaching(false)
|
|
17
|
-
.start();
|
|
18
|
-
aiClient = appInsights.defaultClient;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Base class for Event Publisher classes
|
|
23
|
-
* Facilitates registration and configuration
|
|
24
|
-
*/
|
|
25
|
-
class EventPublisherBase {
|
|
26
|
-
/**
|
|
27
|
-
* Create a new insatnce of the @see EventPublisherBase class
|
|
28
|
-
* @param {Object} config Publisher configuration (in platform-specific format)
|
|
29
|
-
*/
|
|
30
|
-
constructor(config) {
|
|
31
|
-
this.config = config;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Validates input data that they can be passed to mapper
|
|
36
|
-
* @param {Object} data Input data to validate
|
|
37
|
-
* @returns {boolean} Validation result
|
|
38
|
-
*/
|
|
39
|
-
validate(data) {
|
|
40
|
-
return true; // Override this method in custom publisher for custom validation
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* Registers a new instance of @see EventPublisherBase -derived class with array of publishers
|
|
45
|
-
* @param {EventPublisher[]} publishers Tha publishers array to register with
|
|
46
|
-
* @param {Object} config Configuration to pass to new instance
|
|
47
|
-
* Call this static method on @see EventPublisherBase -derived class.
|
|
48
|
-
* It will create its instance and pass @param config to its constructor.
|
|
49
|
-
* Than it will add resulting instance of @param publishers.
|
|
50
|
-
*/
|
|
51
|
-
static register(publishers, config) {
|
|
52
|
-
publishers.push(
|
|
53
|
-
new this(
|
|
54
|
-
config,
|
|
55
|
-
) /* Trick: Creates instance of the specific derived class `register` has been called on */,
|
|
56
|
-
);
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
module.exports = {
|
|
61
|
-
EventPublisherBase: EventPublisherBase,
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* Provides access to Application Insights logging (event reporting)
|
|
65
|
-
* @type {appInsights.TelemetryClient|null}
|
|
66
|
-
*/
|
|
67
|
-
appInsights: aiClient || null,
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* Computes SHA-256 hash of a string
|
|
71
|
-
* @param {string} email The vaue to hash
|
|
72
|
-
* @returns {string} @param email SHA-256 hash; returns email if it is 𝑓𝑎𝑙𝑠𝑒 (null, undefined etc.)
|
|
73
|
-
*/
|
|
74
|
-
encodeEmail: function encodeEmail(email) {
|
|
75
|
-
if (!email) {
|
|
76
|
-
return email;
|
|
77
|
-
}
|
|
78
|
-
return crypto
|
|
79
|
-
.createHash('sha256')
|
|
80
|
-
.update(email.toLowerCase(), 'ascii')
|
|
81
|
-
.digest('hex')
|
|
82
|
-
.toLowerCase();
|
|
83
|
-
},
|
|
84
|
-
|
|
85
|
-
/**
|
|
86
|
-
* Handles HTTP response from node-fetch
|
|
87
|
-
* @param {*} response Node-fetch response object
|
|
88
|
-
* @param {string} event for which response is
|
|
89
|
-
* @returns {Object} Deserialized response JSON
|
|
90
|
-
* Throws exception in case of response error code
|
|
91
|
-
*/
|
|
92
|
-
handleResponse: async function handleResponse(response, event) {
|
|
93
|
-
if (!response.ok) {
|
|
94
|
-
throw new Error(
|
|
95
|
-
`HTTP Error code: ${
|
|
96
|
-
response.status
|
|
97
|
-
}, event: ${event}, body: ${await response.text()}`,
|
|
98
|
-
);
|
|
99
|
-
}
|
|
100
|
-
const body = await response.text();
|
|
101
|
-
try {
|
|
102
|
-
return JSON.parse(body);
|
|
103
|
-
} catch (ex) {
|
|
104
|
-
return body;
|
|
105
|
-
}
|
|
106
|
-
},
|
|
107
|
-
|
|
108
|
-
/**
|
|
109
|
-
* Creates a deep copy of given object removing any properties or array items with undefined value
|
|
110
|
-
* @param {*} obj Objec or array to copy. If value is neither array nor object it's returned as passed.
|
|
111
|
-
* @returns Deep copy of @param obj (providing array or object has bee passed in). Any properties or array item with undefined value are skipped when making the copy, recursively. Returns @param obj untouched if neither array nor object has been passed in.
|
|
112
|
-
*/
|
|
113
|
-
removeUndefined: function removeUndefined(obj) {
|
|
114
|
-
let ret;
|
|
115
|
-
if (obj instanceof Array) {
|
|
116
|
-
ret = [];
|
|
117
|
-
for (let i = 0; i < obj.length; i++) {
|
|
118
|
-
if (obj[i] !== undefined) {
|
|
119
|
-
ret.push(removeUndefined(obj[i]));
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
} else if (obj instanceof Object) {
|
|
123
|
-
ret = {};
|
|
124
|
-
for (const prp in obj) {
|
|
125
|
-
if (obj.hasOwnProperty(prp) && obj[prp] !== undefined) {
|
|
126
|
-
ret[prp] = removeUndefined(obj[prp]);
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
} else {
|
|
130
|
-
return obj;
|
|
131
|
-
}
|
|
132
|
-
return ret;
|
|
133
|
-
},
|
|
134
|
-
|
|
135
|
-
/**
|
|
136
|
-
* Validates an object against the schema it states or given schema
|
|
137
|
-
* @param {Object} data An object to validate. The shema must be provided in its `$schema` property if ot passed in @param schema
|
|
138
|
-
* @param {string} schemaSource Name of a folder to look for schemas. Schemas JSON format are looked for in subfolder `customizable/schemas` of given folder.
|
|
139
|
-
* @param {string} schema Full URL id (i.e. URL starting with https://schema.measurementhub.net/), or just relative part of that URL to resolve schem in @param schemaSource`/customizable/schemas`
|
|
140
|
-
* @returns {boolean} Validation result, true if successful, Exception if unsuccessfull
|
|
141
|
-
*/
|
|
142
|
-
validate: function validate(data, schemaSource, schema = null) {
|
|
143
|
-
schema = schema || data.$schema;
|
|
144
|
-
if (!schema) {
|
|
145
|
-
throw "Data doesn't have schema and schema not passed";
|
|
146
|
-
}
|
|
147
|
-
if (
|
|
148
|
-
!schema.startsWith('https://schema.measurementhub.net/') &&
|
|
149
|
-
(schema.startsWith('http://') || schema.startsWith('https://'))
|
|
150
|
-
) {
|
|
151
|
-
throw `Schema ${data.$schema} is not supported, only https://schema.measurementhub.net/... and schemas identified by relative URL shemas are supported`;
|
|
152
|
-
}
|
|
153
|
-
let parts = schema.split('/');
|
|
154
|
-
if (parts.includes('..')) {
|
|
155
|
-
// Directory traversal attack protection
|
|
156
|
-
throw `It's invalid for schema URI to contain '..' segment, such as in ${schema}`;
|
|
157
|
-
}
|
|
158
|
-
if (schema.startsWith('http://') || schema.startsWith('https://')) {
|
|
159
|
-
parts = parts.slice(3);
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
const schemaLocation = `${schemaSource}/customizable/schemas/${parts.join(
|
|
163
|
-
'/',
|
|
164
|
-
)}.json`;
|
|
165
|
-
if (!fs.existsSync(schemaLocation)) {
|
|
166
|
-
throw `Schema file ${schemaLocation} not found`;
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
let schemaStr;
|
|
170
|
-
try {
|
|
171
|
-
schemaStr = fs.readFileSync(schemaLocation).toString();
|
|
172
|
-
} catch (ex) {
|
|
173
|
-
throw `Failed to load schema ${schema}`;
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
let schemaObj;
|
|
177
|
-
try {
|
|
178
|
-
schemaObj = JSON.parse(schemaStr);
|
|
179
|
-
} catch (ex) {
|
|
180
|
-
throw `Failed to deserialize ${schema}`;
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
const ajv = new Ajv({ allErrors: true });
|
|
184
|
-
let validate;
|
|
185
|
-
try {
|
|
186
|
-
validate = ajv.compile(schemaObj);
|
|
187
|
-
} catch (ex) {
|
|
188
|
-
throw `Failed to compile schema ${schema}`;
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
const valid = validate(data);
|
|
192
|
-
if (!valid) {
|
|
193
|
-
throw `Schema vaidation failed for schema ${schema}, ${
|
|
194
|
-
validate.errors.length
|
|
195
|
-
} errors: ${JSON.stringify(validate.errors)}`;
|
|
196
|
-
}
|
|
197
|
-
return true;
|
|
198
|
-
},
|
|
199
|
-
|
|
200
|
-
/**
|
|
201
|
-
* Enhances header before sending test request to secondary target (like Pipedream)
|
|
202
|
-
* @param {Object} headers Request header dictionary. This contains the original headers and will be ehnanced.
|
|
203
|
-
* @param {string} origUrl Original URL the request has been sent to
|
|
204
|
-
* @param {*} origRequest The entire original request options
|
|
205
|
-
* @param {*} origResponse Response recievend from original request
|
|
206
|
-
*/
|
|
207
|
-
prepareTestRequestHeaders: function prepareTestRequestHeaders(
|
|
208
|
-
headers,
|
|
209
|
-
origUrl,
|
|
210
|
-
origRequest,
|
|
211
|
-
origResponse,
|
|
212
|
-
) {
|
|
213
|
-
headers['x-mhub-orig-url'] = origUrl;
|
|
214
|
-
headers['x-mhub-orig-method'] = origRequest.method;
|
|
215
|
-
headers['x-mhub-orig-response-status-code'] = origResponse.status;
|
|
216
|
-
headers['x-mhub-orig-response-status-message'] = origResponse.statusText;
|
|
217
|
-
},
|
|
218
|
-
|
|
219
|
-
/**
|
|
220
|
-
* Extracts ad code from standardly structured event data (in legacy or new format)
|
|
221
|
-
* @param {{ads:(LegacyAd|Ad)[]}} data Event data to extract ad code from. As you can see the `ads` field is accepted in 2 formats the first being legacy and the later being new one.
|
|
222
|
-
* @param {string} adPlatform value of `data.ads.adPlatform` field to filter ad codes by platform (this is for new style data; ignored for legacy data)
|
|
223
|
-
* @param {string} adCode value of `data.ads.adType` field to filter items in `data.ads` by (this is for legacy style data); als used for new style data to identify the main parameter from `data.ads.adCodes` to obtain
|
|
224
|
-
* @param {(code: AdCodeInfo, ad: LegacyAd|Ad) => string|any} format If this custom function is provided it forats the code returned, so the function does not return object but string formated by this function. But nothing prevents it from returning object if the consumer can hanlde it.
|
|
225
|
-
* @returns {AdCodeInfo|string|null|any} Ad code and time when it was recorded of newest event (by `visitAt`) with given ad code from @param data.ads; when @param format is provided returns string result of that function.
|
|
226
|
-
*/
|
|
227
|
-
extractAdCode: function extractAdCode(
|
|
228
|
-
data,
|
|
229
|
-
adPlatform,
|
|
230
|
-
adCode,
|
|
231
|
-
format = null,
|
|
232
|
-
) {
|
|
233
|
-
const ad = data.ads
|
|
234
|
-
.filter(
|
|
235
|
-
(x) =>
|
|
236
|
-
x.adType === adCode /* legacy*/ ||
|
|
237
|
-
x.adPlatform === adPlatform /* new*/,
|
|
238
|
-
)
|
|
239
|
-
.sort((a, b) => b.visitAt - a.visitAt)[0];
|
|
240
|
-
const code =
|
|
241
|
-
ad?.adCode /* legacy*/ || (ad?.adCodes ? ad.adCodes[adCode] : null);
|
|
242
|
-
if (code) {
|
|
243
|
-
const ret = { code: code, visitAt: ad.visitAt };
|
|
244
|
-
if (format) {
|
|
245
|
-
return format(ret, ad);
|
|
246
|
-
}
|
|
247
|
-
return ret;
|
|
248
|
-
}
|
|
249
|
-
return null;
|
|
250
|
-
},
|
|
251
|
-
|
|
252
|
-
/**
|
|
253
|
-
* Logs message to Azure Function context and to Application Insights (if configured)
|
|
254
|
-
* @param {FunctionContext} log Azure Function context.log.warn
|
|
255
|
-
* @param {0|1|2|3|4} level Application Insights log level according to https://docs.microsoft.com/en-us/dotnet/api/microsoft.applicationinsights.datacontracts.severitylevel?view=azure-dotnet
|
|
256
|
-
* @param {string} message The message to log
|
|
257
|
-
* @param {Object} properties Properties to pass to Application Insights trace
|
|
258
|
-
*/
|
|
259
|
-
log2: function log2(log, level, message, properties) {
|
|
260
|
-
log(message);
|
|
261
|
-
aiClient?.trackTrace({
|
|
262
|
-
message: message,
|
|
263
|
-
severityLevel: level,
|
|
264
|
-
properties: properties,
|
|
265
|
-
});
|
|
266
|
-
},
|
|
267
|
-
|
|
268
|
-
/**
|
|
269
|
-
* Logs exception to Azure Function context and to Application Insights (if configured)
|
|
270
|
-
* @param {FunctionContext} log Azure Function context.log.warn
|
|
271
|
-
* @param {object} exception
|
|
272
|
-
*/
|
|
273
|
-
logException: function logException(log, exception) {
|
|
274
|
-
log(exception);
|
|
275
|
-
aiClient?.trackException({ exception: exception });
|
|
276
|
-
// raise exception if it is running under mocha test
|
|
277
|
-
if (typeof global.it === 'function') {
|
|
278
|
-
throw exception;
|
|
279
|
-
}
|
|
280
|
-
},
|
|
281
|
-
|
|
282
|
-
/**
|
|
283
|
-
* For http request. This function is for edge cases. Use Fetch if possible.
|
|
284
|
-
* @param {object} params (hostname, port, path, method)
|
|
285
|
-
* @param {object} postData
|
|
286
|
-
* @returns
|
|
287
|
-
*/
|
|
288
|
-
httpRequest: function httpRequest(params, postData) {
|
|
289
|
-
return new Promise(function (resolve, reject) {
|
|
290
|
-
var req = https.request(params, function (res) {
|
|
291
|
-
// reject on bad status
|
|
292
|
-
if (res.statusCode < 200 || res.statusCode >= 300) {
|
|
293
|
-
return reject(new Error('statusCode=' + res.statusCode));
|
|
294
|
-
}
|
|
295
|
-
// cumulate data
|
|
296
|
-
var body = [];
|
|
297
|
-
res.on('data', function (chunk) {
|
|
298
|
-
body.push(chunk);
|
|
299
|
-
});
|
|
300
|
-
// resolve on end
|
|
301
|
-
res.on('end', function () {
|
|
302
|
-
try {
|
|
303
|
-
if (body.length > 0) {
|
|
304
|
-
body = JSON.parse(Buffer.concat(body).toString());
|
|
305
|
-
}
|
|
306
|
-
} catch (e) {
|
|
307
|
-
reject(e);
|
|
308
|
-
}
|
|
309
|
-
resolve(body);
|
|
310
|
-
});
|
|
311
|
-
});
|
|
312
|
-
// reject on request error
|
|
313
|
-
req.on('error', function (err) {
|
|
314
|
-
// This is not a "Second reject", just a different sort of failure
|
|
315
|
-
reject(err);
|
|
316
|
-
});
|
|
317
|
-
if (postData) {
|
|
318
|
-
req.write(postData);
|
|
319
|
-
}
|
|
320
|
-
// IMPORTANT
|
|
321
|
-
req.end();
|
|
322
|
-
});
|
|
323
|
-
},
|
|
324
|
-
|
|
325
|
-
/**
|
|
326
|
-
* Transforms an object to be flat, for instance for GA4
|
|
327
|
-
* @param {object} event Event that is received
|
|
328
|
-
* @param {sring} separator Separator that will be used to unnest the structure. The default separator is underscore _
|
|
329
|
-
* @returns
|
|
330
|
-
*/
|
|
331
|
-
flatten: function flatten(event, separator) {
|
|
332
|
-
return Object.assign(
|
|
333
|
-
{},
|
|
334
|
-
...(function _flatten(o, separator = '_', parent) {
|
|
335
|
-
return [].concat(
|
|
336
|
-
...Object.keys(o).map((key) => {
|
|
337
|
-
if (typeof o[key] === 'object' && o[key] !== null) {
|
|
338
|
-
const newParent = parent ? parent + separator + key : key;
|
|
339
|
-
return _flatten(o[key], separator, newParent);
|
|
340
|
-
} else {
|
|
341
|
-
const newKey = parent ? parent + separator + key : key;
|
|
342
|
-
return { [newKey]: o[key] };
|
|
343
|
-
}
|
|
344
|
-
}),
|
|
345
|
-
);
|
|
346
|
-
})(event, separator),
|
|
347
|
-
);
|
|
348
|
-
},
|
|
349
|
-
};
|
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
const fetch = require('node-fetch');
|
|
2
|
-
const utils = require('../lib/utils');
|
|
3
|
-
const SOURCE = 'f_AffiliatePort';
|
|
4
|
-
|
|
5
|
-
module.exports = {
|
|
6
|
-
/**
|
|
7
|
-
* Processed data comming from EventHub to data for further processing
|
|
8
|
-
* @param {Object} data The data comming from EventHub
|
|
9
|
-
* @returns {Object} Data for further processing
|
|
10
|
-
*/
|
|
11
|
-
parse: function parse(data, context) {
|
|
12
|
-
// ConsumerBase.cs:ConsumeOneEventAsync
|
|
13
|
-
data.enqueuedAt = context.test ? 1600000000000 : Date.now();
|
|
14
|
-
return data;
|
|
15
|
-
},
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Publishes data to AffiliatePort
|
|
19
|
-
* @param {{id: string, access_token: string}} config Publisher configuration
|
|
20
|
-
* @param {Object} data Data in publisher-friendly format to be published
|
|
21
|
-
* @param {string} event for which is it triggered
|
|
22
|
-
*/
|
|
23
|
-
publish: async function publish(log, config, data, event) {
|
|
24
|
-
data = utils.removeUndefined(data);
|
|
25
|
-
const requestOptions: PlatformRequestOptions = {
|
|
26
|
-
method: 'GET',
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
for (let product of data.products) {
|
|
30
|
-
// https://tracking.affiliateclub.cz/aff_lsr?offer_id=OFFER_ID&adv_sub=TID_SUB_ID&amount=AMOUNT&transaction_id=TRANSACTION_ID&adv_sub2=CATEGORY&adv_sub3=MASTER_TYPE
|
|
31
|
-
const url =
|
|
32
|
-
'https://tracking.affiliateclub.cz/aff_lsr?offer_id=' +
|
|
33
|
-
encodeURIComponent(config.offerId) +
|
|
34
|
-
'&adv_sub=TID_' +
|
|
35
|
-
data.orderId +
|
|
36
|
-
'&amount=' +
|
|
37
|
-
product.quantity * product.price +
|
|
38
|
-
'&transaction_id=' +
|
|
39
|
-
data.transactionID +
|
|
40
|
-
'&adv_sub2=' +
|
|
41
|
-
product.category +
|
|
42
|
-
'&adv_sub3=' +
|
|
43
|
-
product.masterType;
|
|
44
|
-
|
|
45
|
-
const resp = await fetch(url, reqOpts);
|
|
46
|
-
|
|
47
|
-
if (process.env.PUBLISHER_TESTURL) {
|
|
48
|
-
try {
|
|
49
|
-
utils.prepareTestRequestHeaders(reqOpts.headers, url, reqOpts, resp);
|
|
50
|
-
await fetch(process.env.PUBLISHER_TESTURL + query, reqOpts);
|
|
51
|
-
} catch {}
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
await utils.handleResponse(resp, event);
|
|
55
|
-
|
|
56
|
-
log(`AffiliatePort - ${event} - sent`);
|
|
57
|
-
}
|
|
58
|
-
},
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* Validates an object against given schema
|
|
62
|
-
* @param {Object} data An object to validate.
|
|
63
|
-
* @param {string} schema Name of the schema. That's name of a file with `.schema.json` extension in `customizable/schemas` subfolder of current publisher folder
|
|
64
|
-
* @returns {boolean} Validation result, true if successful, false if unsuccessfull (in which case more info is written to console)
|
|
65
|
-
*/
|
|
66
|
-
validate: function validate(data, schema) {
|
|
67
|
-
if (!schema) {
|
|
68
|
-
throw new Error('Schema parameters not provided');
|
|
69
|
-
}
|
|
70
|
-
if (schema.includes('/')) {
|
|
71
|
-
throw new Error(
|
|
72
|
-
'Schema must be provided as schema name, not schema path',
|
|
73
|
-
);
|
|
74
|
-
}
|
|
75
|
-
// More validation done by utils.validate
|
|
76
|
-
return utils.validate(data, SOURCE, schema);
|
|
77
|
-
},
|
|
78
|
-
};
|
package/js/publishers/CJ.js
DELETED
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
const fetch = require('node-fetch');
|
|
2
|
-
const utils = require("../lib/utils");
|
|
3
|
-
const SOURCE = "f_CJAffiliate";
|
|
4
|
-
|
|
5
|
-
module.exports = {
|
|
6
|
-
/**
|
|
7
|
-
* Processed data comming from EventHub to data for further processing
|
|
8
|
-
* @param {Object} data The data comming from EventHub
|
|
9
|
-
* @param {FunctionContext} test Azure Function context.test
|
|
10
|
-
* @returns {Object} Data for further processing
|
|
11
|
-
*/
|
|
12
|
-
parse: function parse(data, test) {
|
|
13
|
-
//ConsumerBase.cs:ConsumeOneEventAsync
|
|
14
|
-
data.enqueuedAt = test ? 1600000000000 : Date.now();
|
|
15
|
-
return data;
|
|
16
|
-
},
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Publishes data to Facebook
|
|
20
|
-
* @param {FunctionContext} log Azure Function context.log.warn
|
|
21
|
-
* @param {{cid: string|number, type: string|number}} config Publisher configuration
|
|
22
|
-
* @param {Object} data Data in publisher-friendly format to be published
|
|
23
|
-
* @returns {*} Data returned by platform, if possible JSON-deserialized (otherwise as string)
|
|
24
|
-
* @param {string} event for which is it triggered
|
|
25
|
-
*/
|
|
26
|
-
publish: async function publish(log, config, data, event) {
|
|
27
|
-
if(!data.cjevent){
|
|
28
|
-
log(`CJ - ${event} - skipped because CJEVENT is missing`);
|
|
29
|
-
return false;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
data = utils.removeUndefined(data);
|
|
33
|
-
const baseUrl = "https://www.kdukvh.com/u";
|
|
34
|
-
let dt = "?cid=" + encodeURI(config.cid);
|
|
35
|
-
dt += "&type=" + encodeURI(config.type);
|
|
36
|
-
for (let prp in data) {
|
|
37
|
-
if (data.hasOwnProperty(prp) && data[prp] !== undefined) {
|
|
38
|
-
dt += "&" + encodeURI(prp) + "=" + encodeURI(data[prp] === null ? "" : data[prp].toString());
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
const reqOpts = { method: "get", headers: {} /*Needed by test call*/ };
|
|
42
|
-
const resp = await fetch(baseUrl + dt, reqOpts);
|
|
43
|
-
|
|
44
|
-
if (process.env.PUBLISHER_TESTURL) {
|
|
45
|
-
try {
|
|
46
|
-
utils.prepareTestRequestHeaders(reqOpts.headers, baseUrl + dt, reqOpts, resp);
|
|
47
|
-
await fetch(process.env.PUBLISHER_TESTURL + dt, reqOpts);
|
|
48
|
-
} catch { }
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
await utils.handleResponse(resp, event);
|
|
52
|
-
|
|
53
|
-
log(`CJ - ${event} - sent`);
|
|
54
|
-
},
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* Validates an object against given schema
|
|
58
|
-
* @param {Object} data An object to validate.
|
|
59
|
-
* @param {string} schema Name of the schema. That's name of a file with `.schema.json` extension in `customizable/schemas` subfolder of current publisher folder
|
|
60
|
-
* @returns {boolean} Validation result, true if successful, false if unsuccessfull (in which case more info is written to console)
|
|
61
|
-
*/
|
|
62
|
-
validate: function validate(data, schema) {
|
|
63
|
-
if (!schema) throw new Error("Schema parameters not provided");
|
|
64
|
-
if (schema.indexOf("/") >= 0) throw new Error("Schema must be provided as schema name, not schema path");
|
|
65
|
-
//More validation done by utils.validate
|
|
66
|
-
return utils.validate(data, SOURCE, schema);
|
|
67
|
-
}
|
|
68
|
-
};
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
const fetch = require('node-fetch');
|
|
2
|
-
const utils = require("../lib/utils");
|
|
3
|
-
const SOURCE = "f_Facebook";
|
|
4
|
-
|
|
5
|
-
module.exports = {
|
|
6
|
-
/**
|
|
7
|
-
* Processed data comming from EventHub to data for further processing
|
|
8
|
-
* @param {Object} data The data comming from EventHub
|
|
9
|
-
* @param {FunctionContext} test Azure Function context.test
|
|
10
|
-
* @returns {Object} Data for further processing
|
|
11
|
-
*/
|
|
12
|
-
parse: function parse(data, test) {
|
|
13
|
-
//ConsumerBase.cs:ConsumeOneEventAsync
|
|
14
|
-
data.enqueuedAt = test ? 1600000000000 : Date.now();
|
|
15
|
-
return data;
|
|
16
|
-
},
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Publishes data to Facebook
|
|
20
|
-
* @param {FunctionContext} log Azure Function context.log.warn
|
|
21
|
-
* @param {{id: string, access_token: string}} config Publisher configuration
|
|
22
|
-
* @param {Object} data Data in publisher-friendly format to be published
|
|
23
|
-
* @param {string} event for which is it triggered
|
|
24
|
-
*/
|
|
25
|
-
publish: async function publish(log, config, data, event) {
|
|
26
|
-
data = utils.removeUndefined(data);
|
|
27
|
-
const reqOpts = {
|
|
28
|
-
method: "post",
|
|
29
|
-
body: JSON.stringify({ data: [data] }),
|
|
30
|
-
headers: {
|
|
31
|
-
'Content-Type': 'application/json'
|
|
32
|
-
}
|
|
33
|
-
};
|
|
34
|
-
//https://graph.facebook.com/v11.0/<id>/events
|
|
35
|
-
const baseUrl = "https://graph.facebook.com/v11.0/" + encodeURIComponent(config.id) + "/events";
|
|
36
|
-
const query = "?access_token=" + encodeURI(config.access_token);
|
|
37
|
-
const url = baseUrl + query;
|
|
38
|
-
const resp = await fetch(url, reqOpts);
|
|
39
|
-
|
|
40
|
-
if (process.env.PUBLISHER_TESTURL) {
|
|
41
|
-
try {
|
|
42
|
-
utils.prepareTestRequestHeaders(reqOpts.headers, url, reqOpts, resp);
|
|
43
|
-
await fetch(process.env.PUBLISHER_TESTURL + query, reqOpts);
|
|
44
|
-
} catch { }
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
await utils.handleResponse(resp, event);
|
|
48
|
-
|
|
49
|
-
log(`Facebook - ${event} - sent`);
|
|
50
|
-
},
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* Validates an object against given schema
|
|
54
|
-
* @param {Object} data An object to validate.
|
|
55
|
-
* @param {string} schema Name of the schema. That's name of a file with `.schema.json` extension in `customizable/schemas` subfolder of current publisher folder
|
|
56
|
-
* @returns {boolean} Validation result, true if successful, false if unsuccessfull (in which case more info is written to console)
|
|
57
|
-
*/
|
|
58
|
-
validate: function validate(data, schema) {
|
|
59
|
-
if (!schema) throw new Error("Schema parameters not provided");
|
|
60
|
-
if (schema.indexOf("/") >= 0) throw new Error("Schema must be provided as schema name, not schema path");
|
|
61
|
-
//More validation done by utils.validate
|
|
62
|
-
return utils.validate(data, SOURCE, schema);
|
|
63
|
-
}
|
|
64
|
-
};
|
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
const fetch = require('node-fetch');
|
|
2
|
-
const utils = require("../lib/utils");
|
|
3
|
-
const SOURCE = "f_GoogleAnalytics4";
|
|
4
|
-
|
|
5
|
-
//https://cloud.google.com/appengine/docs/standard/php7/integrating-with-analytics#server-side_analytics_collection
|
|
6
|
-
|
|
7
|
-
module.exports = {
|
|
8
|
-
/**
|
|
9
|
-
* Processed data comming from EventHub to data for further processing
|
|
10
|
-
* @param {Object} data The data comming from EventHub
|
|
11
|
-
* @param {FunctionContext} test Azure Function context.test
|
|
12
|
-
* @returns {Object} Data for further processing
|
|
13
|
-
*/
|
|
14
|
-
parse: function parse(data, test) {
|
|
15
|
-
//ConsumerBase.cs:ConsumeOneEventAsync
|
|
16
|
-
data.enqueuedAt = test ? 1600000000000 : Date.now();
|
|
17
|
-
return data;
|
|
18
|
-
},
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Publishes data to Google Analytics
|
|
22
|
-
* @param {FunctionContext} log Azure Function context.log.warn
|
|
23
|
-
* @param {{tid: string}} config Publisher configuration
|
|
24
|
-
* @param {{action: string, ti: string, [key:string]: string|number|boolean}} data Data in publisher-friendly format to be published
|
|
25
|
-
*/
|
|
26
|
-
publish: async function publish(log, config, data, event) {
|
|
27
|
-
data = utils.removeUndefined(data);
|
|
28
|
-
data.v = 2;
|
|
29
|
-
data.seg = 1;
|
|
30
|
-
data.gcs = 111;
|
|
31
|
-
data.tid = config.trackingId;
|
|
32
|
-
|
|
33
|
-
let payload = "";
|
|
34
|
-
|
|
35
|
-
for (const prp in data) {
|
|
36
|
-
if (data.hasOwnProperty(prp)) {
|
|
37
|
-
if (payload) payload += "&";
|
|
38
|
-
payload += encodeURI(prp) + "=" + encodeURI(data[prp]);
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
var reqOpts = {
|
|
43
|
-
hostname: 'www.google-analytics.com',
|
|
44
|
-
port: 443,
|
|
45
|
-
path: '/g/collect?' + payload,
|
|
46
|
-
method: 'POST'
|
|
47
|
-
};
|
|
48
|
-
|
|
49
|
-
await utils.httpRequest(reqOpts);
|
|
50
|
-
|
|
51
|
-
if (process.env.PUBLISHER_TESTURL) {
|
|
52
|
-
try {
|
|
53
|
-
reqOpts.headers = {};
|
|
54
|
-
utils.prepareTestRequestHeaders(reqOpts.headers, reqOpts.hostname + reqOpts.path , reqOpts);
|
|
55
|
-
await fetch(process.env.PUBLISHER_TESTURL, reqOpts);
|
|
56
|
-
} catch(exception) {
|
|
57
|
-
warn(exception);
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
log(`GoogleAnalytics4 - ${event} - sent`);
|
|
62
|
-
},
|
|
63
|
-
|
|
64
|
-
/**
|
|
65
|
-
* Validates an object against given schema
|
|
66
|
-
* @param {Object} data An object to validate.
|
|
67
|
-
* @param {string} schema Name of the schema. That's name of a file with `.schema.json` extension in `customizable/schemas` subfolder of current publisher folder
|
|
68
|
-
* @returns {boolean} Validation result, true if successful, false if unsuccessfull (in which case more info is written to console)
|
|
69
|
-
*/
|
|
70
|
-
validate: function validate(data, schema) {
|
|
71
|
-
if (!schema) throw new Error("Schema parameters not provided");
|
|
72
|
-
if (schema.indexOf("/") >= 0) throw new Error("Schema must be provided as schema name, not schema path");
|
|
73
|
-
//More validation done by utils.validate
|
|
74
|
-
return utils.validate(data, SOURCE, schema);
|
|
75
|
-
}
|
|
76
|
-
};
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
const fetch = require('node-fetch');
|
|
2
|
-
const utils = require("../lib/utils");
|
|
3
|
-
const SOURCE = "f_HttpPublisher";
|
|
4
|
-
|
|
5
|
-
module.exports = {
|
|
6
|
-
/**
|
|
7
|
-
* Processed data comming from EventHub to data for further processing
|
|
8
|
-
* @param {Object} data The data comming from EventHub
|
|
9
|
-
* @param {FunctionContext} test Azure Function context.test
|
|
10
|
-
* @returns {Object} Data for further processing
|
|
11
|
-
*/
|
|
12
|
-
parse: function parse(data, test) {
|
|
13
|
-
//ConsumerBase.cs:ConsumeOneEventAsync
|
|
14
|
-
data.enqueuedAt = test ? 1600000000000 : Date.now();
|
|
15
|
-
return data;
|
|
16
|
-
},
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Publishes data to provided URL
|
|
20
|
-
* @param {FunctionContext} log Azure Function context.log.warn
|
|
21
|
-
* @param {string} event Required: event for which is it triggered
|
|
22
|
-
* @param {string} url Required: Request URL with query parameters
|
|
23
|
-
* @param {string} platform Required: Name of the plaform to which request is sent
|
|
24
|
-
* @param {string} method Required: Request method - GET|POST|PUT...
|
|
25
|
-
* @param {Object} headers Optional: Object of request headers
|
|
26
|
-
* @param {Object} body Optional: Non-strigifed request body object
|
|
27
|
-
*
|
|
28
|
-
*/
|
|
29
|
-
publish: async function publish(log, event, platform, url, method, headers = {}, body = {}) {
|
|
30
|
-
const reqOpts = {
|
|
31
|
-
method: method,
|
|
32
|
-
headers: headers
|
|
33
|
-
};
|
|
34
|
-
if(method == "POST"){
|
|
35
|
-
reqOpts.body = JSON.stringify(body);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
const resp = await fetch(url, reqOpts);
|
|
39
|
-
|
|
40
|
-
if (process.env.PUBLISHER_TESTURL) {
|
|
41
|
-
try {
|
|
42
|
-
utils.prepareTestRequestHeaders(reqOpts.headers, url, reqOpts, resp);
|
|
43
|
-
await fetch(process.env.PUBLISHER_TESTURL, reqOpts);
|
|
44
|
-
} catch { }
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
await utils.handleResponse(resp, event);
|
|
48
|
-
|
|
49
|
-
log(`${platform} - ${event} - sent`);
|
|
50
|
-
},
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* Validates an object against given schema
|
|
54
|
-
* @param {Object} data An object to validate.
|
|
55
|
-
* @param {string} schema Name of the schema. That's name of a file with `.schema.json` extension in `customizable/schemas` subfolder of current publisher folder
|
|
56
|
-
* @returns {boolean} Validation result, true if successful, false if unsuccessfull (in which case more info is written to console)
|
|
57
|
-
*/
|
|
58
|
-
validate: function validate(data, schema) {
|
|
59
|
-
if (!schema) throw new Error("Schema parameters not provided");
|
|
60
|
-
if (schema.indexOf("/") >= 0) throw new Error("Schema must be provided as schema name, not schema path");
|
|
61
|
-
//More validation done by utils.validate
|
|
62
|
-
return utils.validate(data, SOURCE, schema);
|
|
63
|
-
}
|
|
64
|
-
};
|
package/js/publishers/Piano.js
DELETED
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
const utils = require("../lib/utils");
|
|
2
|
-
const fetch = require('node-fetch');
|
|
3
|
-
const SOURCE = "f_Piano";
|
|
4
|
-
|
|
5
|
-
module.exports = {
|
|
6
|
-
/**
|
|
7
|
-
* Processed data comming from EventHub to data for further processing
|
|
8
|
-
* @param {Object} data The data comming from EventHub
|
|
9
|
-
* @param {FunctionContext} test Azure Function context.test
|
|
10
|
-
* @returns {Object} Data for further processing
|
|
11
|
-
*/
|
|
12
|
-
parse: function parse(data, test) {
|
|
13
|
-
//ConsumerBase.cs:ConsumeOneEventAsync
|
|
14
|
-
data.enqueuedAt = test ? 1600000000000 : Date.now();
|
|
15
|
-
return data;
|
|
16
|
-
},
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Publishes data to Piano
|
|
20
|
-
* @param {FunctionContext} log Azure Function context.log.warn
|
|
21
|
-
* @param {{collectionDomain: string, siteId: string|number}} config Publisher configuration
|
|
22
|
-
* @param {{pianoData: {events: {name: string, data: {[key: string]: any}}[]}, aux: {visitorId: string, ref: string, userAgent?: string, referer?: string, forwardedFor?: string}}} data Data in publisher-friendly format to be published
|
|
23
|
-
* @returns {*} Data returned by platform, if possible JSON-deserialized (otherwise as string)
|
|
24
|
-
* @param {string} event for which is it triggered
|
|
25
|
-
*/
|
|
26
|
-
publish: async function publish(log, config, data, event) {
|
|
27
|
-
data = utils.removeUndefined(data);
|
|
28
|
-
let dt = "";
|
|
29
|
-
//https://developers.atinternet-solutions.com/piano-analytics-tagging-en/event-tagging-piano-analytics-en/events-pattern-en/#post-request_5
|
|
30
|
-
//https://<collection-domain>/<path>?s=<site-id>&idclient=<visitor-id>&ref=<previous-url>
|
|
31
|
-
dt = "?s=" + encodeURI(config.siteId);
|
|
32
|
-
dt += "&idclient=" + encodeURI(data.aux.visitorId);
|
|
33
|
-
dt += "&ref=" + encodeURI(data.aux.ref);
|
|
34
|
-
|
|
35
|
-
const reqOpts = { method: "post", headers: {} /*Needed by test call*/, body: JSON.stringify(data.pianoData) };
|
|
36
|
-
if (data.aux.userAgent)
|
|
37
|
-
reqOpts.headers["User-Agent"] = data.aux.userAgent;
|
|
38
|
-
if (data.aux.referer)
|
|
39
|
-
reqOpts.headers["Referer"] = data.aux.referer;
|
|
40
|
-
if (data.aux.forwardedFor)
|
|
41
|
-
reqOpts.headers["X-Forwarded-For"] = data.aux.forwardedFor;
|
|
42
|
-
const resp = await fetch("https://" + config.collectionDomain + "/" + dt, reqOpts);
|
|
43
|
-
|
|
44
|
-
if (process.env.PUBLISHER_TESTURL) {
|
|
45
|
-
try {
|
|
46
|
-
utils.prepareTestRequestHeaders(reqOpts.headers, config.collectionDomain + dt, reqOpts, resp);
|
|
47
|
-
await fetch(process.env.PUBLISHER_TESTURL + dt, reqOpts);
|
|
48
|
-
} catch { }
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
await utils.handleResponse(resp, event);
|
|
52
|
-
|
|
53
|
-
log(`Piano Analytics - ${event} - sent`);
|
|
54
|
-
},
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* Validates an object against given schema
|
|
58
|
-
* @param {Object} data An object to validate.
|
|
59
|
-
* @param {string} schema Name of the schema. That's name of a file with `.schema.json` extension in `customizable/schemas` subfolder of current publisher folder
|
|
60
|
-
* @returns {boolean} Validation result, true if successful, false if unsuccessfull (in which case more info is written to console)
|
|
61
|
-
*/
|
|
62
|
-
validate: function validate(data, schema) {
|
|
63
|
-
if (!schema) throw new Error("Schema parameters not provided");
|
|
64
|
-
if (schema.indexOf("/") >= 0) throw new Error("Schema must be provided as schema name, not schema path");
|
|
65
|
-
//More validation done by utils.validate
|
|
66
|
-
return utils.validate(data, SOURCE, schema);
|
|
67
|
-
}
|
|
68
|
-
};
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
const fetch = require('node-fetch');
|
|
2
|
-
const utils = require("../lib/utils");
|
|
3
|
-
const SOURCE = "f_UniversalAnalytics";
|
|
4
|
-
|
|
5
|
-
//https://cloud.google.com/appengine/docs/standard/php7/integrating-with-analytics#server-side_analytics_collection
|
|
6
|
-
|
|
7
|
-
module.exports = {
|
|
8
|
-
/**
|
|
9
|
-
* Processed data comming from EventHub to data for further processing
|
|
10
|
-
* @param {Object} data The data comming from EventHub
|
|
11
|
-
* @param {FunctionContext} test Azure Function context.test
|
|
12
|
-
* @returns {Object} Data for further processing
|
|
13
|
-
*/
|
|
14
|
-
parse: function parse(data, test) {
|
|
15
|
-
//ConsumerBase.cs:ConsumeOneEventAsync
|
|
16
|
-
data.enqueuedAt = test ? 1600000000000 : Date.now();
|
|
17
|
-
return data;
|
|
18
|
-
},
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Publishes data to Google Analytics
|
|
22
|
-
* @param {FunctionContext} log Azure Function context.log.warn
|
|
23
|
-
* @param {{tid: string}} config Publisher configuration
|
|
24
|
-
* @param {{action: string, ti: string, [key:string]: string|number|boolean}} data Data in publisher-friendly format to be published
|
|
25
|
-
*/
|
|
26
|
-
publish: async function publish(log, config, data, event) {
|
|
27
|
-
data = utils.removeUndefined(data);
|
|
28
|
-
//https://developers.google.com/analytics/devguides/collection/protocol/v1/devguide#event
|
|
29
|
-
const url = "https://www.google-analytics.com/collect";
|
|
30
|
-
data.v = 1;
|
|
31
|
-
data.tid = config.trackingId;
|
|
32
|
-
let payload = "";
|
|
33
|
-
|
|
34
|
-
for (const prp in data) {
|
|
35
|
-
if (data.hasOwnProperty(prp)) {
|
|
36
|
-
if (payload) payload += "&";
|
|
37
|
-
payload += encodeURI(prp) + "=" + encodeURI(data[prp]);
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
const reqOpts = {
|
|
42
|
-
method: "post",
|
|
43
|
-
body: payload,
|
|
44
|
-
headers: {
|
|
45
|
-
'Content-Type': 'application/x-www-form-urlencoded'
|
|
46
|
-
}
|
|
47
|
-
};
|
|
48
|
-
|
|
49
|
-
const resp = await fetch(url, reqOpts);
|
|
50
|
-
|
|
51
|
-
if (process.env.PUBLISHER_TESTURL) {
|
|
52
|
-
try {
|
|
53
|
-
utils.prepareTestRequestHeaders(reqOpts.headers, url, reqOpts, resp);
|
|
54
|
-
await fetch(process.env.PUBLISHER_TESTURL, reqOpts);
|
|
55
|
-
} catch { }
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
await utils.handleResponse(resp);
|
|
59
|
-
|
|
60
|
-
log(`Universal Analytics - ${event} - sent`);
|
|
61
|
-
},
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* Validates an object against given schema
|
|
65
|
-
* @param {Object} data An object to validate.
|
|
66
|
-
* @param {string} schema Name of the schema. That's name of a file with `.schema.json` extension in `customizable/schemas` subfolder of current publisher folder
|
|
67
|
-
* @returns {boolean} Validation result, true if successful, false if unsuccessfull (in which case more info is written to console)
|
|
68
|
-
*/
|
|
69
|
-
validate: function validate(data, schema) {
|
|
70
|
-
if (!schema) throw new Error("Schema parameters not provided");
|
|
71
|
-
if (schema.indexOf("/") >= 0) throw new Error("Schema must be provided as schema name, not schema path");
|
|
72
|
-
//More validation done by utils.validate
|
|
73
|
-
return utils.validate(data, SOURCE, schema);
|
|
74
|
-
}
|
|
75
|
-
};
|