Skip to content

Commit

Permalink
fix linter
Browse files Browse the repository at this point in the history
  • Loading branch information
borosr committed Apr 7, 2022
1 parent 7f0faa3 commit a4b90d5
Show file tree
Hide file tree
Showing 9 changed files with 145 additions and 127 deletions.
2 changes: 1 addition & 1 deletion .eslintrc.cjs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
module.exports = {
root: true,
parser: '@typescript-eslint/parser',
extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended'],
extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended', 'prettier'],
plugins: ['@typescript-eslint'],
ignorePatterns: ['*.cjs', 'node_modules'],
parserOptions: {
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1 @@
# fluidpay-guardian
# fluidpay-guardian
54 changes: 30 additions & 24 deletions src/guardian/guardian.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
import {Event} from "../models/events.interface";
import {getLocalStorage} from "./helper";
import {utmCampaignListener, utmContent, utmMediumListener, utmSourceListener, utmTerm} from "./utm";
import { Event } from '../models/events.interface';
import { getLocalStorage } from './helper';
import {
utmCampaignListener,
utmContent,
utmMediumListener,
utmSourceListener,
utmTerm
} from './utm';

export const localStorageKey = 'fp-guardian-results';
export const defaultClearPeriod = 1_800_000
export const defaultClearPeriod = 1_800_000;

class Guardian {
private readonly utmSourceObserver: MutationObserver;
Expand All @@ -13,36 +19,36 @@ class Guardian {
private readonly utmContentObserver: MutationObserver;

constructor() {
this.utmSourceObserver = new MutationObserver(utmSourceListener)
this.utmMediumObserver = new MutationObserver(utmMediumListener)
this.utmCampaignObserver = new MutationObserver(utmCampaignListener)
this.utmTermObserver = new MutationObserver(utmTerm)
this.utmContentObserver = new MutationObserver(utmContent)
this.utmSourceObserver = new MutationObserver(utmSourceListener);
this.utmMediumObserver = new MutationObserver(utmMediumListener);
this.utmCampaignObserver = new MutationObserver(utmCampaignListener);
this.utmTermObserver = new MutationObserver(utmTerm);
this.utmContentObserver = new MutationObserver(utmContent);
}

process() {
this.utmSourceObserver.observe(document, {subtree: true, childList: true});
this.utmMediumObserver.observe(document, {subtree: true, childList: true});
this.utmCampaignObserver.observe(document, {subtree: true, childList: true});
this.utmTermObserver.observe(document, {subtree: true, childList: true});
this.utmContentObserver.observe(document, {subtree: true, childList: true});
this.utmSourceObserver.observe(document, { subtree: true, childList: true });
this.utmMediumObserver.observe(document, { subtree: true, childList: true });
this.utmCampaignObserver.observe(document, { subtree: true, childList: true });
this.utmTermObserver.observe(document, { subtree: true, childList: true });
this.utmContentObserver.observe(document, { subtree: true, childList: true });
}

disconnect() {
this.utmSourceObserver.disconnect()
this.utmMediumObserver.disconnect()
this.utmCampaignObserver.disconnect()
this.utmTermObserver.disconnect()
this.utmContentObserver .disconnect()
this.utmSourceObserver.disconnect();
this.utmMediumObserver.disconnect();
this.utmCampaignObserver.disconnect();
this.utmTermObserver.disconnect();
this.utmContentObserver.disconnect();
}
}

const getGuardianData = (): Event[] => {
const values = getLocalStorage(localStorageKey)
const values = getLocalStorage(localStorageKey);
if (!values) {
return [] as Event[]
return [] as Event[];
}
return Object.values(values)
}
return Object.values(values);
};

export {Guardian, getGuardianData}
export { Guardian, getGuardianData };
81 changes: 46 additions & 35 deletions src/guardian/helper.ts
Original file line number Diff line number Diff line change
@@ -1,62 +1,73 @@
import {EventData} from "../models/events.interface";

import { EventData } from '../models/events.interface';

const hash = async (eventData: EventData): Promise<string> => {
const digest = await crypto.subtle.digest('SHA-512', new TextEncoder().encode(JSON.stringify(eventData)))
const digest = await crypto.subtle.digest(
'SHA-512',
new TextEncoder().encode(JSON.stringify(eventData))
);

return window.btoa(unescape(encodeURIComponent(new TextDecoder().decode(digest))))
}
return window.btoa(unescape(encodeURIComponent(new TextDecoder().decode(digest))));
};

const localStorageLockTimeout = 10
const localStorageLockTimeout = 10;

const setLocalStorage = (key: string, value: Record<string, any> | string, ttl = -1) => {
waitUtilUnlocked(key)
localStorage.setItem(key, JSON.stringify({expr: ttl > 0 ? +(new Date(ttl + +(new Date()))) : ttl, value: value}))
invalidateMutex(key)
}
waitUtilUnlocked(key);
localStorage.setItem(
key,
JSON.stringify({ expr: ttl > 0 ? +new Date(ttl + +new Date()) : ttl, value: value })
);
invalidateMutex(key);
};

