salsify-experiences-sdk
Version:
SDK to be used by commerce websites to implement product experiences.
81 lines (66 loc) • 2.26 kB
text/typescript
import request from '../request'
import SdkSettings from '../../settings'
import { Context } from '../../api'
import Timeout from '../timeout'
const stagingBaseUrl = 'https://retail-client-events-service-staging.internal.salsify.com'
const stagingEventsEndpoint = `${stagingBaseUrl}/events`
const prodBaseUrl = 'https://retail-client-events-service.internal.salsify.com'
const prodEventsEndpoint = `${prodBaseUrl}/events`
interface Event {
code: string
properties: Record<string, unknown>
timestamp: number
}
const MAX_QUEUE_SIZE = 1000
export default class LogTransport {
#context: Context
#settings: SdkSettings
#eventsEndpoint: string
#queuedEvents: Array<Event> = []
#timeout?: Timeout
public constructor(context: Context, settings: SdkSettings) {
this.#context = context
this.#settings = settings
this.#eventsEndpoint = this.#settings.staging ? stagingEventsEndpoint : prodEventsEndpoint
}
public log(code: string, properties: Record<string, unknown>, context: Record<string, unknown>): void {
const event = {
code: 'sdk_' + code,
properties,
context,
timestamp: Date.now() / 1000,
}
this.#send([event])
}
async #send(logs: Array<Event>): Promise<void> {
const allLogs = [...this.#queuedEvents.splice(0), ...logs]
if (!allLogs.length) return
const payload = {
app: 'sxp_sdk',
channel: this.#context.clientId,
csid: this.#context.sessionId,
pagesessionid: this.#context.pageSessionId,
jsSource: this.#context.jsSource,
timestamp: Date.now() / 1000,
logs: allLogs,
}
let response: Response
try {
response = await request.post(this.#eventsEndpoint, payload)
} catch (e) {
this.#enqueueAndStartTimeout(allLogs)
return
}
if (response.ok) {
this.#timeout?.clear()
} else {
this.#enqueueAndStartTimeout(allLogs)
}
}
#enqueueAndStartTimeout(logs: Array<Event>): void {
if (this.#queuedEvents.length >= MAX_QUEUE_SIZE) return
this.#queuedEvents.push(...logs.splice(0, MAX_QUEUE_SIZE - this.#queuedEvents.length))
if (!this.#timeout) this.#timeout = new Timeout()
this.#timeout.start(() => this.#send(this.#queuedEvents.splice(0)))
}
}