Skip to content
This repository has been archived by the owner on Jan 27, 2025. It is now read-only.

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
mschuwalow committed Sep 15, 2023
1 parent c4237d0 commit 0c9c9cd
Show file tree
Hide file tree
Showing 22 changed files with 274 additions and 168 deletions.
26 changes: 13 additions & 13 deletions src/cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,19 @@ export type StorageHandlerBackedCacheOpts = {
defaultExpirationHours?: number
}

export type MakeCacheOpts = StorageHandlerBackedCacheOpts & {
strategy: StorageStrategy,
}

export function makeCache(opts: MakeCacheOpts): DurableCache {
if (!strEqualsIgnoreCase(opts.strategy, StorageStrategies.cookie) && strEqualsIgnoreCase(opts.strategy, StorageStrategies.none)) {
return NoOpCache
} else {
// TODO: Remove once we validate config properly
const strategyWithDefault = opts.strategy ?? StorageStrategies.cookie
return new StorageHandlerBackedCache({ ...opts, strategy: strategyWithDefault })
}
}
// export type MakeCacheOpts = StorageHandlerBackedCacheOpts & {
// strategy: StorageStrategy,
// }

// export function makeCache(opts: MakeCacheOpts): DurableCache {
// if (!strEqualsIgnoreCase(opts.strategy, StorageStrategies.cookie) && strEqualsIgnoreCase(opts.strategy, StorageStrategies.none)) {
// return NoOpCache
// } else {
// // TODO: Remove once we validate config properly
// const strategyWithDefault = opts.strategy ?? StorageStrategies.cookie
// return new StorageHandlerBackedCache({ ...opts, strategy: strategyWithDefault })
// }
// }