const updateLocalStorage = (key: string, update: (v: string | null) => any, ttl = -1) => {
waitUtilUnlocked(key)
localStorage.setItem(key, JSON.stringify({expr: ttl > 0 ? +(new Date(ttl + +(new Date()))) : ttl, value: update(localStorage.getItem(key))}))
invalidateMutex(key)
}
waitUtilUnlocked(key);
localStorage.setItem(
key,
JSON.stringify({
expr: ttl > 0 ? +new Date(ttl + +new Date()) : ttl,
value: update(localStorage.getItem(key))
})
);
invalidateMutex(key);
};

const getLocalStorage = (key: string): any => {
waitUtilUnlocked(key)
const item = localStorage.getItem(key)
waitUtilUnlocked(key);
const item = localStorage.getItem(key);
if (!item) {
invalidateMutex(key)
return null
invalidateMutex(key);
return null;
}
const parsed = JSON.parse(item) as { expr: number; value: any }
if (parsed.expr >= 0 && parsed.expr < +(new Date())) {
localStorage.removeItem(key)
invalidateMutex(key)
return null
const parsed = JSON.parse(item) as { expr: number; value: any };
if (parsed.expr >= 0 && parsed.expr < +new Date()) {
localStorage.removeItem(key);
invalidateMutex(key);
return null;
}
invalidateMutex(key)
return parsed.value
}
invalidateMutex(key);
return parsed.value;
};

function invalidateMutex(key: string) {
localStorage.removeItem(key + '-mutex')
localStorage.removeItem(key + '-mutex');
}

const waitUtilUnlocked = (key: string) => {
let i = 0
let i = 0;
// eslint-disable-next-line no-constant-condition
while (true) {
if (!localStorage.getItem(key + '-mutex')) {
localStorage.setItem(key + '-mutex', 'true')
break
localStorage.setItem(key + '-mutex', 'true');
break;
}
setTimeout(() => ({}), localStorageLockTimeout)
setTimeout(() => ({}), localStorageLockTimeout);
if (i > 1000) {
invalidateMutex(key);
throw new Error("local storage timeout exceeded")
throw new Error('local storage timeout exceeded');
}
i++
i++;
}
}
};

export {hash, setLocalStorage, updateLocalStorage, getLocalStorage}
export { hash, setLocalStorage, updateLocalStorage, getLocalStorage };
106 changes: 55 additions & 51 deletions src/guardian/utm.ts
Original file line number Diff line number Diff line change
@@ -1,88 +1,92 @@
import * as queryString from 'query-string'
import {Event, EventData} from "../models/events.interface";
import {getLocalStorage, hash, setLocalStorage, updateLocalStorage} from "./helper";
import {defaultClearPeriod, localStorageKey} from "./guardian";
import * as queryString from 'query-string';
import { Event, EventData } from '../models/events.interface';
import { getLocalStorage, hash, setLocalStorage, updateLocalStorage } from './helper';
import { defaultClearPeriod, localStorageKey } from './guardian';

const utmSuffix = "_last"
const previousElementTTL = 10800000
const utmSuffix = '_last';
const previousElementTTL = 10800000;

const utmSourceListener = () => {
const key = 'utm_source'
const lastUTM = getLocalStorage(key + utmSuffix)
const utmParam = queryString.parse(location.search)[key]
const key = 'utm_source';
const lastUTM = getLocalStorage(key + utmSuffix);
const utmParam = queryString.parse(location.search)[key];
if (utmParam && typeof utmParam === 'string') {
setLocalStorage(key + utmSuffix, utmParam, previousElementTTL)
onUrlChange(key, lastUTM, utmParam)
setLocalStorage(key + utmSuffix, utmParam, previousElementTTL);
onUrlChange(key, lastUTM, utmParam);
}
}
};

