All files / src/worker scripts.ts

100% Statements 7/7
100% Branches 0/0
100% Functions 4/4
100% Lines 7/7

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64        5x             5x     3x                         2x     2x       2x                                     2x                    
import { Script } from '../shared/scripts'
import { CacheOptions, createResponseWithMaxAge } from './utils/cache'
import { resolveTemplates } from './utils/string'
 
export const workerScriptsCacheOptions: CacheOptions = {
  // Cache in the browser up to 1 minute. Longer cache might cause unnecessary delay if Flow options are modified in the dashboard.
  maxAge: 60,
  // CDN and worker should cache up to 1 minute. Same as above.
  sMaxAge: 60,
}
 
export const scripts: Script[] = ['instrumentor.iife.js', 'loader.js', 'agent-processor.iife.js']
 
export function getScriptUrl(script: Script, routePrefix: string) {
  return `/${routePrefix}/${script}`
}
 
/**
 * Injects a script into the `<head>` element of an HTML document to load the agent processor
 * with specified agent data as a data attribute.
 *
 * @param {Response} response - The HTTP response containing the HTML content to modify.
 * @param {string} agentData - The agent-specific data to be injected as a data attribute in the script.
 * @param {string} routePrefix - The route prefix used to construct the script's source URL.
 * @return {Response} - A transformed HTTP response with the injected agent processor script.
 */
export function injectAgentProcessorScript(response: Response, agentData: string, routePrefix: string): Response {
  return new HTMLRewriter()
    .on('head', {
      element(element) {
        console.info('Injecting agent processor script into <head> element.')
 
        // Append script that loads the agent processor. Injects agent data as a data attribute.
        // Injected as an ` async ` script, since it doesn't depend on DOM structure and can be loaded in the background.
        element.append(
          `<script data-agent-data="${agentData}" async src="${getScriptUrl('agent-processor.iife.js', routePrefix)}"></script>\n`,
          {
            html: true,
          }
        )
      },
    })
    .transform(response)
}
 
/**
 * Creates a response object for a worker script with resolved templates and appropriate headers.
 *
 * @param {string} code - The JavaScript code for the worker script, containing templates to resolve.
 * @param {Record<string, string>} variables - A record of key-value pairs used to resolve templates in the code.
 * @return {Response} A Response object with the resolved JavaScript code and applicable headers.
 */
export function createWorkerScriptResponse(code: string, variables: Record<string, string>): Response {
  return createResponseWithMaxAge(
    new Response(resolveTemplates(code, variables), {
      headers: {
        'Content-Type': 'application/javascript',
      },
    }),
    workerScriptsCacheOptions,
    'set'
  )
}