Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 21 additions & 7 deletions src/first-party/auto-inject.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -51,22 +51,36 @@ export function autoInjectProxyEndpoints(
): void {
for (const def of AUTO_INJECT_DEFS) {
const entry = registry[def.registryKey]
if (!entry || typeof entry !== 'object')
if (!entry)
continue

const config = (Array.isArray(entry) ? entry[0] : entry) as Record<string, any>
const rtScripts = runtimeConfig.public?.scripts as Record<string, any> | undefined
const rtEntry = rtScripts?.[def.registryKey]
const rtConfig = rtEntry && typeof rtEntry === 'object'
? (Array.isArray(rtEntry) ? rtEntry[0] : rtEntry)
: undefined

let config: Record<string, any> | undefined
if (entry === true || entry === 'mock') {
config = rtConfig || {}
}
else if (typeof entry === 'object') {
config = (Array.isArray(entry) ? entry[0] : entry) as Record<string, any>
}

if (!config || config[def.configField])
continue

config[def.configField] = def.computeValue(collectPrefix, config)
const value = def.computeValue(collectPrefix, config)
Comment thread
coderabbitai[bot] marked this conversation as resolved.

if (typeof entry === 'object') {
config[def.configField] = value
}

// Propagate to runtimeConfig
const rtScripts = runtimeConfig.public?.scripts as Record<string, any> | undefined
const rtEntry = rtScripts?.[def.registryKey]
if (rtEntry && typeof rtEntry === 'object') {
const rtConfig = Array.isArray(rtEntry) ? rtEntry[0] : rtEntry
if (rtConfig)
rtConfig[def.configField] = config[def.configField]
rtConfig[def.configField] = value
}
}
}
178 changes: 178 additions & 0 deletions test/unit/auto-inject.test.ts
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
import { describe, expect, it } from 'vitest'
import { autoInjectProxyEndpoints } from '../../src/first-party/auto-inject'

function makeRuntimeConfig(scripts: Record<string, any> = {}) {
return { public: { scripts } }
}