const utmMediumListener = () => {
const key = 'utm_medium'
const lastUTM = getLocalStorage(key + utmSuffix)
const utmParam = queryString.parse(location.search)[key]
const key = 'utm_medium';
const lastUTM = getLocalStorage(key + utmSuffix);
const utmParam = queryString.parse(location.search)[key];
if (utmParam && typeof utmParam === 'string') {
setLocalStorage(key + utmSuffix, utmParam, previousElementTTL)
onUrlChange(key, lastUTM, utmParam)
setLocalStorage(key + utmSuffix, utmParam, previousElementTTL);
onUrlChange(key, lastUTM, utmParam);
}
}
};

const utmCampaignListener = () => {
const key = 'utm_campaign'
const lastUTM = getLocalStorage(key + utmSuffix)
const utmParam = queryString.parse(location.search)[key]
const key = 'utm_campaign';
const lastUTM = getLocalStorage(key + utmSuffix);
const utmParam = queryString.parse(location.search)[key];
if (utmParam && typeof utmParam === 'string') {
setLocalStorage(key + utmSuffix, utmParam, previousElementTTL)
onUrlChange(key, lastUTM, utmParam)
setLocalStorage(key + utmSuffix, utmParam, previousElementTTL);
onUrlChange(key, lastUTM, utmParam);
}
}
};

const utmTerm = () => {
const key = 'utm_term'
const lastUTM = getLocalStorage(key + utmSuffix)
const utmParam = queryString.parse(location.search)[key]
const key = 'utm_term';
const lastUTM = getLocalStorage(key + utmSuffix);
const utmParam = queryString.parse(location.search)[key];
if (utmParam && typeof utmParam === 'string') {
setLocalStorage(key + utmSuffix, utmParam, previousElementTTL)
onUrlChange(key, lastUTM, utmParam)
setLocalStorage(key + utmSuffix, utmParam, previousElementTTL);
onUrlChange(key, lastUTM, utmParam);
}
}
};

const utmContent = () => {
const key = 'utm_content'
const lastUTM = getLocalStorage(key + utmSuffix)
const utmParam = queryString.parse(location.search)[key]
const key = 'utm_content';
const lastUTM = getLocalStorage(key + utmSuffix);
const utmParam = queryString.parse(location.search)[key];
if (utmParam && typeof utmParam === 'string') {
setLocalStorage(key + utmSuffix, utmParam, previousElementTTL)
onUrlChange(key, lastUTM, utmParam)
setLocalStorage(key + utmSuffix, utmParam, previousElementTTL);
onUrlChange(key, lastUTM, utmParam);
}
}
};

const onUrlChange = (key: string, lastUtm: string | null, utmParam: string) => {
if (lastUtm && lastUtm === utmParam) {
return
return;
}
const eventData = {
type: !lastUtm ? key + '_detected' : key + '_changed',
action: {
value: utmParam
}
} as EventData
} as EventData;

hash(eventData).then((h: string) => {
const event = {
hash: h,
created_at: new Date().getTime(),
data: eventData
} as Event
updateLocalStorage(localStorageKey, (v: string | null) => {
let result = {} as Record<string, any>
if (v) {
const parsed = JSON.parse(v) as { expr: number; value: Record<string, any> }
result = parsed.value
}
result[h] = event
return result
}, defaultClearPeriod)
})
}
} as Event;
updateLocalStorage(
localStorageKey,
(v: string | null) => {
let result = {} as Record<string, any>;
if (v) {
const parsed = JSON.parse(v) as { expr: number; value: Record<string, any> };
result = parsed.value;
}
result[h] = event;
return result;
},
defaultClearPeriod
);
});
};

export {utmSourceListener,utmMediumListener,utmCampaignListener,utmTerm,utmContent}
export { utmSourceListener, utmMediumListener, utmCampaignListener, utmTerm, utmContent };
4 changes: 2 additions & 2 deletions src/main.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
import {Guardian} from "./guardian/guardian";
import { Guardian } from './guardian/guardian';

new Guardian().process()
new Guardian().process();
10 changes: 5 additions & 5 deletions src/models/events.interface.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
export interface Event {
data: EventData
created_at: number
hash: string
data: EventData;
created_at: number;
hash: string;
}

export interface EventData {
type: string
action: Record<string, any>
type: string;
action: Record<string, any>;
}
8 changes: 4 additions & 4 deletions src/models/guardian.interface.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
export interface GuardianBuilder {
url: string
apiKey: string
type: string
clearPeriod?: number
url: string;
apiKey: string;
type: string;
clearPeriod?: number;
}
5 changes: 1 addition & 4 deletions tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,5 @@
"src/**/*.ts",
"scripts/**/*.ts"
],
"exclude": [
"scripts/*",
"src/sift/sift.js"
]
"exclude": ["scripts/*", "src/sift/sift.js"]
}

0 comments on commit a4b90d5

Please sign in to comment.