kv-test-lib 1.0.0

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.
@@ -0,0 +1,148 @@
1
+ /*
2
+ Authored by Brett Barinaga on 11/17/21.
3
+ Copyright (c) Kochava, Inc. All rights reserved.
4
+ */
5
+ import * as http from "../http";
6
+ import * as utils from "../utils/utils";
7
+ import * as browser from "../browser/browser";
8
+ import { Log } from "../utils/log";
9
+ import { constructPayload } from "./payload";
10
+ import { getPersistedIdentityLinks, PersistKey, readAndUpdatePersistedValue, updatePersistedValue } from "../browser/persist";
11
+ let timeOut;
12
+ let canceled = false;
13
+ export const build = (instance) => {
14
+ const payload = constructPayload("install", instance);
15
+ instance.installStarted = true;
16
+ payload.data = constructInstallData(instance);
17
+ Log.debug("Install Payload", JSON.stringify(payload));
18
+ if (instance.kochavaConfig.privacy) {
19
+ instance.kochavaConfig.privacy.deny_datapoints.forEach(denyPoint => {
20
+ for (const point in payload.data) {
21
+ const key = point;
22
+ if (key === denyPoint)
23
+ delete payload.data[key];
24
+ }
25
+ for (const point in payload) {
26
+ const key = point;
27
+ if (key === denyPoint)
28
+ delete payload[key];
29
+ }
30
+ });
31
+ }
32
+ return payload;
33
+ };
34
+ export const cancelRetries = () => {
35
+ canceled = true;
36
+ clearTimeout(timeOut);
37
+ };
38
+ export const send = async (instance, payload, retries = 0) => {
39
+ canceled = false;
40
+ let success = false;
41
+ let resp;
42
+ do {
43
+ const sendTime = utils.getCurrTimeMS() - instance.startTimeMS;
44
+ Log.diagDebug(`Sending install at ${utils.formatTime(sendTime / 1000)} seconds`);
45
+ const respStr = await http.sendRequest(payload, (instance.overrideUrls.install) ?
46
+ instance.overrideUrls.install : instance.kochavaConfig.networking.urls.install);
47
+ const respTime = utils.getCurrTimeMS() - instance.startTimeMS;
48
+ Log.diagDebug(`Completed install at ${new Date().toLocaleTimeString()}
49
+ seconds with a network duration of ${utils.formatTime((respTime - sendTime) / 1000)} seconds`);
50
+ if (canceled) {
51
+ Log.trace("Can no longer retry install, cancelling.");
52
+ return false;
53
+ }
54
+ try {
55
+ Log.trace("Install Response string:", respStr);
56
+ resp = JSON.parse(respStr);
57
+ Log.debug("Install Response:", respStr);
58
+ success = http.wasRespSuccess(resp.success);
59
+ }
60
+ catch (e) {
61
+ Log.error("Error parsing Install Response", e);
62
+ success = false;
63
+ }
64
+ if (success) {
65
+ Log.info("Install success!");
66
+ return success;
67
+ }
68
+ if (!canceled) {
69
+ const retryWaterfall = instance.kochavaConfig.networking.retry_waterfall;
70
+ const retryIndex = (retries > retryWaterfall.length - 1) ? retryWaterfall.length - 1 : retries;
71
+ const retrySec = retryWaterfall[retryIndex];
72
+ Log.error(`Install failed, attempting again in ${retrySec} seconds`);
73
+ await new Promise(resolve => { timeOut = setTimeout(resolve, retrySec * 1000); });
74
+ retries++;
75
+ }
76
+ } while (!success && !canceled);
77
+ };
78
+ export const onSuccess = (instance) => {
79
+ instance.kochavaInstallDate = utils.getCurrTimeMS();
80
+ updatePersistedValue(PersistKey.InstallSentDate, String(instance.kochavaInstallDate), instance.useCookies);
81
+ };
82
+ const constructInstallData = (instance) => {
83
+ const currTime = Math.floor(Date.now() / 1000);
84
+ let uptime = (currTime - instance.startTimeMS) / 1000;
85
+ if (uptime < 0.0)
86
+ uptime = 0.0;
87
+ let returnObj = {
88
+ starttime: instance.startTimeMS / 1000,
89
+ uptime: uptime,
90
+ usertime: determineInstallUserTime(instance, currTime),
91
+ device_orientation: browser.getDeviceOrientation(),
92
+ package: browser.getPackageName(),
93
+ disp_w: browser.getDeviceWidth(),
94
+ disp_h: browser.getDeviceHeight(),
95
+ language: browser.getLanguage(),
96
+ };
97
+ if (instance.utm) {
98
+ returnObj = Object.assign(Object.assign({}, returnObj), { conversion_data: { utm_source: instance.utm } });
99
+ }
100
+ if (instance.customValues.length > 0)
101
+ returnObj.device_ids = {};
102
+ instance.customValues.forEach((custom) => {
103
+ const customKey = Object.keys(custom.data)[0];
104
+ if (instance.kochavaConfig.privacy) {
105
+ let keyAllowed = false;
106
+ for (const allowed of instance.kochavaConfig.privacy.allow_custom_ids) {
107
+ if (customKey === allowed) {
108
+ keyAllowed = true;
109
+ }
110
+ }
111
+ if (keyAllowed) {
112
+ if (custom.isDeviceId)
113
+ returnObj.device_ids = Object.assign(Object.assign({}, returnObj.device_ids), custom.data);
114
+ else
115
+ returnObj = Object.assign(Object.assign({}, custom.data), returnObj);
116
+ }
117
+ }
118
+ });
119
+ // add the persisted identityLinks
120
+ const persistedIdLinks = getPersistedIdentityLinks();
121
+ if (persistedIdLinks) {
122
+ returnObj.identity_link = {};
123
+ for (const key in persistedIdLinks) {
124
+ let includeKey = true;
125
+ for (const denyIdLinkKey of instance.kochavaConfig.privacy.deny_identity_links) {
126
+ if (denyIdLinkKey === key) {
127
+ Log.debug(`Denied identity_link ${denyIdLinkKey}, dropping from install.`);
128
+ includeKey = false;
129
+ }
130
+ }
131
+ if (includeKey)
132
+ returnObj.identity_link[key] = persistedIdLinks[key];
133
+ }
134
+ }
135
+ return returnObj;
136
+ };
137
+ const determineInstallUserTime = (instance, currTime) => {
138
+ const firstStartStr = readAndUpdatePersistedValue(PersistKey.FirstStartDate, instance.useCookies);
139
+ if (firstStartStr) {
140
+ const firstStart = JSON.parse(firstStartStr);
141
+ // If its been 30 days since the sdk started
142
+ if ((currTime - firstStart) > 2592000) {
143
+ return currTime;
144
+ }
145
+ return firstStart;
146
+ }
147
+ return currTime;
148
+ };
@@ -0,0 +1,5 @@
1
+ import { KochavaInstance } from "../kochava";
2
+ import { KvinitResponse } from "../interfaces";
3
+ export declare const cancelRetries: () => void;
4
+ export declare const send: (instance: KochavaInstance, retryWaterfall: number[], retries?: number) => Promise<boolean>;
5
+ export declare const applyKvinitResp: (instance: KochavaInstance, resp: KvinitResponse) => void;
@@ -0,0 +1,134 @@
1
+ /*
2
+ Authored by Brett Barinaga on 11/17/21.
3
+ Copyright (c) Kochava, Inc. All rights reserved.
4
+ */
5
+ import * as http from "../http";
6
+ import * as utils from "../utils/utils";
7
+ import { getPackageName } from "../browser/browser";
8
+ import { Log } from "../utils/log";
9
+ import { constructPayload } from "./payload";
10
+ import { DEFAULTS } from "../interfaces";
11
+ import { PersistKey, updatePersistedValue } from "../browser/persist";
12
+ let timeOut;
13
+ let canceled = false;
14
+ const build = (instance) => {
15
+ const payload = constructPayload("init", instance);
16
+ payload.build_date = instance.buildDate;
17
+ payload.data = constructKvinitData(instance);
18
+ Log.debug("Kvinit Payload", JSON.stringify(payload));
19
+ return payload;
20
+ };
21
+ export const cancelRetries = () => {
22
+ canceled = true;
23
+ clearTimeout(timeOut);
24
+ };
25
+ export const send = async (instance, retryWaterfall, retries = 0) => {
26
+ canceled = false;
27
+ const payload = build(instance);
28
+ let success = false;
29
+ let resp;
30
+ do {
31
+ Log.trace("Kvinit endpoint:", instance.kochavaConfig.networking.urls.init);
32
+ const sendTime = utils.getCurrTimeMS() - instance.startTimeMS;
33
+ Log.diagDebug(`Sending kvinit at ${utils.formatTime(sendTime / 1000)} seconds`);
34
+ const respStr = await http.sendRequest(payload, (instance.overrideUrls.init) ?
35
+ instance.overrideUrls.init : instance.kochavaConfig.networking.urls.init);
36
+ const respTime = utils.getCurrTimeMS() - instance.startTimeMS;
37
+ Log.diagDebug(`Completed kvinit at ${utils.formatTime(respTime / 1000)}
38
+ seconds with a network duration of ${utils.formatTime((respTime - sendTime) / 1000)} seconds`);
39
+ if (canceled) {
40
+ Log.trace("Can no longer retry kvinit, cancelling.");
41
+ return false;
42
+ }
43
+ try {
44
+ resp = JSON.parse(respStr);
45
+ Log.debug("Kvinit Response:", resp);
46
+ success = http.wasRespSuccess(resp.success);
47
+ }
48
+ catch (e) {
49
+ Log.error("Error parsing Kvinit Response", e);
50
+ success = false;
51
+ }
52
+ if (success) {
53
+ Log.info("Kvinit success!");
54
+ updatePersistedValue(PersistKey.LastKvinit, JSON.stringify(resp), instance.useCookies);
55
+ return success;
56
+ }
57
+ if (!canceled) {
58
+ // retry kvinit
59
+ const retryIndex = (retries > retryWaterfall.length - 1) ? retryWaterfall.length - 1 : retries;
60
+ const retrySec = retryWaterfall[retryIndex];
61
+ Log.error(`Kvinit failed, attempting again in ${retrySec} seconds`);
62
+ await new Promise(resolve => { timeOut = setTimeout(resolve, retrySec * 1000); });
63
+ retries++;
64
+ }
65
+ } while (!success && !canceled);
66
+ };
67
+ export const applyKvinitResp = (instance, resp) => {
68
+ if (resp.general) {
69
+ if (resp.general.device_id_override) {
70
+ Log.trace(`Device_id override found, going from ${instance.kochavaDeviceId} to
71
+ ${resp.general.device_id_override}`);
72
+ instance.kochavaConfig.general.device_id_override = resp.general.device_id_override;
73
+ instance.kochavaDeviceId = resp.general.device_id_override;
74
+ updatePersistedValue(PersistKey.OverrideDeviceId, resp.general.device_id_override, instance.useCookies);
75
+ }
76
+ if (resp.general.app_id_override) {
77
+ Log.trace(`App_id override found, going from ${instance.appGuid} to
78
+ ${resp.general.app_id_override}`);
79
+ instance.kochavaConfig.general.app_id_override = resp.general.app_id_override;
80
+ instance.appGuid = resp.general.app_id_override;
81
+ updatePersistedValue(PersistKey.OverrideAppId, resp.general.app_id_override, instance.useCookies);
82
+ }
83
+ }
84
+ if (resp.config) {
85
+ instance.kochavaConfig.config = {
86
+ init_token: resp.config.init_token || DEFAULTS.config.init_token,
87
+ refresh_minimum: (resp.config.refresh_minimum !== undefined &&
88
+ resp.config.refresh_minimum !== null) ? resp.config.refresh_minimum :
89
+ DEFAULTS.config.refresh_minimum,
90
+ };
91
+ }
92
+ if (resp.install) {
93
+ if (resp.install.resend_id) {
94
+ instance.kochavaConfig.install.resend_id = resp.install.resend_id;
95
+ }
96
+ instance.kochavaConfig.install.updates_enabled =
97
+ resp.install.updates_enabled || DEFAULTS.install.updates_enabled;
98
+ }
99
+ if (resp.networking) {
100
+ instance.kochavaConfig.networking.retry_waterfall =
101
+ resp.networking.retry_waterfall || DEFAULTS.networking.retry_waterfall;
102
+ instance.retryWaterfall =
103
+ instance.kochavaConfig.networking.retry_waterfall;
104
+ if (resp.networking.urls) {
105
+ instance.kochavaConfig.networking.urls = {
106
+ init: resp.networking.urls.init || DEFAULTS.networking.urls.init,
107
+ install: resp.networking.urls.install || DEFAULTS.networking.urls.install,
108
+ event: resp.networking.urls.event || DEFAULTS.networking.urls.event,
109
+ identityLink: resp.networking.urls.identityLink || DEFAULTS.networking.urls.identityLink,
110
+ };
111
+ }
112
+ }
113
+ if (resp.privacy) {
114
+ instance.kochavaConfig.privacy = {
115
+ allow_custom_ids: resp.privacy.allow_custom_ids || DEFAULTS.privacy.allow_custom_ids,
116
+ deny_datapoints: resp.privacy.deny_datapoints || DEFAULTS.privacy.deny_datapoints,
117
+ deny_event_names: resp.privacy.deny_event_names || DEFAULTS.privacy.deny_event_names,
118
+ deny_identity_links: resp.privacy.deny_identity_links || DEFAULTS.privacy.deny_identity_links,
119
+ };
120
+ }
121
+ };
122
+ const constructKvinitData = (instance) => {
123
+ const currTime = Math.floor(Date.now() / 1000);
124
+ let uptime = (currTime - instance.startTimeMS) / 1000;
125
+ if (uptime < 0.0)
126
+ uptime = 0.0;
127
+ return {
128
+ package: getPackageName(),
129
+ platform: "web",
130
+ starttime: instance.startTimeMS / 1000,
131
+ uptime,
132
+ usertime: currTime,
133
+ };
134
+ };
@@ -0,0 +1,33 @@
1
+ import { Json } from '../interfaces';
2
+ import { KochavaInstance } from "../kochava";
3
+ export interface Payload {
4
+ action: string;
5
+ kochava_app_id: string;
6
+ kochava_device_id: string;
7
+ sdk_version: string;
8
+ sdk_protocol: string;
9
+ nt_id: string;
10
+ build_date?: string;
11
+ init_token?: string;
12
+ data?: Json;
13
+ }
14
+ export interface PreStartBody {
15
+ action: string;
16
+ sdk_version: string;
17
+ sdk_protocol: string;
18
+ init_token?: string;
19
+ data?: Json;
20
+ }
21
+ export interface PostStartBody {
22
+ kochava_app_id: string;
23
+ kochava_device_id: string;
24
+ nt_id: string;
25
+ data?: Json;
26
+ }
27
+ export interface CommonData {
28
+ starttime: number;
29
+ uptime: number;
30
+ usertime: number;
31
+ }
32
+ export declare const constructPayload: (action: string, instance: KochavaInstance, originalNtId?: string) => Payload;
33
+ export declare const constructCommonData: (instance: KochavaInstance) => CommonData;
@@ -0,0 +1,33 @@
1
+ /*
2
+ Authored by Brett Barinaga on 11/17/21.
3
+ Copyright (c) Kochava, Inc. All rights reserved.
4
+ */
5
+ import * as utils from "../utils/utils";
6
+ import { Log } from "../utils/log";
7
+ export const constructPayload = (action, instance, originalNtId) => {
8
+ let nt_id = `${instance.kochavaSession}-${instance.kochavaSessionCount}-${utils.uuidv4()}`;
9
+ if (originalNtId) {
10
+ Log.debug("Persisted call found with nt_id:", originalNtId);
11
+ nt_id = originalNtId;
12
+ }
13
+ return {
14
+ action: action,
15
+ kochava_app_id: instance.appGuid,
16
+ kochava_device_id: instance.kochavaDeviceId,
17
+ sdk_version: instance.version,
18
+ sdk_protocol: "17",
19
+ nt_id: nt_id,
20
+ init_token: (instance.kochavaConfig.config.init_token) || undefined,
21
+ };
22
+ };
23
+ export const constructCommonData = (instance) => {
24
+ const currTime = utils.getCurrTimeMS();
25
+ let uptime = (currTime - instance.startTimeMS) / 1000;
26
+ if (uptime < 0.0)
27
+ uptime = 0.0;
28
+ return {
29
+ starttime: instance.startTimeMS / 1000,
30
+ uptime: uptime,
31
+ usertime: currTime / 1000,
32
+ };
33
+ };
@@ -0,0 +1,30 @@
1
+ declare enum Level {
2
+ Off = "Off",
3
+ Error = "Error",
4
+ Warn = "Warn",
5
+ Info = "Info",
6
+ Debug = "Debug",
7
+ Trace = "Trace"
8
+ }
9
+ declare class Logger {
10
+ private currLevel;
11
+ private logObjects;
12
+ private levelPrio;
13
+ private logsFilteredOut;
14
+ static instance: Logger;
15
+ constructor();
16
+ setLogLevel(input: string): void;
17
+ getLogLevel(): string;
18
+ setLogObjects(enable: boolean): void;
19
+ disableLogType(input: string): void;
20
+ error(msg: string, ...args: any): void;
21
+ warn(msg: string, ...args: any): void;
22
+ info(msg: string, ...args: any): void;
23
+ debug(msg: string, ...args: any): void;
24
+ trace(msg: string, ...args: any): void;
25
+ diagInfo(msg: string, ...args: any): void;
26
+ diagDebug(msg: string, ...args: any): void;
27
+ print(lvl: Level, msg: string, ...args: any): void;
28
+ }
29
+ export declare const Log: Logger;
30
+ export {};
@@ -0,0 +1,104 @@
1
+ /*
2
+ Authored by Brett Barinaga on 11/17/21.
3
+ Copyright (c) Kochava, Inc. All rights reserved.
4
+ */
5
+ import { getMsTime } from "./utils";
6
+ var Level;
7
+ (function (Level) {
8
+ Level["Off"] = "Off";
9
+ Level["Error"] = "Error";
10
+ Level["Warn"] = "Warn";
11
+ Level["Info"] = "Info";
12
+ Level["Debug"] = "Debug";
13
+ Level["Trace"] = "Trace";
14
+ })(Level || (Level = {}));
15
+ class Logger {
16
+ constructor() {
17
+ if (Logger.instance)
18
+ return;
19
+ this.levelPrio = {
20
+ Off: 0,
21
+ Error: 1,
22
+ Warn: 2,
23
+ Info: 3,
24
+ Debug: 4,
25
+ Trace: 5,
26
+ };
27
+ this.currLevel = Level.Info;
28
+ this.logObjects = false;
29
+ this.logsFilteredOut = {
30
+ Off: false,
31
+ Error: false,
32
+ Warn: false,
33
+ Info: false,
34
+ Debug: false,
35
+ Trace: false,
36
+ Diag: false,
37
+ };
38
+ Logger.instance = this;
39
+ }
40
+ setLogLevel(input) {
41
+ const levelStr = input[0].toUpperCase() + input.substring(1).toLowerCase();
42
+ const key = levelStr;
43
+ const level = Level[key];
44
+ if (level !== undefined && level !== null) {
45
+ this.currLevel = level;
46
+ }
47
+ else {
48
+ console.log(`Invalid logLevel ${level} passed in, defaulting to info.`);
49
+ this.currLevel = Level.Info;
50
+ }
51
+ }
52
+ getLogLevel() {
53
+ return this.currLevel.toString();
54
+ }
55
+ setLogObjects(enable) {
56
+ this.logObjects = enable;
57
+ }
58
+ disableLogType(input) {
59
+ const levelStr = input[0].toUpperCase() + input.substring(1).toLowerCase();
60
+ const key = levelStr;
61
+ this.logsFilteredOut[key] = true;
62
+ }
63
+ error(msg, ...args) {
64
+ this.print(Level.Error, msg, ...args);
65
+ }
66
+ warn(msg, ...args) {
67
+ this.print(Level.Warn, msg, ...args);
68
+ }
69
+ info(msg, ...args) {
70
+ this.print(Level.Info, msg, ...args);
71
+ }
72
+ debug(msg, ...args) {
73
+ this.print(Level.Debug, msg, ...args);
74
+ }
75
+ trace(msg, ...args) {
76
+ this.print(Level.Trace, msg, ...args);
77
+ }
78
+ diagInfo(msg, ...args) {
79
+ if (!this.logsFilteredOut.Diag)
80
+ this.print(Level.Info, "Kochava Diagnostic - " + msg, ...args);
81
+ }
82
+ diagDebug(msg, ...args) {
83
+ if (!this.logsFilteredOut.Diag)
84
+ this.print(Level.Debug, "Kochava Diagnostic - " + msg, ...args);
85
+ }
86
+ print(lvl, msg, ...args) {
87
+ if (this.levelPrio[this.currLevel.toString()] >= this.levelPrio[lvl.toString()] &&
88
+ !this.logsFilteredOut[lvl.toString()]) {
89
+ try {
90
+ const obj = JSON.parse(args[0]);
91
+ if (this.logObjects && obj) {
92
+ console.log(`KVA :: ${getMsTime()} ${lvl.toString()}:`, msg, obj);
93
+ }
94
+ else {
95
+ console.log(`KVA :: ${getMsTime()} ${lvl.toString()}:`, msg, ...args);
96
+ }
97
+ }
98
+ catch (_a) {
99
+ console.log(`KVA :: ${getMsTime()} ${lvl.toString()}:`, msg, ...args);
100
+ }
101
+ }
102
+ }
103
+ }
104
+ export const Log = new Logger();
@@ -0,0 +1,5 @@
1
+ export declare const uuidv4: () => string;
2
+ export declare const getCurrTimeMS: () => number;
3
+ export declare const getCurrTimeSec: () => number;
4
+ export declare const formatTime: (num: number) => string;
5
+ export declare const getMsTime: () => string;
@@ -0,0 +1,21 @@
1
+ /*
2
+ Authored by Brett Barinaga on 11/17/21.
3
+ Copyright (c) Kochava, Inc. All rights reserved.
4
+ */
5
+ export const uuidv4 = () => {
6
+ return (`${1e7}-${1e3}-${4e3}-${8e3}-${1e11}`).replace(/[018]/g, (c) => (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16));
7
+ };
8
+ // returns the number of milliseconds elapsed since January 1, 1970
9
+ export const getCurrTimeMS = () => Math.floor(Date.now());
10
+ // returns the number of seconds elapsed since January 1, 1970
11
+ export const getCurrTimeSec = () => Math.floor(Date.now() / 1000);
12
+ export const formatTime = (num) => {
13
+ if (num < 10 && num % 10 <= 9)
14
+ return "0" + num.toFixed(1).toString();
15
+ else
16
+ return num.toFixed(1).toString();
17
+ };
18
+ export const getMsTime = () => {
19
+ const date = new Date();
20
+ return `${date.getHours()}:${date.getMinutes()}:${date.getSeconds()}:${date.getMilliseconds()}`;
21
+ };
package/package.json ADDED
@@ -0,0 +1,16 @@
1
+ {
2
+ "type": "module",
3
+ "name": "kv-test-lib",
4
+ "version": "1.0.0",
5
+ "description": "",
6
+ "scripts": {
7
+ "build": "tsc -p ../../src/tsconfig.node.json",
8
+ "test": "tsc -p ."
9
+ },
10
+ "devDependencies": {
11
+ "playwright": "^1.16.3",
12
+ "typescript": "^4.5.5"
13
+ },
14
+ "author": "",
15
+ "license": "ISC"
16
+ }
@@ -0,0 +1,64 @@
1
+ // Generated using webpack-cli https://github.com/webpack/webpack-cli
2
+
3
+ const path = require('path');
4
+ // import * as path from 'path';
5
+
6
+ const isProduction = process.env.NODE_ENV == 'production';
7
+
8
+ const kochavaConfig = {
9
+ entry: '../../src/kochava.ts',
10
+ plugins: [
11
+ // Add your plugins here
12
+ // Learn more about plugins from https://webpack.js.org/configuration/plugins/
13
+ ],
14
+ output: {
15
+ filename: 'kochava.js',
16
+ path: path.resolve(__dirname, 'dist'),
17
+ clean: true,
18
+ },
19
+ target: 'web',
20
+ module: {
21
+ rules: [
22
+ {
23
+ test: /\.(ts|tsx)$/i,
24
+ loader: 'ts-loader',
25
+ exclude: ['/node_modules/'],
26
+ options: {
27
+ configFile: "tsconfig.node.json"
28
+ }
29
+ },
30
+ {
31
+ test: /\.(eot|svg|ttf|woff|woff2|png|jpg|gif)$/i,
32
+ type: 'asset',
33
+ },
34
+
35
+ // Add your rules for custom modules here
36
+ // Learn more about loaders from https://webpack.js.org/loaders/
37
+ ],
38
+ },
39
+ resolve: {
40
+ extensions: ['.ts', '.js'],
41
+ },
42
+ mode: (isProduction) ? 'production' : 'development',
43
+ devtool: 'source-map',
44
+ };
45
+
46
+
47
+ module.exports = [
48
+ kochavaConfig,
49
+ ];
50
+ module.exports.parallelism = 2;
51
+
52
+
53
+
54
+
55
+
56
+ // module.exports = () => {
57
+ // if (isProduction) {
58
+ // config.mode = 'production';
59
+ // } else {
60
+ // config.mode = 'development';
61
+ // }
62
+ // return config;
63
+ // };
64
+