describe('autoInjectProxyEndpoints', () => {
describe('object entries', () => {
it('injects apiHost for posthog config object', () => {
const registry: any = { posthog: { apiKey: 'phc_test' } }
const rt = makeRuntimeConfig({ posthog: { apiKey: 'phc_test' } })

autoInjectProxyEndpoints(registry, rt, '/_proxy')

expect(registry.posthog.apiHost).toBe('/_proxy/ph')
expect(rt.public.scripts.posthog.apiHost).toBe('/_proxy/ph')
})

it('injects endpoint for plausible config object', () => {
const registry: any = { plausibleAnalytics: { domain: 'example.com' } }
const rt = makeRuntimeConfig({ plausibleAnalytics: { domain: 'example.com' } })

autoInjectProxyEndpoints(registry, rt, '/_proxy')

expect(registry.plausibleAnalytics.endpoint).toBe('/_proxy/plausible/api/event')
expect(rt.public.scripts.plausibleAnalytics.endpoint).toBe('/_proxy/plausible/api/event')
})

it('does not override existing config field', () => {
const registry: any = { posthog: { apiKey: 'phc_test', apiHost: 'https://custom.host' } }
const rt = makeRuntimeConfig({ posthog: { apiKey: 'phc_test', apiHost: 'https://custom.host' } })

autoInjectProxyEndpoints(registry, rt, '/_proxy')

expect(registry.posthog.apiHost).toBe('https://custom.host')
expect(rt.public.scripts.posthog.apiHost).toBe('https://custom.host')
})

it('uses EU prefix when posthog region is eu', () => {
const registry: any = { posthog: { apiKey: 'phc_test', region: 'eu' } }
const rt = makeRuntimeConfig({ posthog: { apiKey: 'phc_test', region: 'eu' } })

autoInjectProxyEndpoints(registry, rt, '/_proxy')

expect(registry.posthog.apiHost).toBe('/_proxy/ph-eu')
})
})

describe('array entries', () => {
it('injects into first element of array entry', () => {
const registry: any = { posthog: [{ apiKey: 'phc_test' }, { partytown: true }] }
const rt = makeRuntimeConfig({ posthog: { apiKey: 'phc_test' } })

autoInjectProxyEndpoints(registry, rt, '/_proxy')

expect(registry.posthog[0].apiHost).toBe('/_proxy/ph')
expect(rt.public.scripts.posthog.apiHost).toBe('/_proxy/ph')
})

it('skips empty array entries', () => {
const registry: any = { posthog: [] }
const rt = makeRuntimeConfig({ posthog: { apiKey: '' } })

autoInjectProxyEndpoints(registry, rt, '/_proxy')

expect(rt.public.scripts.posthog.apiHost).toBeUndefined()
})
})

describe('boolean entries', () => {
it('injects into runtimeConfig for posthog: true', () => {
const registry: any = { posthog: true }
const rt = makeRuntimeConfig({ posthog: { apiKey: '' } })

autoInjectProxyEndpoints(registry, rt, '/_proxy')

expect(registry.posthog).toBe(true)
expect(rt.public.scripts.posthog.apiHost).toBe('/_proxy/ph')
})

it('uses EU prefix for posthog: true when runtime region is eu', () => {
const registry: any = { posthog: true }
const rt = makeRuntimeConfig({ posthog: { apiKey: '', region: 'eu' } })

autoInjectProxyEndpoints(registry, rt, '/_proxy')

expect(rt.public.scripts.posthog.apiHost).toBe('/_proxy/ph-eu')
})

it('injects into runtimeConfig for plausibleAnalytics: true', () => {
const registry: any = { plausibleAnalytics: true }
const rt = makeRuntimeConfig({ plausibleAnalytics: { domain: '' } })

autoInjectProxyEndpoints(registry, rt, '/_proxy')

expect(rt.public.scripts.plausibleAnalytics.endpoint).toBe('/_proxy/plausible/api/event')
})

it('injects into runtimeConfig for umamiAnalytics: true', () => {
const registry: any = { umamiAnalytics: true }
const rt = makeRuntimeConfig({ umamiAnalytics: { websiteId: '' } })

autoInjectProxyEndpoints(registry, rt, '/_proxy')

expect(rt.public.scripts.umamiAnalytics.hostUrl).toBe('/_proxy/umami')
})

it('injects into runtimeConfig for rybbitAnalytics: true', () => {
const registry: any = { rybbitAnalytics: true }
const rt = makeRuntimeConfig({ rybbitAnalytics: { siteId: '' } })

autoInjectProxyEndpoints(registry, rt, '/_proxy')

expect(rt.public.scripts.rybbitAnalytics.analyticsHost).toBe('/_proxy/rybbit/api')
})

it('injects into runtimeConfig for databuddyAnalytics: true', () => {
const registry: any = { databuddyAnalytics: true }
const rt = makeRuntimeConfig({ databuddyAnalytics: { clientId: '' } })

autoInjectProxyEndpoints(registry, rt, '/_proxy')

expect(rt.public.scripts.databuddyAnalytics.apiUrl).toBe('/_proxy/databuddy-api')
})
})

describe('mock entries', () => {
it('injects into runtimeConfig for posthog: mock', () => {
const registry: any = { posthog: 'mock' }
const rt = makeRuntimeConfig({ posthog: { apiKey: '' } })

autoInjectProxyEndpoints(registry, rt, '/_proxy')

expect(rt.public.scripts.posthog.apiHost).toBe('/_proxy/ph')
})
})

describe('skipped entries', () => {
it('skips scripts not in AUTO_INJECT_DEFS', () => {
const registry: any = { googleAnalytics: { id: 'G-TEST' } }
const rt = makeRuntimeConfig({ googleAnalytics: { id: 'G-TEST' } })

autoInjectProxyEndpoints(registry, rt, '/_proxy')

expect(rt.public.scripts.googleAnalytics).toEqual({ id: 'G-TEST' })
})

it('skips falsy entries', () => {
const registry: any = { posthog: false }
const rt = makeRuntimeConfig()

autoInjectProxyEndpoints(registry, rt, '/_proxy')

expect(rt.public.scripts.posthog).toBeUndefined()
})

it('does not modify existing runtimeConfig for falsy entry', () => {
const registry: any = { posthog: false }
const rt = makeRuntimeConfig({ posthog: { existing: 'value' } })

autoInjectProxyEndpoints(registry, rt, '/_proxy')

expect(rt.public.scripts.posthog).toEqual({ existing: 'value' })
})
})

describe('custom collectPrefix', () => {
it('uses custom prefix in computed values', () => {
const registry: any = { posthog: true }
const rt = makeRuntimeConfig({ posthog: { apiKey: '' } })

autoInjectProxyEndpoints(registry, rt, '/_analytics')

expect(rt.public.scripts.posthog.apiHost).toBe('/_analytics/ph')
})
})
})
Loading