@mhubcloud/tms_core 2.0.0-beta.0 → 2.0.0-beta.1

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.
Files changed (2) hide show
  1. package/dist/index.js +609 -0
  2. package/package.json +2 -2
package/dist/index.js ADDED
@@ -0,0 +1,609 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/index.ts
31
+ var src_exports = {};
32
+ __export(src_exports, {
33
+ DefaultPublisher: () => defaultPublisher,
34
+ publisher: () => publisher,
35
+ utils: () => utils_exports
36
+ });
37
+ module.exports = __toCommonJS(src_exports);
38
+
39
+ // src/utils/utils.ts
40
+ var utils_exports = {};
41
+ __export(utils_exports, {
42
+ EventPublisherBase: () => EventPublisherBase,
43
+ encodeEmail: () => encodeEmail,
44
+ extractAdCode: () => extractAdCode,
45
+ flatten: () => flatten,
46
+ handlePlatformRequest: () => handlePlatformRequest,
47
+ handleResponse: () => handleResponse,
48
+ log: () => log,
49
+ logException: () => logException,
50
+ prepareTestRequestHeaders: () => prepareTestRequestHeaders,
51
+ removeUndefined: () => removeUndefined
52
+ });
53
+ var crypto = __toESM(require("crypto"));
54
+ var appInsights = __toESM(require("applicationinsights"));
55
+ var import_node_fetch = __toESM(require("node-fetch"));
56
+ var aiClient = null;
57
+ if (process.env.APPINSIGHTS_INSTRUMENTATIONKEY) {
58
+ appInsights.setup().setAutoCollectDependencies(false).setAutoCollectConsole(true, true).setSendLiveMetrics(false).setAutoCollectRequests(false).setAutoCollectPerformance(false).setUseDiskRetryCaching(false).start();
59
+ aiClient = appInsights.defaultClient;
60
+ }
61
+ var EventPublisherBase = class {
62
+ config;
63
+ constructor(config) {
64
+ this.config = config;
65
+ }
66
+ /** @deprecated Please use a 'new Class(config)' notation. The .register() method will be deleted in future major version
67
+ * Registers a new instance of @see EventPublisherBase -derived class with array of publishers
68
+ * @param {EventPublisher[]} publishers Tha publishers array to register with
69
+ * @param {Object} config Configuration to pass to new instance
70
+ * Call this static method on @see EventPublisherBase -derived class.
71
+ * It will create its instance and pass @param config to its constructor.
72
+ * Than it will add resulting instance of @param publishers.
73
+ */
74
+ static register(publishers, config) {
75
+ publishers.push(
76
+ new this(
77
+ config
78
+ )
79
+ );
80
+ }
81
+ };
82
+ function log(log2, level, message, properties) {
83
+ log2.warn(message);
84
+ aiClient?.trackTrace({
85
+ message,
86
+ severity: level,
87
+ properties
88
+ });
89
+ }
90
+ function logException(log2, exception) {
91
+ log2.warn(exception);
92
+ aiClient?.trackException({
93
+ exception
94
+ });
95
+ }
96
+ function removeUndefined(originalValue) {
97
+ if (originalValue instanceof Array) {
98
+ return removeUndefinedFromArray(originalValue);
99
+ } else if (originalValue instanceof Object) {
100
+ return removeUndefinedFromObject(originalValue);
101
+ } else {
102
+ return originalValue;
103
+ }
104
+ }
105
+ function removeUndefinedFromObject(object) {
106
+ const resultObject = {};
107
+ for (const property in object) {
108
+ if (Object.prototype.hasOwnProperty.call(object, property) && object[property] !== void 0) {
109
+ resultObject[property] = removeUndefined(
110
+ object[property]
111
+ );
112
+ }
113
+ }
114
+ return resultObject;
115
+ }
116
+ function removeUndefinedFromArray(array) {
117
+ const resultArray = [];
118
+ for (const item of array) {
119
+ if (item !== void 0) {
120
+ resultArray.push(removeUndefined(item));
121
+ }
122
+ }
123
+ return resultArray;
124
+ }
125
+ function encodeEmail(email) {
126
+ return computeSha256HashFromString(email);
127
+ }
128
+ function computeSha256HashFromString(stringToHash) {
129
+ if (typeof stringToHash !== "string") {
130
+ return void 0;
131
+ }
132
+ return crypto.createHash("sha256").update(stringToHash.toLowerCase(), "ascii").digest("hex").toLowerCase();
133
+ }
134
+ function extractAdCode(data, adPlatform, adCode, format = null) {
135
+ const ad = data.ads.filter((x) => {
136
+ return x.adPlatform === adPlatform;
137
+ }).sort((a, b) => b.visitAt - a.visitAt)[0];
138
+ if (!ad) {
139
+ return null;
140
+ }
141
+ const code = ad.adCodes ? ad.adCodes[adCode] : null;
142
+ if (code) {
143
+ const returnValue = { code, visitAt: ad.visitAt };
144
+ if (format) {
145
+ return format(returnValue, ad);
146
+ }
147
+ return returnValue;
148
+ }
149
+ return null;
150
+ }
151
+ function flatten(event, separator = "_") {
152
+ return Object.assign(
153
+ {},
154
+ ...function _flatten(o, separator2, parent) {
155
+ return [].concat(
156
+ ...Object.keys(o).map((key) => {
157
+ if (typeof o[key] === "object" && o[key] !== null) {
158
+ const newParent = parent ? parent + separator2 + key : key;
159
+ return _flatten(o[key], separator2, newParent);
160
+ } else {
161
+ const newKey = parent ? parent + separator2 + key : key;
162
+ return { [newKey]: o[key] };
163
+ }
164
+ })
165
+ );
166
+ }(event, separator)
167
+ );
168
+ }
169
+ function prepareTestRequestHeaders(headers, origUrl, origRequest, origResponse) {
170
+ headers["x-mhub-orig-url"] = origUrl;
171
+ headers["x-mhub-orig-method"] = origRequest.method;
172
+ headers["x-mhub-orig-response-status-code"] = origResponse.status;
173
+ headers["x-mhub-orig-response-status-message"] = origResponse.statusText;
174
+ }
175
+ async function handleResponse(response, event) {
176
+ if (!response.ok) {
177
+ throw new Error(
178
+ `HTTP Error code: ${response.status}, event: ${event}, body: ${await response.text()}`
179
+ );
180
+ }
181
+ const body = await response.text();
182
+ try {
183
+ return JSON.parse(body);
184
+ } catch (ex) {
185
+ return body;
186
+ }
187
+ }
188
+ async function handlePlatformRequest({
189
+ source,
190
+ baseUrl,
191
+ requestOptions,
192
+ query = "",
193
+ event,
194
+ logger
195
+ }) {
196
+ if (!baseUrl || baseUrl.length < 3) {
197
+ throw new Error("URL for request was not provided or was not valid");
198
+ }
199
+ const fullUrl = baseUrl + query;
200
+ const fetchRequestOptions = {
201
+ method: requestOptions.method ?? "POST",
202
+ body: requestOptions.body ?? void 0,
203
+ // eslint-disable-next-line @typescript-eslint/naming-convention
204
+ headers: { ...requestOptions.headers }
205
+ };
206
+ const rawPlatformResponse = await (0, import_node_fetch.default)(fullUrl, fetchRequestOptions);
207
+ if (process.env.PUBLISHER_TESTURL) {
208
+ await handleTestRequest({
209
+ fetchRequestOptions,
210
+ fullUrl,
211
+ query,
212
+ rawPlatformResponse
213
+ });
214
+ }
215
+ const processedPlatfromResponse = await handleResponse(
216
+ rawPlatformResponse,
217
+ event
218
+ );
219
+ log(logger, 1, `${source} - ${event} - sent`);
220
+ return processedPlatfromResponse;
221
+ }
222
+ async function handleTestRequest(params) {
223
+ try {
224
+ params.fetchRequestOptions.headers = {
225
+ ...params.fetchRequestOptions.headers,
226
+ // eslint-disable-next-line @typescript-eslint/naming-convention
227
+ "x-mhub-orig-url": params.fullUrl,
228
+ // eslint-disable-next-line @typescript-eslint/naming-convention
229
+ "x-mhub-orig-method": params.fetchRequestOptions.method ?? "",
230
+ // eslint-disable-next-line @typescript-eslint/naming-convention
231
+ "x-mhub-orig-response-status-code": `${params.rawPlatformResponse.status}`,
232
+ // eslint-disable-next-line @typescript-eslint/naming-convention
233
+ "x-mhub-orig-response-status-message": params.rawPlatformResponse.statusText
234
+ };
235
+ await (0, import_node_fetch.default)(
236
+ `${process.env.PUBLISHER_TESTURL ?? ""} + ${params.query ?? ""}`,
237
+ params.fetchRequestOptions
238
+ );
239
+ } catch {
240
+ }
241
+ }
242
+
243
+ // src/defaultPublisher.ts
244
+ async function defaultPublisher(azureFunctionContext, eventHubMessages, source, platformPublisher, trigger) {
245
+ const processMessagePromises = [];
246
+ for (const message of eventHubMessages) {
247
+ processMessagePromises.push(
248
+ processMessage(
249
+ message,
250
+ azureFunctionContext.log,
251
+ platformPublisher,
252
+ trigger
253
+ )
254
+ );
255
+ }
256
+ const results = await Promise.allSettled(processMessagePromises);
257
+ for (const result of results) {
258
+ if (result.status === "rejected") {
259
+ logException(
260
+ azureFunctionContext.log,
261
+ new Error(result.reason)
262
+ );
263
+ }
264
+ }
265
+ }
266
+ async function processMessage(message, log2, platfromPublisher, trigger) {
267
+ const logProperties = {
268
+ source: platfromPublisher.source,
269
+ data: JSON.stringify(message)
270
+ };
271
+ const publishers = trigger(message);
272
+ if (!publishers.length) {
273
+ log(
274
+ log2,
275
+ 1,
276
+ "Message excluded by filter (no publishers determined)",
277
+ logProperties
278
+ );
279
+ return false;
280
+ }
281
+ let publishedAny = false;
282
+ let failedToPublishAll = false;
283
+ for (const eventPublisher of publishers) {
284
+ const mapped = await eventPublisher.map(message);
285
+ const res = await publishMessage(
286
+ log2,
287
+ mapped,
288
+ eventPublisher.config,
289
+ platfromPublisher,
290
+ message.event.code + (message.event.name ? "/" + message.event.name : "")
291
+ );
292
+ if (res) {
293
+ publishedAny = true;
294
+ } else {
295
+ logException(
296
+ log2,
297
+ new Error(
298
+ `The message has not been published. Source: ${platfromPublisher.source}`
299
+ )
300
+ );
301
+ failedToPublishAll = true;
302
+ }
303
+ }
304
+ if (!publishedAny) {
305
+ logException(
306
+ log2,
307
+ new Error(
308
+ "The message has not been published to any publisher configuration"
309
+ )
310
+ );
311
+ return false;
312
+ }
313
+ return !failedToPublishAll;
314
+ }
315
+ async function publishMessage(log2, mapped, config, platformPublisher, event) {
316
+ await platformPublisher.publish(log2, config, mapped, event);
317
+ return true;
318
+ }
319
+
320
+ // src/publishers/affiliatePort.ts
321
+ var affiliatePort = {
322
+ source: "AffiliatePort",
323
+ /**
324
+ * Publishes data to AffiliatePort
325
+ * @param log zure Function context.log
326
+ * @param config Publisher configuration
327
+ * @param data Data in publisher-friendly format to be published
328
+ * @param event Event for which the function is triggered
329
+ */
330
+ async publish(log2, config, data, event) {
331
+ if (data.products instanceof Array && (typeof config.offerId === "string" || typeof config.offerId === "number")) {
332
+ const affiliatePortData = removeUndefined(
333
+ data
334
+ );
335
+ const requestOptions = {
336
+ method: "GET"
337
+ };
338
+ const baseUrl = "https://tracking.affiliateclub.cz/aff_lsr";
339
+ for (const product of affiliatePortData.products) {
340
+ const query = `?offer_id=${encodeURIComponent(
341
+ config.offerId
342
+ )}&adv_sub=TID_${affiliatePortData.orderId}&amount=${product.quantity * product.price}&transaction_id=${affiliatePortData.transactionID}&adv_sub2=${product.category}&adv_sub3=${product.masterType}`;
343
+ await handlePlatformRequest({
344
+ source: this.source,
345
+ baseUrl,
346
+ query,
347
+ requestOptions,
348
+ event,
349
+ logger: log2
350
+ });
351
+ }
352
+ } else {
353
+ throw new Error("Invalid config for platform " + this.source);
354
+ }
355
+ }
356
+ };
357
+
358
+ // src/publishers/cj.ts
359
+ var cj = {
360
+ source: "CJAffiliate",
361
+ /**
362
+ * Publishes data to CJ
363
+ * @param log Azure Function context.log
364
+ * @param config Publisher configuration
365
+ * @param data Data in publisher-friendly format to be published
366
+ * @param event Event for which the function is triggered
367
+ */
368
+ async publish(log2, config, data, event) {
369
+ if (!data.cjevent) {
370
+ log(log2, 1, `CJ - ${event} - skipped because CJEVENT is missing`);
371
+ } else {
372
+ if (typeof config.cid === "string" && typeof config.type === "string") {
373
+ const cjData = removeUndefined(data);
374
+ let query = "?cid=" + encodeURI(config.cid);
375
+ query += "&type=" + encodeURI(config.type);
376
+ for (const property in data) {
377
+ if (Object.prototype.hasOwnProperty.call(cjData, property) && cjData[property] !== void 0) {
378
+ query += "&" + encodeURI(property) + "=" + encodeURI(
379
+ cjData[property] === null ? "" : (
380
+ // eslint-disable-next-line @typescript-eslint/non-nullable-type-assertion-style
381
+ cjData[property]?.toString()
382
+ )
383
+ );
384
+ }
385
+ }
386
+ const baseUrl = "https://www.kdukvh.com/u";
387
+ const requestOptions = {
388
+ method: "GET"
389
+ };
390
+ await handlePlatformRequest({
391
+ source: this.source,
392
+ baseUrl,
393
+ query,
394
+ requestOptions,
395
+ event,
396
+ logger: log2
397
+ });
398
+ } else {
399
+ throw new Error("Invalid config for platform " + this.source);
400
+ }
401
+ }
402
+ }
403
+ };
404
+
405
+ // src/publishers/facebook.ts
406
+ var facebook = {
407
+ source: "Faceboook",
408
+ /**
409
+ *Publishes data to Facebook
410
+ * @param log Azure Function context.log
411
+ * @param config Publisher configuration
412
+ * @param data Data in publisher-friendly format to be published
413
+ * @param event Event for which the function is triggered
414
+ */
415
+ async publish(log2, config, data, event) {
416
+ if (typeof config.id === "string" && typeof config.access_token === "string") {
417
+ const requestOptions = {
418
+ method: "POST",
419
+ body: JSON.stringify({ data: [removeUndefined(data)] }),
420
+ headers: {
421
+ // eslint-disable-next-line @typescript-eslint/naming-convention
422
+ "Content-Type": "application/json"
423
+ }
424
+ };
425
+ const baseUrl = `https://graph.facebook.com/v11.0/${encodeURIComponent(
426
+ config.id
427
+ )}/events`;
428
+ const query = `?access_token=${encodeURI(config.access_token)}`;
429
+ await handlePlatformRequest({
430
+ source: this.source,
431
+ baseUrl,
432
+ query,
433
+ requestOptions,
434
+ event,
435
+ logger: log2
436
+ });
437
+ } else {
438
+ throw new Error("Invalid config for platform " + this.source);
439
+ }
440
+ }
441
+ };
442
+
443
+ // src/publishers/googleAnalytics4.ts
444
+ var googleAnalytics4 = {
445
+ source: "GoogleAnalytics4",
446
+ /**
447
+ * Publishes data to Google Analytics
448
+ * @param log zure Function context.log
449
+ * @param config Publisher configuration
450
+ * @param data Data in publisher-friendly format to be published
451
+ * @param event Event for which the function is triggered
452
+ */
453
+ async publish(log2, config, data, event) {
454
+ if (config.trackingId) {
455
+ const ga4Data = removeUndefined(data);
456
+ ga4Data.v = 2;
457
+ ga4Data.seg = 1;
458
+ ga4Data.gcs = 111;
459
+ ga4Data.tid = config.trackingId;
460
+ let payload = "";
461
+ for (const property in ga4Data) {
462
+ if (Object.prototype.hasOwnProperty.call(ga4Data, property)) {
463
+ if (payload) {
464
+ payload += "&";
465
+ }
466
+ payload += encodeURI(property) + "=" + encodeURI(ga4Data[property]);
467
+ }
468
+ }
469
+ const requestOptions = {
470
+ method: "POST",
471
+ headers: {
472
+ // eslint-disable-next-line @typescript-eslint/naming-convention
473
+ "User-Agent": "mHub Cloud"
474
+ }
475
+ };
476
+ const baseUrl = "https://www.google-analytics.com/g/collect";
477
+ const query = `?${payload}`;
478
+ await handlePlatformRequest({
479
+ source: this.source,
480
+ baseUrl,
481
+ query,
482
+ requestOptions,
483
+ event,
484
+ logger: log2
485
+ });
486
+ } else {
487
+ throw new Error("Invalid config for platform " + this.source);
488
+ }
489
+ }
490
+ };
491
+
492
+ // src/publishers/piano.ts
493
+ var piano = {
494
+ source: "Piano",
495
+ /**
496
+ * Publishes data to Piano
497
+ * @param log zure Function context.log
498
+ * @param config Publisher configuration
499
+ * @param data Data in publisher-friendly format to be published
500
+ * @param event Event for which the function is triggered
501
+ */
502
+ async publish(log2, config, data, event) {
503
+ if (typeof config.siteId === "string" && typeof config.collectionDomain === "string") {
504
+ const pianoData = removeUndefined(data);
505
+ let query = "";
506
+ query = "?s=" + encodeURI(config.siteId);
507
+ query += "&idclient=" + encodeURI(pianoData.aux.visitorId);
508
+ query += "&ref=" + encodeURI(pianoData.aux.ref);
509
+ const requestOptions = {
510
+ method: "POST"
511
+ };
512
+ requestOptions.headers = {};
513
+ if (pianoData.aux.userAgent) {
514
+ requestOptions.headers["User-Agent"] = pianoData.aux.userAgent;
515
+ }
516
+ if (pianoData.aux.referer) {
517
+ requestOptions.headers.Referer = pianoData.aux.referer;
518
+ }
519
+ if (pianoData.aux.forwardedFor) {
520
+ requestOptions.headers["X-Forwarded-For"] = pianoData.aux.forwardedFor;
521
+ }
522
+ const baseUrl = `https://${config.collectionDomain}/`;
523
+ await handlePlatformRequest({
524
+ source: this.source,
525
+ baseUrl,
526
+ query,
527
+ requestOptions,
528
+ event,
529
+ logger: log2
530
+ });
531
+ } else {
532
+ throw new Error("Invalid config for platform " + this.source);
533
+ }
534
+ }
535
+ };
536
+
537
+ // src/publishers/universalAnalytics.ts
538
+ var universalAnalytics = {
539
+ source: "UniversalAnalytics",
540
+ /**
541
+ * Publishes data to UniversalAnalytics
542
+ * @param log zure Function context.log
543
+ * @param config Publisher configuration
544
+ * @param data Data in publisher-friendly format to be published
545
+ * @param event Event for which the function is triggered
546
+ */
547
+ async publish(log2, config, data, event) {
548
+ if (config.trackingId) {
549
+ const uaData = removeUndefined(data);
550
+ uaData.v = 1;
551
+ uaData.tid = config.trackingId;
552
+ let payload = "";
553
+ for (const property in uaData) {
554
+ if (Object.prototype.hasOwnProperty.call(uaData, property)) {
555
+ if (payload) {
556
+ payload += "&";
557
+ }
558
+ if (uaData[property]) {
559
+ payload += encodeURI(property) + "=" + encodeURI(uaData[property] ?? "");
560
+ }
561
+ }
562
+ }
563
+ const requestOptions = {
564
+ method: "POST",
565
+ body: payload,
566
+ headers: {
567
+ // eslint-disable-next-line @typescript-eslint/naming-convention
568
+ "Content-Type": "application/x-www-form-urlencoded",
569
+ // eslint-disable-next-line @typescript-eslint/naming-convention
570
+ "User-Agent": "mHub Cloud"
571
+ }
572
+ };
573
+ const baseUrl = "https://www.google-analytics.com/collect";
574
+ const query = `?${payload}`;
575
+ await handlePlatformRequest({
576
+ source: this.source,
577
+ baseUrl,
578
+ query,
579
+ requestOptions,
580
+ event,
581
+ logger: log2
582
+ });
583
+ } else {
584
+ throw new Error("Invalid config for platform " + this.source);
585
+ }
586
+ }
587
+ };
588
+
589
+ // src/index.ts
590
+ var publisher = {
591
+ // eslint-disable-next-line @typescript-eslint/naming-convention
592
+ Facebook: facebook,
593
+ // eslint-disable-next-line @typescript-eslint/naming-convention
594
+ CJ: cj,
595
+ // eslint-disable-next-line @typescript-eslint/naming-convention
596
+ GoogleAnalytics4: googleAnalytics4,
597
+ // eslint-disable-next-line @typescript-eslint/naming-convention
598
+ UniversalAnalytics: universalAnalytics,
599
+ // eslint-disable-next-line @typescript-eslint/naming-convention
600
+ Piano: piano,
601
+ // eslint-disable-next-line @typescript-eslint/naming-convention
602
+ AffiliatePort: affiliatePort
603
+ };
604
+ // Annotate the CommonJS export names for ESM import in node:
605
+ 0 && (module.exports = {
606
+ DefaultPublisher,
607
+ publisher,
608
+ utils
609
+ });
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@mhubcloud/tms_core",
3
- "version": "2.0.0-beta.0",
3
+ "version": "2.0.0-beta.1",
4
4
  "description": "Core function for mHub Cloud TMS publishers",
5
5
  "homepage": "https://mhubcloud.com/",
6
6
  "license": "Apache 2.0",
7
7
  "email": "info@crossmasters.com",
8
8
  "author": "Jan Brzobohatý",
9
- "main": "index.js",
9
+ "main": "dist/index.js",
10
10
  "keywords": [
11
11
  "mHub Cloud",
12
12
  "TMS",