Skip to content

Commit dd29cec

Browse files
committed
chore: sync
1 parent 22f5df1 commit dd29cec

2 files changed

Lines changed: 33 additions & 25 deletions

File tree

src/module.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ import type {
2929
} from './runtime/types'
3030
import { NuxtScriptsCheckScripts } from './plugins/check-scripts'
3131
import { registerTypeTemplates, templatePlugin, templateTriggerResolver } from './templates'
32-
import { getAllProxyConfigs, getInterceptRules } from './proxy-configs'
32+
import { getAllProxyConfigs, routesToInterceptRules } from './proxy-configs'
33+
import type { InterceptRule } from './proxy-configs'
3334
import type { ProxyPrivacyInput } from './runtime/server/utils/privacy'
3435

3536
declare module '@nuxt/schema' {
@@ -466,10 +467,11 @@ export default defineNuxtModule<ModuleOptions>({
466467

467468
logger.debug('[nuxt-scripts] First-party config:', { firstPartyEnabled, firstPartyPrivacy, firstPartyCollectPrefix })
468469

470+
// Populated inside modules:done with only the configured scripts' routes
471+
let interceptRules: InterceptRule[] = []
472+
469473
// Setup first-party proxy mode (must be before modules:done)
470474
if (firstPartyEnabled) {
471-
const interceptRules = getInterceptRules(firstPartyCollectPrefix)
472-
473475
// Register __nuxtScripts runtime helper — provides sendBeacon/fetch wrappers
474476
// that route matching URLs through the first-party proxy. AST rewriting transforms
475477
// navigator.sendBeacon/fetch calls to use these wrappers at build time.
@@ -608,6 +610,9 @@ export default defineNuxtModule<ModuleOptions>({
608610
)
609611
}
610612

613+
// Compute intercept rules from only the configured scripts' routes
614+
interceptRules = routesToInterceptRules(neededRoutes)
615+
611616
// Expose first-party status via runtime config (for DevTools and status endpoint)
612617
const flatRoutes: Record<string, string> = {}
613618
for (const [path, config] of Object.entries(neededRoutes)) {

src/proxy-configs.ts

Lines changed: 25 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -326,42 +326,45 @@ export function getAllProxyConfigs(collectPrefix: string): Record<string, ProxyC
326326
}
327327

328328
export interface InterceptRule {
329-
/** Domain pattern to match (supports wildcards like *.google-analytics.com) */
329+
/** Domain to match (exact match or implicit subdomain suffix match, e.g. google-analytics.com matches *.google-analytics.com) */
330330
pattern: string
331331
/** Path prefix to match and strip from the original URL (e.g., /tr for www.facebook.com/tr) */
332332
pathPrefix: string
333333
/** Local path prefix to rewrite to */
334334
target: string
335335
}
336336

337+
/**
338+
* Convert route definitions into intercept rules for client-side URL rewriting.
339+
*/
340+
export function routesToInterceptRules(routes: Record<string, { proxy: string }>): InterceptRule[] {
341+
const rules: InterceptRule[] = []
342+
for (const [localPath, { proxy }] of Object.entries(routes)) {
343+
// Extract domain and path prefix from proxy URL
344+
// e.g., "https://www.facebook.com/tr/**" -> domain="www.facebook.com", pathPrefix="/tr"
345+
// e.g., "https://connect.facebook.net/**" -> domain="connect.facebook.net", pathPrefix=""
346+
const match = proxy.match(/^https?:\/\/([^/]+)(\/.*)?\/\*\*$/)
347+
if (match?.[1]) {
348+
const domain = match[1]
349+
const pathPrefix = match[2] || ''
350+
const target = localPath.replace(/\/\*\*$/, '')
351+
rules.push({ pattern: domain, pathPrefix, target })
352+
}
353+
}
354+
return rules
355+
}
356+
337357
/**
338358
* Get intercept rules from all proxy configs.
339359
* These rules are embedded in the __nuxtScripts client plugin to rewrite
340360
* outbound fetch/sendBeacon URLs through the first-party proxy.
341361
*/
342362
export function getInterceptRules(collectPrefix: string): InterceptRule[] {
343363
const configs = buildProxyConfig(collectPrefix)
344-
const rules: InterceptRule[] = []
345-
346-
// Extract unique domain -> target mappings from route rules
364+
const allRoutes: Record<string, { proxy: string }> = {}
347365
for (const config of Object.values(configs)) {
348-
if (!config.routes)
349-
continue
350-
for (const [localPath, { proxy }] of Object.entries(config.routes)) {
351-
// Extract domain and path prefix from proxy URL
352-
// e.g., "https://www.facebook.com/tr/**" -> domain="www.facebook.com", pathPrefix="/tr"
353-
// e.g., "https://connect.facebook.net/**" -> domain="connect.facebook.net", pathPrefix=""
354-
const match = proxy.match(/^https?:\/\/([^/]+)(\/.*)?\/\*\*$/)
355-
if (match?.[1]) {
356-
const domain = match[1]
357-
// Path prefix is everything between domain and /** (e.g., /tr), empty if none
358-
const pathPrefix = match[2] || ''
359-
// Extract target prefix: "/_proxy/meta-tr/**" -> "/_proxy/meta-tr"
360-
const target = localPath.replace(/\/\*\*$/, '')
361-
rules.push({ pattern: domain, pathPrefix, target })
362-
}
363-
}
366+
if (config.routes)
367+
Object.assign(allRoutes, config.routes)
364368
}
365-
366-
return rules
369+
return routesToInterceptRules(allRoutes)
367370
}

0 commit comments

Comments
 (0)