generated from chiffre-io/template-library
-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Exported code from monorepo
- Loading branch information
Showing
8 changed files
with
295 additions
and
31 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,13 @@ | ||
# @chiffre/template-library | ||
# @chiffre/analytics-core | ||
|
||
[![NPM](https://img.shields.io/npm/v/@chiffre/template-library?color=red)](https://www.npmjs.com/package/@chiffre/template-library) | ||
[![MIT License](https://img.shields.io/github/license/chiffre-io/template-library.svg?color=blue)](https://github.com/chiffre-io/template-library/blob/next/LICENSE) | ||
[![Continuous Integration](https://github.com/chiffre-io/template-library/workflows/Continuous%20Integration/badge.svg?branch=next)](https://github.com/chiffre-io/template-library/actions) | ||
[![Coverage Status](https://coveralls.io/repos/github/chiffre-io/template-library/badge.svg?branch=next)](https://coveralls.io/github/chiffre-io/template-library?branch=next) | ||
[![Dependabot Status](https://api.dependabot.com/badges/status?host=github&repo=chiffre-io/template-library)](https://dependabot.com) | ||
[![NPM](https://img.shields.io/npm/v/@chiffre/analytics-core?color=red)](https://www.npmjs.com/package/@chiffre/analytics-core) | ||
[![MIT License](https://img.shields.io/github/license/chiffre-io/analytics-core.svg?color=blue)](https://github.com/chiffre-io/analytics-core/blob/next/LICENSE) | ||
[![Continuous Integration](https://github.com/chiffre-io/analytics-core/workflows/Continuous%20Integration/badge.svg?branch=next)](https://github.com/chiffre-io/analytics-core/actions) | ||
[![Coverage Status](https://coveralls.io/repos/github/chiffre-io/analytics-core/badge.svg?branch=next)](https://coveralls.io/github/chiffre-io/analytics-core?branch=next) | ||
[![Dependabot Status](https://api.dependabot.com/badges/status?host=github&repo=chiffre-io/analytics-core)](https://dependabot.com) | ||
|
||
Template for Chiffre libraries | ||
Types & definitions for Chiffre Analytics | ||
|
||
## License | ||
|
||
[MIT](https://github.com/chiffre-io/template-library/blob/next/LICENSE) - Made with ❤️ by [François Best](https://francoisbest.com). | ||
[MIT](https://github.com/chiffre-io/analytics-core/blob/next/LICENSE) - Made with ❤️ by [François Best](https://francoisbest.com). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
import { SessionData } from './session' | ||
import { PageVisitData } from './navigation' | ||
|
||
export interface Event<T, K extends keyof T> { | ||
type: K | ||
time: number | ||
data?: T[K] | ||
} | ||
|
||
// --- | ||
|
||
export interface GenericDataPoint<T, Meta = any> { | ||
name: string | ||
value: T | ||
meta?: Meta | ||
} | ||
|
||
export type GenericEvents = { | ||
'generic:number': GenericDataPoint<number> | ||
'generic:numbers': GenericDataPoint<number>[] | ||
'generic:string': GenericDataPoint<string> | ||
'generic:strings': GenericDataPoint<string>[] | ||
} | ||
export type GenericEvent = Event<GenericEvents, keyof GenericEvents> | ||
|
||
export function isGenericEvent(event: AllEvents): event is GenericEvent { | ||
return ( | ||
isGenericNumberEvent(event) || | ||
isGenericNumbersEvent(event) || | ||
isGenericStringEvent(event) || | ||
isGenericStringsEvent(event) | ||
) | ||
} | ||
export function isGenericNumberEvent( | ||
event: AllEvents | ||
): event is Event<GenericEvents, 'generic:number'> { | ||
return event.type === 'generic:number' | ||
} | ||
export function isGenericNumbersEvent( | ||
event: AllEvents | ||
): event is Event<GenericEvents, 'generic:numbers'> { | ||
return event.type === 'generic:numbers' | ||
} | ||
export function isGenericStringEvent( | ||
event: AllEvents | ||
): event is Event<GenericEvents, 'generic:string'> { | ||
return event.type === 'generic:string' | ||
} | ||
export function isGenericStringsEvent( | ||
event: AllEvents | ||
): event is Event<GenericEvents, 'generic:strings'> { | ||
return event.type === 'generic:strings' | ||
} | ||
|
||
// -- | ||
|
||
export interface BrowserEventData { | ||
sid: string | ||
path: string | ||
} | ||
|
||
export type BrowserDataPoint<T = {}> = BrowserEventData & T | ||
|
||
export type BrowserEvents = { | ||
'session:start': BrowserDataPoint<SessionData> | ||
'session:dnt': never | ||
'session:end': BrowserDataPoint | ||
'page:visit': BrowserDataPoint<PageVisitData> | ||
'page:hide': BrowserDataPoint | ||
'page:show': BrowserDataPoint | ||
} | ||
export type BrowserEvent = Event<BrowserEvents, keyof BrowserEvents> | ||
|
||
export function isBrowserEvent(event: AllEvents): event is BrowserEvent { | ||
return ( | ||
isSessionStartEvent(event) || | ||
isSessionEndEvent(event) || | ||
isPageVisitEvent(event) || | ||
isPageHideEvent(event) || | ||
isPageShowEvent(event) | ||
) | ||
} | ||
export function isSessionStartEvent( | ||
event: AllEvents | ||
): event is Event<BrowserEvents, 'session:start'> { | ||
return event.type === 'session:start' | ||
} | ||
export function isSessionDNTEvent( | ||
event: AllEvents | ||
): event is Event<BrowserEvents, 'session:dnt'> { | ||
return event.type === 'session:dnt' | ||
} | ||
export function isSessionEndEvent( | ||
event: AllEvents | ||
): event is Event<BrowserEvents, 'session:end'> { | ||
return event.type === 'session:end' | ||
} | ||
export function isPageVisitEvent( | ||
event: AllEvents | ||
): event is Event<BrowserEvents, 'page:visit'> { | ||
return event.type === 'page:visit' | ||
} | ||
export function isPageHideEvent( | ||
event: AllEvents | ||
): event is Event<BrowserEvents, 'page:hide'> { | ||
return event.type === 'page:hide' | ||
} | ||
export function isPageShowEvent( | ||
event: AllEvents | ||
): event is Event<BrowserEvents, 'page:show'> { | ||
return event.type === 'page:show' | ||
} | ||
|
||
function eventFactory<Events>() { | ||
return function createEvent<K extends keyof Events>( | ||
type: K, | ||
data?: Events[K] | ||
): Event<Events, K> { | ||
return { | ||
type, | ||
time: Date.now(), | ||
data | ||
} | ||
} | ||
} | ||
|
||
export const createGenericEvent = eventFactory<GenericEvents>() | ||
export const createBrowserEvent = eventFactory<BrowserEvents>() | ||
|
||
export type EventSender = <T>(event: Event<T, keyof T>) => void | ||
|
||
export type AllEvents = GenericEvent | BrowserEvent |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,36 @@ | ||
import hello from './index' | ||
import { sessionStart, sessionEnd, pageHide, pageShow } from './session' | ||
import { | ||
isBrowserEvent, | ||
isSessionStartEvent, | ||
isSessionEndEvent, | ||
isPageHideEvent, | ||
isPageShowEvent | ||
} from './events' | ||
|
||
test('testing works', () => { | ||
expect(hello('World')).toEqual('Hello, World !') | ||
test('sessionStart', () => { | ||
const event = sessionStart() | ||
expect(event.type).toEqual('session:start') | ||
expect(isBrowserEvent(event)).toEqual(true) | ||
expect(isSessionStartEvent(event)).toEqual(true) | ||
}) | ||
|
||
test('sessionEnd', () => { | ||
const event = sessionEnd() | ||
expect(event.type).toEqual('session:end') | ||
expect(isBrowserEvent(event)).toEqual(true) | ||
expect(isSessionEndEvent(event)).toEqual(true) | ||
}) | ||
|
||
test('pageHide', () => { | ||
const event = pageHide() | ||
expect(event.type).toEqual('page:hide') | ||
expect(isBrowserEvent(event)).toEqual(true) | ||
expect(isPageHideEvent(event)).toEqual(true) | ||
}) | ||
|
||
test('pageShow', () => { | ||
const event = pageShow() | ||
expect(event.type).toEqual('page:show') | ||
expect(isBrowserEvent(event)).toEqual(true) | ||
expect(isPageShowEvent(event)).toEqual(true) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,3 @@ | ||
export default (name: string) => `Hello, ${name} !` | ||
export * from './events' | ||
export * from './session' | ||
export * from './navigation' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import { createBrowserEvent, EventSender } from './events' | ||
import { sessionID } from './session' | ||
|
||
export interface PageVisitData { | ||
from: string | ||
} | ||
|
||
export const setupPageVisitListeners = (send: EventSender) => { | ||
let oldPath = window.location.pathname | ||
|
||
setInterval(() => { | ||
const newPath = window.location.pathname | ||
if (oldPath === newPath) { | ||
return | ||
} | ||
const event = createBrowserEvent(`page:visit`, { | ||
sid: sessionID, | ||
from: oldPath, | ||
path: newPath | ||
}) | ||
oldPath = newPath | ||
send(event) | ||
}, 500) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
import nanoid from 'nanoid' | ||
import { createBrowserEvent, EventSender } from './events' | ||
|
||
export const sessionID = nanoid() | ||
|
||
export interface SessionData { | ||
ua: string // user-agent | ||
os: string // operating system | ||
ref: string // referer | ||
lang: string // language | ||
tzo: number // timezone offset from UTC in minutes | ||
vp: { | ||
// viewport dimensions | ||
w: number | ||
h: number | ||
} | ||
lvd?: string // last visit date, ISO-8601 | ||
} | ||
|
||
export const sessionStart = () => { | ||
const event = createBrowserEvent('session:start', { | ||
ua: navigator.userAgent, | ||
os: navigator.platform, | ||
ref: document.referrer, | ||
lang: navigator.language, | ||
tzo: new Date().getTimezoneOffset(), | ||
vp: { | ||
w: window.innerWidth, | ||
h: window.innerHeight | ||
}, | ||
lvd: window.localStorage.getItem('chiffre:last-visit-date') || undefined, | ||
sid: sessionID, | ||
path: window.location.pathname | ||
}) | ||
window.localStorage.setItem( | ||
'chiffre:last-visit-date', | ||
new Date().toISOString().slice(0, 10) // YYYY-MM-DD | ||
) | ||
return event | ||
} | ||
|
||
export const sessionEnd = () => { | ||
return createBrowserEvent('session:end', { | ||
sid: sessionID, | ||
path: window.location.pathname | ||
}) | ||
} | ||
|
||
export const pageHide = () => { | ||
return createBrowserEvent('page:hide', { | ||
sid: sessionID, | ||
path: window.location.pathname | ||
}) | ||
} | ||
|
||
export const pageShow = () => { | ||
return createBrowserEvent('page:show', { | ||
sid: sessionID, | ||
path: window.location.pathname | ||
}) | ||
} | ||
|
||
export const setupSessionListeners = (send: EventSender) => { | ||
const startEvent = sessionStart() | ||
window.addEventListener('beforeunload', () => { | ||
send(sessionEnd()) | ||
}) | ||
window.addEventListener('visibilitychange', () => { | ||
send(document.hidden ? pageHide() : pageShow()) | ||
}) | ||
send(startEvent) | ||
} |
Oops, something went wrong.