export class StorageHandlerBackedCache implements DurableCache {
private handler
Expand Down
29 changes: 29 additions & 0 deletions src/enrichers/cache.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { strEqualsIgnoreCase } from "live-connect-common";
import { DurableCache, NoOpCache, StorageHandlerBackedCache } from "../cache";
import { WrappedStorageHandler } from "../handlers/storage-handler";
import { StorageStrategies, StorageStrategy } from "../model/storage-strategy";
import { Enricher } from "../types";

type Input = { domain: string, storageHandler: WrappedStorageHandler, storageStrategy: StorageStrategy }
type Output = { cache: DurableCache }

export const enrichCache: Enricher<Input, Output> = state => {
let cache

if (strEqualsIgnoreCase(state.storageStrategy, StorageStrategies.cookie) && strEqualsIgnoreCase(state.storageStrategy, StorageStrategies.none)) {
cache = NoOpCache
} else if (strEqualsIgnoreCase(state.storageStrategy, StorageStrategies.ls)) {
cache = new StorageHandlerBackedCache({
strategy: 'ls',
storageHandler: state.storageHandler,
domain: state.domain,
})
} else {
cache = new StorageHandlerBackedCache({
strategy: 'cookie',
storageHandler: state.storageHandler,
domain: state.domain,
})
}
return { ...state, cache }
}
11 changes: 11 additions & 0 deletions src/enrichers/call-handler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { CallHandler, EventBus } from "live-connect-common"
import { WrappedCallHandler } from "../handlers/call-handler"
import { Enricher } from "../types"

type Input = { callHandler: CallHandler, eventBus: EventBus }
type Output = { callHandler: WrappedCallHandler }

export const enrichCallHandler: Enricher<Input, Output> = state => {
const callHandler = new WrappedCallHandler(state.callHandler, state.eventBus)
return { ...state, callHandler }
}
14 changes: 9 additions & 5 deletions src/manager/decisions.ts → src/enrichers/decisions.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { getQueryParameter, ParsedParam } from '../utils/url'
import { trim, isUUID, expiresInDays } from 'live-connect-common'
import { EventBus, State } from '../types'
import { Enricher, EventBus, State } from '../types'
import { WrappedStorageHandler } from '../handlers/storage-handler'

const DEFAULT_DECISION_ID_COOKIE_EXPIRES = expiresInDays(30)
Expand All @@ -10,7 +10,11 @@ const DECISION_ID_COOKIE_NAMESPACE = 'lidids.'
const _onlyUnique = (value: string, index: number, self: string[]) => self.indexOf(value) === index
const _nonEmpty = (value: string) => value && trim(value).length > 0

export function resolve(state: State, storageHandler: WrappedStorageHandler, eventBus: EventBus): State {
type Input = { storageHandler: WrappedStorageHandler, eventBus: EventBus, pageUrl?: string, domain: string }
type Output = { decisionIds: string[] }

export const enrichDecisionIds: Enricher<Input, Output> = state => {
const { storageHandler, eventBus, pageUrl, domain } = state
function _addDecisionId(key: string, cookieDomain?: string) {
if (key) {
storageHandler.setCookie(
Expand All @@ -34,7 +38,7 @@ export function resolve(state: State, storageHandler: WrappedStorageHandler, eve
const freshDecisions = _orElseEmtpy(
'Error while extracting new decision ids',
() => {
const extractedFreshDecisions = ([] as ParsedParam[]).concat((state.pageUrl && getQueryParameter(state.pageUrl, DECISION_ID_QUERY_PARAM_NAME)) || [])
const extractedFreshDecisions = ([] as ParsedParam[]).concat((pageUrl && getQueryParameter(pageUrl, DECISION_ID_QUERY_PARAM_NAME)) || [])
return extractedFreshDecisions
.map(trim)
.filter(_nonEmpty)
Expand All @@ -56,11 +60,11 @@ export function resolve(state: State, storageHandler: WrappedStorageHandler, eve

freshDecisions.forEach(decision => {
try {
_addDecisionId(decision, state.domain)
_addDecisionId(decision, domain)
} catch (e) {
eventBus.emitErrorWithMessage('DecisionsResolve', 'Error while storing new decision id', e)
}
})

return { decisionIds: freshDecisions.concat(storedDecisions).filter(_onlyUnique) }
return { ...state, decisionIds: freshDecisions.concat(storedDecisions).filter(_onlyUnique) }
}
9 changes: 9 additions & 0 deletions src/enrichers/domain.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { WrappedStorageHandler } from "../handlers/storage-handler"
import { Enricher } from "../types"
import { determineHighestAccessibleDomain } from "../utils/domain"

type Input = { storageHandler: WrappedStorageHandler }
type Output = { domain: string }

export const enrichDomain: Enricher<Input, Output> = state =>
({ ...state, domain: determineHighestAccessibleDomain(state.storageHandler) })
10 changes: 10 additions & 0 deletions src/enrichers/error-pixel.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { EventBus } from "live-connect-common";
import { Enricher } from "../types";
import { register } from "../events/error-pixel";
import { WrappedCallHandler } from "../handlers/call-handler";

type Input = { eventBus: EventBus, domain: string, callHandler: WrappedCallHandler }

export const enrichErrorPixel: Enricher<Input, {}> = ({ eventBus, domain, callHandler }) => {
register(eventBus, domain, callHandler)
}
22 changes: 11 additions & 11 deletions src/enrichers/identifiers-nohash.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,22 @@
import { containsEmailField, isEmail } from '../utils/email'
import { safeToString, isArray, trim } from 'live-connect-common'
import { EventBus, RetrievedIdentifier, State } from '../types'
import { Enricher, EventBus, RetrievedIdentifier, State } from '../types'
import { WrappedReadOnlyStorageHandler } from '../handlers/storage-handler'

export function enrich(state: State, storageHandler: WrappedReadOnlyStorageHandler, eventBus: EventBus): State {
type Input = {identifiersToResolve: string | string[], storageHandler: WrappedReadOnlyStorageHandler, eventBus: EventBus}
type Output = {retrievedIdentifiers: RetrievedIdentifier[]}

export const enrichIdentifiers: Enricher<Input, Output> = state => {
try {
return _parseIdentifiersToResolve(state, storageHandler)
return { ...state, retrievedIdentifiers: resolveIdentifiers(state.identifiersToResolve, state.storageHandler) }
} catch (e) {
eventBus.emitError('IdentifiersEnrich', e)
return {}
state.eventBus.emitError('IdentifiersEnrich', e)
return { ...state, retrievedIdentifiers: [] }
}
}

function _parseIdentifiersToResolve(state: State, storageHandler: WrappedReadOnlyStorageHandler): State {
state.identifiersToResolve = state.identifiersToResolve || []
const cookieNames = isArray(state.identifiersToResolve) ? state.identifiersToResolve : safeToString(state.identifiersToResolve).split(',')
function resolveIdentifiers(identifiersToResolve: string | string[], storageHandler: WrappedReadOnlyStorageHandler): RetrievedIdentifier[] {
const cookieNames = isArray(identifiersToResolve) ? identifiersToResolve : safeToString(identifiersToResolve).split(',')
const identifiers: RetrievedIdentifier[] = []
for (let i = 0; i < cookieNames.length; i++) {
const identifierName = trim(cookieNames[i])
Expand All @@ -26,7 +28,5 @@ function _parseIdentifiersToResolve(state: State, storageHandler: WrappedReadOnl
})
}
}
return {
retrievedIdentifiers: identifiers
}
return identifiers
}
33 changes: 17 additions & 16 deletions src/enrichers/identifiers.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,27 @@
import { replaceEmailsWithHashes } from '../utils/email'
import { safeToString, isString, isArray } from 'live-connect-common'
import { EventBus, HashedEmail, State, RetrievedIdentifier } from '../types'
import { EventBus, HashedEmail, State, RetrievedIdentifier, Enricher } from '../types'
import { WrappedReadOnlyStorageHandler } from '../handlers/storage-handler'

export function enrich(state: State, storageHandler: WrappedReadOnlyStorageHandler, eventBus: EventBus): State {
type Input = { identifiersToResolve: string | string[], storageHandler: WrappedReadOnlyStorageHandler, eventBus: EventBus }
type Output = { retrievedIdentifiers: RetrievedIdentifier[], hashesFromIdentifiers: HashedEmail[] }

export const enrichIdentifiers: Enricher<Input, Output> = state => {
try {
return _getIdentifiers(_parseIdentifiersToResolve(state), storageHandler)
return { ...state, ...getIdentifiers(parseIdentifiersToResolve(state.identifiersToResolve), state.storageHandler) }
} catch (e) {
if (eventBus) {
eventBus.emitError('IdentifiersEnricher', e)
}
return {}
state.eventBus.emitError('IdentifiersEnricher', e)
return { ...state, retrievedIdentifiers: [], hashesFromIdentifiers: [] }
}
}

function _parseIdentifiersToResolve(state: State): string[] {
function parseIdentifiersToResolve(identifiersToResolve: string | string[]): string[] {
let cookieNames: string[] = []
if (state.identifiersToResolve) {
if (isArray(state.identifiersToResolve)) {
cookieNames = state.identifiersToResolve as string[]
} else if (isString(state.identifiersToResolve)) {
cookieNames = (state.identifiersToResolve as string).split(',')
if (identifiersToResolve) {
if (isArray(identifiersToResolve)) {
cookieNames = identifiersToResolve as string[]
} else if (isString(identifiersToResolve)) {
cookieNames = (identifiersToResolve as string).split(',')
}
}
for (let i = 0; i < cookieNames.length; i++) {
Expand All @@ -29,7 +30,7 @@ function _parseIdentifiersToResolve(state: State): string[] {
return cookieNames
}

function _getIdentifiers(cookieNames: string[], storageHandler: WrappedReadOnlyStorageHandler): State {
function getIdentifiers(cookieNames: string[], storageHandler: WrappedReadOnlyStorageHandler): Output {
const identifiers: RetrievedIdentifier[] = []
let hashes: HashedEmail[] = []
for (let i = 0; i < cookieNames.length; i++) {
Expand All @@ -46,11 +47,11 @@ function _getIdentifiers(cookieNames: string[], storageHandler: WrappedReadOnlyS
}
return {
retrievedIdentifiers: identifiers,
hashesFromIdentifiers: _deduplicateHashes(hashes)
hashesFromIdentifiers: deduplicateHashes(hashes)
}
}

function _deduplicateHashes(hashes: HashedEmail[]): HashedEmail[] {
function deduplicateHashes(hashes: HashedEmail[]): HashedEmail[] {
const seen = new Set<string>()
const result: HashedEmail[] = []
for (let i = 0; i < hashes.length; i++) {
Expand Down
20 changes: 10 additions & 10 deletions src/manager/identifiers.ts → src/enrichers/live-connect-id.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,27 @@
import { ulid } from '../utils/ulid'
import { loadedDomain } from '../utils/page'
import { domainHash } from '../utils/hash'
import { expiresInDays } from 'live-connect-common'
import { PEOPLE_VERIFIED_LS_ENTRY } from '../utils/consts'
import { EventBus, State } from '../types'
import { Enricher, EventBus } from '../types'
import { WrappedStorageHandler } from '../handlers/storage-handler'
import { DurableCache } from '../cache'

const NEXT_GEN_FP_NAME = '_lc2_fpi'
const DEFAULT_EXPIRATION_DAYS = 730

export function resolve(
state: { expirationDays?: number, domain: string },
storageHandler: WrappedStorageHandler,
cache: DurableCache,
eventBus: EventBus
): State {
const expiry = state.expirationDays || DEFAULT_EXPIRATION_DAYS
type Input = { expirationDays?: number, domain: string, cache: DurableCache, storageHandler: WrappedStorageHandler }
type Output = { liveConnectId?: string, peopleVerifiedId?: string }

export const enrichLiveConnectId: Enricher<Input, Output> = state => {
const {expirationDays, domain, storageHandler, cache } = state

const expiry = expirationDays || DEFAULT_EXPIRATION_DAYS
const oldValue = cache.get(NEXT_GEN_FP_NAME)?.data

if (oldValue) {
cache.set(NEXT_GEN_FP_NAME, oldValue, expiresInDays(expiry))
} else {
const newValue = `${domainHash(state.domain)}--${ulid()}`
const newValue = `${domainHash(domain)}--${ulid()}`

cache.set(NEXT_GEN_FP_NAME, newValue, expiresInDays(expiry))
}
Expand All @@ -34,6 +33,7 @@ export function resolve(
}

return {
...state,
liveConnectId: liveConnectIdentifier,
peopleVerifiedId: liveConnectIdentifier
}
Expand Down
23 changes: 10 additions & 13 deletions src/enrichers/page.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,15 @@
import { State } from '../types'
import { Enricher } from '../types'
import { getPage, getReferrer, getContextElements } from '../utils/page'

let _currentPage: State | null = null
type Input = { privacyMode: boolean, contextSelectors: string, contextElementsLength: number }
type Output = { pageUrl?: string, referrer?: string, contextElements: string }

export function enrich(state: State): State {
if (_currentPage) {
return _currentPage
} else {
const result = {
pageUrl: getPage(),
referrer: getReferrer(),
contextElements: getContextElements(state.privacyMode, state.contextSelectors, state.contextElementsLength)
}
_currentPage = result
return result
export const enrichPage: Enricher<Input, Output> = state => {
return {
...state,
pageUrl: getPage(),
referrer: getReferrer(),
contextElements: getContextElements(state.privacyMode, state.contextSelectors, state.contextElementsLength)
}
}

19 changes: 19 additions & 0 deletions src/enrichers/people-verified-id.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { PEOPLE_VERIFIED_LS_ENTRY } from '../utils/consts'
import { Enricher, EventBus } from '../types'
import { WrappedReadOnlyStorageHandler } from '../handlers/storage-handler'

type Input = { peopleVerifiedId?: string, storageHandler: WrappedReadOnlyStorageHandler, eventBus: EventBus }
type Output = { peopleVerifiedId?: string }

export const enrichPeopleVerifiedId: Enricher<Input, Output> = state => {
try {
return {
...state,
peopleVerifiedId: state.peopleVerifiedId || state.storageHandler.getDataFromLocalStorage(PEOPLE_VERIFIED_LS_ENTRY) || undefined
}
} catch (e) {
state.eventBus.emitError('PeopleVerifiedEnrich', e)
return state
}
}

12 changes: 0 additions & 12 deletions src/enrichers/people-verified.ts

This file was deleted.

16 changes: 6 additions & 10 deletions src/enrichers/privacy-config.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
import { State } from '../types'
import { isNonEmpty } from 'live-connect-common'
import { Enricher } from '../types'

export function enrich(state: State): State {
if (isNonEmpty(state) && isNonEmpty(state.gdprApplies)) {
const privacyMode = !!state.gdprApplies
return {
privacyMode
}
} else return {}
}
type Input = { gdprApplies?: boolean }
type Output = { privacyMode: boolean }

export const enrichPrivacyMode: Enricher<Input, Output> = state =>
({ ...state, privacyMode: !!state.gdprApplies })
20 changes: 20 additions & 0 deletions src/enrichers/storage-handler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { EventBus, ReadOnlyStorageHandler, StorageHandler } from "live-connect-common";
import { StorageStrategy } from "../model/storage-strategy";
import { Enricher } from "../types";
import { WrappedReadOnlyStorageHandler, WrappedStorageHandler } from "../handlers/storage-handler";

type InputReadOnly = { storageStrategy: StorageStrategy, storageHandler: ReadOnlyStorageHandler, eventBus: EventBus }
type OutputReadOnly = { storageHandler: WrappedReadOnlyStorageHandler }

export const enrichReadOnlyStorageHandler: Enricher<InputReadOnly, OutputReadOnly> = state => {
const storageHandler = WrappedReadOnlyStorageHandler.make(state.storageStrategy, state.storageHandler, state.eventBus)
return { ...state, storageHandler }
}

type Input = { storageStrategy: StorageStrategy, storageHandler: StorageHandler, eventBus: EventBus }
type Output = { storageHandler: WrappedStorageHandler }

export const enrichStorageHandler: Enricher<Input, Output> = state => {
const storageHandler = WrappedStorageHandler.make(state.storageStrategy, state.storageHandler, state.eventBus)
return { ...state, storageHandler }
}
Loading

0 comments on commit 0c9c9cd

Please sign in to comment.