@nuxt/scripts 1.0.0-beta.19 → 1.0.0-beta.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client/200.html +1 -1
- package/dist/client/404.html +1 -1
- package/dist/client/_nuxt/{BAII0Gd6.js → 9LJPrOyI.js} +1 -1
- package/dist/client/_nuxt/DFEfk2pB.js +162 -0
- package/dist/client/_nuxt/{BFIM6xmj.js → DMlY-BNa.js} +1 -1
- package/dist/client/_nuxt/{XsmoCkZQ.js → __ZZTkMj.js} +1 -1
- package/dist/client/_nuxt/builds/latest.json +1 -1
- package/dist/client/_nuxt/builds/meta/8212d4fa-7985-421b-815a-03a886e667d4.json +1 -0
- package/dist/client/_nuxt/entry.CACgbLJl.css +1 -0
- package/dist/client/_nuxt/error-404.CHeaW3dp.css +1 -0
- package/dist/client/_nuxt/error-500.DvOvWme_.css +1 -0
- package/dist/client/index.html +1 -1
- package/dist/module.d.mts +7 -5
- package/dist/module.d.ts +7 -5
- package/dist/module.json +1 -1
- package/dist/module.mjs +389 -197
- package/dist/registry.mjs +5 -2
- package/dist/runtime/components/GoogleMaps/ScriptGoogleMaps.vue +1 -1
- package/dist/runtime/components/ScriptYouTubePlayer.vue +2 -1
- package/dist/runtime/registry/clarity.d.ts +8 -8
- package/dist/runtime/registry/crisp.d.ts +7 -7
- package/dist/runtime/registry/databuddy-analytics.js +18 -0
- package/dist/runtime/registry/fathom-analytics.d.ts +4 -3
- package/dist/runtime/registry/fathom-analytics.js +0 -1
- package/dist/runtime/registry/google-analytics.d.ts +1 -1
- package/dist/runtime/registry/google-recaptcha.js +1 -1
- package/dist/runtime/registry/google-tag-manager.js +1 -1
- package/dist/runtime/registry/hotjar.d.ts +1 -1
- package/dist/runtime/registry/instagram-embed.js +2 -1
- package/dist/runtime/registry/intercom.d.ts +1 -1
- package/dist/runtime/registry/meta-pixel.d.ts +1 -1
- package/dist/runtime/registry/reddit-pixel.d.ts +2 -1
- package/dist/runtime/registry/rybbit-analytics.js +1 -1
- package/dist/runtime/registry/schemas.d.ts +6 -0
- package/dist/runtime/registry/schemas.js +7 -1
- package/dist/runtime/registry/snapchat-pixel.d.ts +1 -1
- package/dist/runtime/registry/tiktok-pixel.d.ts +1 -1
- package/dist/runtime/registry/x-pixel.d.ts +1 -1
- package/dist/runtime/server/gravatar-proxy.js +1 -1
- package/dist/runtime/server/instagram-embed-asset.js +2 -1
- package/dist/runtime/server/instagram-embed-image.js +2 -1
- package/dist/runtime/server/instagram-embed.js +21 -12
- package/dist/runtime/server/proxy-handler.js +37 -27
- package/dist/runtime/server/utils/privacy.js +14 -7
- package/dist/runtime/server/x-embed.js +3 -2
- package/dist/runtime/utils.js +7 -3
- package/dist/shared/{scripts.Bg4pl9Yo.mjs → scripts.Crpn87WB.mjs} +15 -7
- package/dist/stats.mjs +7 -4
- package/dist/types-source.mjs +29 -18
- package/package.json +14 -14
- package/dist/client/_nuxt/8nZpL1GZ.js +0 -162
- package/dist/client/_nuxt/builds/meta/4f48c83d-e40d-436a-afd0-3b8e6ac6f303.json +0 -1
- package/dist/client/_nuxt/entry.D45OuV0w.css +0 -1
- package/dist/client/_nuxt/error-404.Cqp3ffuH.css +0 -1
- package/dist/client/_nuxt/error-500.B9hH8BAi.css +0 -1
package/dist/registry.mjs
CHANGED
|
@@ -56,8 +56,7 @@ async function registry(resolve) {
|
|
|
56
56
|
{
|
|
57
57
|
label: "Fathom Analytics",
|
|
58
58
|
proxy: "fathom",
|
|
59
|
-
|
|
60
|
-
// breaks script
|
|
59
|
+
src: "https://cdn.usefathom.com/script.js",
|
|
61
60
|
category: "analytics",
|
|
62
61
|
logo: `<svg width="32" height="32" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg"><circle cx="512" cy="512" r="512" style="fill:#9187ff"/><path d="M558.62 256c-36.31.16-78.78 10-129.45 28.4-170.71 62.15-206.9 139.74-144.79 310.45s139.73 206.89 310.45 144.76S801.74 599.88 739.6 429.16c-43.69-120-95-173.55-181-173.17zm59.1 140.16h26.73a5.33 5.33 0 0 1 5.16 6.72l-59.26 220.48a5.34 5.34 0 0 1-5.15 4h-26.75a5.33 5.33 0 0 1-5.16-6.72l3.6-13.4 2.63-9.75 53-197.38a5.33 5.33 0 0 1 5.14-3.94zM421.79 413.4h10.75a5.33 5.33 0 0 1 5.33 5.33v18a5.33 5.33 0 0 1-5.33 5.33h-9.13a36.76 36.76 0 0 0-5.51.24 4.7 4.7 0 0 0-2.56 1 4.19 4.19 0 0 0-1 1.66 18.91 18.91 0 0 0-.92 6.72v13.67h19.16a5.33 5.33 0 0 1 5.33 5.33v18a5.34 5.34 0 0 1-5.33 5.33h-19.21v108.71a5.34 5.34 0 0 1-5.34 5.34H387a5.33 5.33 0 0 1-5.33-5.34V448.48a36.74 36.74 0 0 1 3.6-16.64 29.76 29.76 0 0 1 9.73-11.16c7.9-5.48 17.62-7.27 26.82-7.31zm82.14 50c16.37 0 30.27 4.65 40.17 13.27s15.47 21.21 15.42 35.59v35.91l-16.11 59.92h-10.24a5.33 5.33 0 0 1-5.33-5.34v-4a39.13 39.13 0 0 1-4.76 3.56c-7.14 4.55-16.85 7.51-29.65 7.51a62.65 62.65 0 0 1-28.52-6.18 40.49 40.49 0 0 1-18.84-19.35 46.81 46.81 0 0 1-4-19.54 40.72 40.72 0 0 1 5.23-21.12 36.78 36.78 0 0 1 13.78-13.18c11.09-6.25 24.75-8.45 38.14-10.24 7.3-1 13.14-1.61 17.64-2.2a42 42 0 0 0 9.2-1.88 3.16 3.16 0 0 0 1.39-.86l.24-.48a6.77 6.77 0 0 0 .16-1.84v-.73a17.24 17.24 0 0 0-5.85-13.6c-3.8-3.31-9.77-5.55-18.07-5.57s-14.64 2.26-19 5.59a17.51 17.51 0 0 0-7.21 12.54 5.33 5.33 0 0 1-5.31 4.86h-22.25a5.33 5.33 0 0 1-5.33-5.57 45.64 45.64 0 0 1 17.6-34c10.47-8.34 24.85-13.12 41.49-13.12zm23.92 80.71c-1.92.48-4 1-6.31 1.45-6.47 1.28-14.29 2.41-21.87 3.48a61 61 0 0 0-14.76 3.65c-4.18 1.75-7.1 4-8.68 6.57a12.12 12.12 0 0 0-1.71 6.54v.2a12.93 12.93 0 0 0 1.32 5.87 11.81 11.81 0 0 0 3.76 4.22c3.41 2.45 9.13 4.14 16.85 4.14 11.95 0 19.52-3.5 24.32-8.32s7-11.56 7.08-19.11v-8.65zm0 0" style="fill:#fff"/></svg>`,
|
|
63
62
|
import: {
|
|
@@ -79,6 +78,8 @@ async function registry(resolve) {
|
|
|
79
78
|
{
|
|
80
79
|
label: "Rybbit Analytics",
|
|
81
80
|
proxy: "rybbit",
|
|
81
|
+
scriptBundling: false,
|
|
82
|
+
// SDK reads document.currentScript.src to derive API host — analyticsHost config injection handles proxy instead
|
|
82
83
|
category: "analytics",
|
|
83
84
|
logo: {
|
|
84
85
|
light: `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 263.33 173.53" width="37.24" height="32"><g><polygon fill="#0a3a3a" points="181.28 171.2 227.21 123.96 261.15 171.2 181.28 171.2"/><path fill="#0a3a3a" d="M261.15,89.05L206.64,2.33l-33.22,17.75-34.61-7.4c2.88,5.56,4.56,12.11,4.56,19.15,0,20.03-13.46,36.26-30.06,36.26-13.66,0-25.17-11-28.83-26.06l-39.92,71.46L2.18,94.19l22.66,77.01h55.81l22.28-54.01v54.01h64.66l-49.95-82.15h143.51Z"/></g><ellipse fill="#0a3a3a" cx="105.94" cy="28.62" rx="12.9" ry="18.88"/></svg>`,
|
|
@@ -92,6 +93,7 @@ async function registry(resolve) {
|
|
|
92
93
|
{
|
|
93
94
|
label: "Databuddy Analytics",
|
|
94
95
|
proxy: "databuddy",
|
|
96
|
+
scriptBundling: () => "https://cdn.databuddy.cc/databuddy.js",
|
|
95
97
|
category: "analytics",
|
|
96
98
|
logo: `<svg xmlns="http://www.w3.org/2000/svg" width="56.5" height="32" viewBox="0 0 8 8" shape-rendering="crispEdges"><path d="M0 0h8v8H0z"/><path fill="#fff" d="M1 1h1v6H1zm1 0h4v1H2zm4 1h1v1H6zm0 1h1v1H6zm0 1h1v1H6zm0 1h1v1H6zM2 6h4v1H2zm1-3h1v1H3zm1 1h1v1H4z"/></svg>`,
|
|
97
99
|
import: {
|
|
@@ -426,6 +428,7 @@ async function registry(resolve) {
|
|
|
426
428
|
{
|
|
427
429
|
label: "Umami Analytics",
|
|
428
430
|
proxy: "umami",
|
|
431
|
+
scriptBundling: () => "https://cloud.umami.is/script.js",
|
|
429
432
|
category: "analytics",
|
|
430
433
|
logo: `<svg xmlns="http://www.w3.org/2000/svg" width="96" height="96" viewBox="0 0 24 24"><path fill="currentColor" d="M2.203 8.611H.857a.845.845 0 0 0-.841.841v.858a13 13 0 0 0-.016.6c0 6.627 5.373 12 12 12c6.527 0 11.837-5.212 11.996-11.701c0-.025.004-.05.004-.075V9.452a.845.845 0 0 0-.841-.841h-1.346c-1.159-4.329-5.112-7.521-9.805-7.521S3.363 4.282 2.203 8.611m18.444 0H3.37c1.127-3.702 4.57-6.399 8.638-6.399c4.069 0 7.512 2.697 8.639 6.399"/></svg>`,
|
|
431
434
|
import: {
|
|
@@ -355,7 +355,7 @@ const rootAttrs = computed(() => {
|
|
|
355
355
|
});
|
|
356
356
|
});
|
|
357
357
|
onBeforeUnmount(async () => {
|
|
358
|
-
await Promise.all(
|
|
358
|
+
await Promise.all(Array.from(mapMarkers.value.entries(), ([, marker]) => resetMapMarkerMap(marker)));
|
|
359
359
|
mapMarkers.value.clear();
|
|
360
360
|
map.value?.unbindAll();
|
|
361
361
|
map.value = void 0;
|
|
@@ -30,6 +30,7 @@ const events = [
|
|
|
30
30
|
"onError",
|
|
31
31
|
"onApiChange"
|
|
32
32
|
];
|
|
33
|
+
const CAMEL_CASE_RE = /([A-Z])/g;
|
|
33
34
|
const rootEl = ref();
|
|
34
35
|
const youtubeEl = ref();
|
|
35
36
|
const ready = ref(false);
|
|
@@ -92,7 +93,7 @@ onMounted(() => {
|
|
|
92
93
|
playerVars: props.playerVars,
|
|
93
94
|
...props.playerOptions,
|
|
94
95
|
events: Object.fromEntries(events.map((event) => [event, (e) => {
|
|
95
|
-
const emitEventName = event.replace(
|
|
96
|
+
const emitEventName = event.replace(CAMEL_CASE_RE, "-$1").replace("on-", "").toLowerCase();
|
|
96
97
|
emits(emitEventName, e);
|
|
97
98
|
if (event === "onReady") {
|
|
98
99
|
ready.value = true;
|
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
import type { RegistryScriptInput } from '#nuxt-scripts/types';
|
|
2
2
|
import { ClarityOptions } from './schemas.js';
|
|
3
3
|
export { ClarityOptions };
|
|
4
|
-
type ClarityFunctions = ((fn: 'start', options
|
|
5
|
-
content
|
|
6
|
-
cookies
|
|
7
|
-
dob
|
|
8
|
-
expire
|
|
9
|
-
projectId
|
|
10
|
-
upload
|
|
4
|
+
type ClarityFunctions = ((fn: 'start', options?: {
|
|
5
|
+
content?: boolean;
|
|
6
|
+
cookies?: string[];
|
|
7
|
+
dob?: number;
|
|
8
|
+
expire?: number;
|
|
9
|
+
projectId?: string;
|
|
10
|
+
upload?: string;
|
|
11
11
|
}) => void) & ((fn: 'identify', id: string, session?: string, page?: string, userHint?: string) => Promise<{
|
|
12
12
|
id: string;
|
|
13
13
|
session: string;
|
|
14
14
|
page: string;
|
|
15
15
|
userHint: string;
|
|
16
|
-
}>) & ((fn: 'consent', enabled?: boolean) => void) & ((fn: 'set', key:
|
|
16
|
+
}>) & ((fn: 'consent', enabled?: boolean | Record<string, string>) => void) & ((fn: 'set', key: string, value: string | string[]) => void) & ((fn: 'event', value: string) => void) & ((fn: 'upgrade', upgradeReason: string) => void) & ((fn: (string & {}), ...args: any[]) => void);
|
|
17
17
|
export interface ClarityApi {
|
|
18
18
|
clarity: ClarityFunctions & {
|
|
19
19
|
q: any[];
|
|
@@ -4,13 +4,13 @@ export { CrispOptions };
|
|
|
4
4
|
export type CrispInput = RegistryScriptInput<typeof CrispOptions, false, false, false>;
|
|
5
5
|
export interface CrispApi {
|
|
6
6
|
push: (...args: any[]) => void;
|
|
7
|
-
is: (name: 'chat:opened' | 'chat:closed' | 'chat:visible' | 'chat:hidden' | 'chat:small' | 'chat:large' | 'session:ongoing' | 'website:available' | 'overlay:opened' | 'overlay:closed' | string) => boolean;
|
|
8
|
-
set: (name: 'message:text' | '
|
|
9
|
-
get: (name: 'chat:unread:count'
|
|
10
|
-
do: (name: 'chat:open' | 'chat:close' | 'chat:toggle' | 'chat:show' | 'chat:hide' | 'helpdesk:search' | 'helpdesk:article:open' | 'helpdesk:query' | 'overlay:open' | 'overlay:close' | 'message:send' | 'message:show' | 'message:read' | 'message:thread:start' | 'message:thread:end' | 'session:reset' | 'trigger:run'
|
|
11
|
-
on: (name: 'session:loaded' | 'chat:initiated' | 'chat:opened' | 'chat:closed' | 'message:sent' | 'message:received' | 'message:compose:sent' | 'message:compose:received' | 'user:email:changed' | 'user:phone:changed' | 'user:nickname:changed' | 'user:avatar:changed' | 'website:availability:changed' | 'helpdesk:queried' | string, callback: (...args: any[]) => any) => void;
|
|
12
|
-
off: (name: 'session:loaded' | 'chat:initiated' | 'chat:opened' | 'chat:closed' | 'message:sent' | 'message:received' | 'message:compose:sent' | 'message:compose:received' | 'user:email:changed' | 'user:phone:changed' | 'user:nickname:changed' | 'user:avatar:changed' | 'website:availability:changed' | 'helpdesk:queried' | string, callback: (...args: any[]) => any) => void;
|
|
13
|
-
config: (
|
|
7
|
+
is: (name: 'chat:opened' | 'chat:closed' | 'chat:visible' | 'chat:hidden' | 'chat:small' | 'chat:large' | 'session:ongoing' | 'website:available' | 'overlay:opened' | 'overlay:closed' | (string & {})) => boolean;
|
|
8
|
+
set: ((name: 'message:text' | 'user:email' | 'user:phone' | 'user:nickname' | 'user:avatar' | 'user:company', value: string) => void) & ((name: 'session:data', value: [[string, string | number | boolean], ...[string, string | number | boolean][]]) => void) & ((name: 'session:segments', value: string[]) => void) & ((name: 'session:event', value: [[string, Record<string, any>?, string?]]) => void) & ((name: (string & {}), value: any) => void);
|
|
9
|
+
get: ((name: 'chat:unread:count') => number) & ((name: 'message:text' | 'session:identifier' | 'user:email' | 'user:phone' | 'user:nickname' | 'user:avatar' | 'user:company') => string) & ((name: 'session:data', key: string) => string | number | boolean) & ((name: (string & {})) => any);
|
|
10
|
+
do: (name: 'chat:open' | 'chat:close' | 'chat:toggle' | 'chat:show' | 'chat:hide' | 'helpdesk:search' | 'helpdesk:article:open' | 'helpdesk:query' | 'overlay:open' | 'overlay:close' | 'message:send' | 'message:show' | 'message:read' | 'message:thread:start' | 'message:thread:end' | 'session:reset' | 'trigger:run', arg2?: any) => any;
|
|
11
|
+
on: (name: 'session:loaded' | 'chat:initiated' | 'chat:opened' | 'chat:closed' | 'message:sent' | 'message:received' | 'message:compose:sent' | 'message:compose:received' | 'user:email:changed' | 'user:phone:changed' | 'user:nickname:changed' | 'user:avatar:changed' | 'website:availability:changed' | 'helpdesk:queried' | (string & {}), callback: (...args: any[]) => any) => void;
|
|
12
|
+
off: (name: 'session:loaded' | 'chat:initiated' | 'chat:opened' | 'chat:closed' | 'message:sent' | 'message:received' | 'message:compose:sent' | 'message:compose:received' | 'user:email:changed' | 'user:phone:changed' | 'user:nickname:changed' | 'user:avatar:changed' | 'website:availability:changed' | 'helpdesk:queried' | (string & {}), callback: (...args: any[]) => any) => void;
|
|
13
|
+
config: ((name: 'container:index', value: number) => void) & ((name: 'color:theme', value: 'default' | 'amber' | 'black' | 'blue' | 'blue_grey' | 'light_blue' | 'brown' | 'cyan' | 'green' | 'light_green' | 'grey' | 'indigo' | 'orange' | 'deep_orange' | 'pink' | 'purple' | 'deep_purple' | 'red' | 'teal') => void) & ((name: 'position:reverse' | 'hide:on:mobile' | 'hide:on:away' | 'lock:maximized' | 'lock:fullview' | 'show:operator:count' | 'sound:mute', value: boolean) => void) & ((name: (string & {}), value: any) => void);
|
|
14
14
|
help: () => void;
|
|
15
15
|
[key: string]: any;
|
|
16
16
|
}
|
|
@@ -53,6 +53,24 @@ export function useScriptDatabuddyAnalytics(_options) {
|
|
|
53
53
|
return null;
|
|
54
54
|
}
|
|
55
55
|
return window.db || window.databuddy || null;
|
|
56
|
+
},
|
|
57
|
+
// The SDK finds config by searching for a <script> with src containing
|
|
58
|
+
// "/databuddy.js". When first-party bundling rewrites the src to
|
|
59
|
+
// /_scripts/<hash>.js, the lookup fails. Set window.databuddyConfig
|
|
60
|
+
// so the SDK picks up the config regardless of script src.
|
|
61
|
+
clientInit: import.meta.server ? void 0 : () => {
|
|
62
|
+
const cfg = { clientId: options.clientId };
|
|
63
|
+
if (options?.apiUrl)
|
|
64
|
+
cfg.apiUrl = options.apiUrl;
|
|
65
|
+
if (options?.disabled)
|
|
66
|
+
cfg.disabled = options.disabled;
|
|
67
|
+
if (options?.trackScreenViews)
|
|
68
|
+
cfg.trackScreenViews = options.trackScreenViews;
|
|
69
|
+
if (options?.trackPerformance)
|
|
70
|
+
cfg.trackPerformance = options.trackPerformance;
|
|
71
|
+
if (options?.trackSessions)
|
|
72
|
+
cfg.trackSessions = options.trackSessions;
|
|
73
|
+
window.databuddyConfig = cfg;
|
|
56
74
|
}
|
|
57
75
|
}
|
|
58
76
|
};
|
|
@@ -12,14 +12,15 @@ export interface FathomAnalyticsApi {
|
|
|
12
12
|
isTrackingEnabled: () => boolean;
|
|
13
13
|
send: (type: string, data: unknown) => void;
|
|
14
14
|
setSite: (siteId: string) => void;
|
|
15
|
-
|
|
15
|
+
siteId: string;
|
|
16
16
|
trackPageview: (ctx?: {
|
|
17
17
|
url: string;
|
|
18
18
|
referrer?: string;
|
|
19
19
|
}) => void;
|
|
20
20
|
trackGoal: (goalId: string, cents: number) => void;
|
|
21
|
-
trackEvent: (eventName: string, value
|
|
22
|
-
_value
|
|
21
|
+
trackEvent: (eventName: string, value?: {
|
|
22
|
+
_value?: number;
|
|
23
|
+
_site_id?: string;
|
|
23
24
|
}) => void;
|
|
24
25
|
}
|
|
25
26
|
declare global {
|
|
@@ -5,7 +5,6 @@ export function useScriptFathomAnalytics(_options) {
|
|
|
5
5
|
return useRegistryScript("fathomAnalytics", (options) => ({
|
|
6
6
|
scriptInput: {
|
|
7
7
|
src: "https://cdn.usefathom.com/script.js",
|
|
8
|
-
// can't be bundled
|
|
9
8
|
// append the data attr's
|
|
10
9
|
...Object.entries(options).filter(([key]) => ["site", "spa", "auto", "canonical", "honorDnt"].includes(key)).reduce((acc, [_key, value]) => {
|
|
11
10
|
const key = _key === "honourDnt" ? "honor-dnt" : _key;
|
|
@@ -38,7 +38,7 @@ export interface EventParameters extends GtagCustomParams {
|
|
|
38
38
|
}>;
|
|
39
39
|
[key: string]: any;
|
|
40
40
|
}
|
|
41
|
-
export type DefaultEventName = 'add_payment_info' | 'add_shipping_info' | 'add_to_cart' | 'add_to_wishlist' | 'begin_checkout' | 'purchase' | 'refund' | 'remove_from_cart' | 'select_item' | 'select_promotion' | 'view_cart' | 'view_item' | 'view_item_list' | 'view_promotion' | 'login' | 'sign_up' | 'search' | 'page_view' | 'screen_view' | string;
|
|
41
|
+
export type DefaultEventName = 'add_payment_info' | 'add_shipping_info' | 'add_to_cart' | 'add_to_wishlist' | 'begin_checkout' | 'purchase' | 'refund' | 'remove_from_cart' | 'select_item' | 'select_promotion' | 'view_cart' | 'view_item' | 'view_item_list' | 'view_promotion' | 'login' | 'sign_up' | 'search' | 'page_view' | 'screen_view' | (string & {});
|
|
42
42
|
export interface GTag {
|
|
43
43
|
(command: 'js', value: Date): void;
|
|
44
44
|
(command: 'config', targetId: string, configParams?: ConfigParams): void;
|
|
@@ -24,7 +24,7 @@ export function useScriptGoogleRecaptcha(_options) {
|
|
|
24
24
|
const w = window;
|
|
25
25
|
w.grecaptcha = w.grecaptcha || {};
|
|
26
26
|
const readyFn = function(cb) {
|
|
27
|
-
(w.___grecaptcha_cfg = w.___grecaptcha_cfg || {}).fns =
|
|
27
|
+
(w.___grecaptcha_cfg = w.___grecaptcha_cfg || {}).fns = [...w.___grecaptcha_cfg.fns || [], ...[cb]];
|
|
28
28
|
};
|
|
29
29
|
w.grecaptcha.ready = w.grecaptcha.ready || readyFn;
|
|
30
30
|
if (options?.enterprise) {
|
|
@@ -41,7 +41,7 @@ export function useScriptGoogleTagManager(options) {
|
|
|
41
41
|
if (opts.defaultConsent)
|
|
42
42
|
gtag("consent", "default", opts.defaultConsent);
|
|
43
43
|
window[dataLayerName].push({
|
|
44
|
-
"gtm.start":
|
|
44
|
+
"gtm.start": Date.now(),
|
|
45
45
|
"event": "gtm.js"
|
|
46
46
|
});
|
|
47
47
|
}
|
|
@@ -2,7 +2,7 @@ import type { RegistryScriptInput } from '#nuxt-scripts/types';
|
|
|
2
2
|
import { HotjarOptions } from './schemas.js';
|
|
3
3
|
export { HotjarOptions };
|
|
4
4
|
export interface HotjarApi {
|
|
5
|
-
hj: ((event: 'identify', userId: string, attributes?: Record<string, any>) => void) & ((event: 'stateChange', path: string) => void) & ((event: '
|
|
5
|
+
hj: ((event: 'identify', userId: string, attributes?: Record<string, any>) => void) & ((event: 'stateChange', path: string) => void) & ((event: 'vPageView', path: string) => void) & ((event: 'event', eventName: string) => void) & ((event: (string & {}), ...args: any[]) => void) & {
|
|
6
6
|
q: any[];
|
|
7
7
|
};
|
|
8
8
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { InstagramEmbedOptions } from "./schemas.js";
|
|
2
2
|
export { InstagramEmbedOptions };
|
|
3
|
+
const INSTAGRAM_SHORTCODE_RE = /instagram\.com\/(?:p|reel|tv)\/([^/?]+)/;
|
|
3
4
|
export function extractInstagramShortcode(url) {
|
|
4
|
-
const match = url.match(
|
|
5
|
+
const match = url.match(INSTAGRAM_SHORTCODE_RE);
|
|
5
6
|
return match?.[1];
|
|
6
7
|
}
|
|
@@ -4,7 +4,7 @@ import { IntercomOptions } from './schemas.js';
|
|
|
4
4
|
export { IntercomOptions };
|
|
5
5
|
export type IntercomInput = RegistryScriptInput<typeof IntercomOptions, true, false, false>;
|
|
6
6
|
export interface IntercomApi {
|
|
7
|
-
Intercom: ((event: 'boot', data?: InferInput<typeof IntercomOptions>) => void) & ((event: 'shutdown') => void) & ((event: 'update', options?: InferInput<typeof IntercomOptions>) => void) & ((event: 'hide') => void) & ((event: 'show') => void) & ((event: 'showSpace', spaceName: 'home' | 'messages' | 'help' | 'news' | 'tasks' | 'tickets' | string) => void) & ((event: 'showMessages') => void) & ((event: 'showNewMessage', content?: string) => void) & ((event: 'onHide', fn: () => void) => void) & ((event: 'onShow', fn: () => void) => void) & ((event: 'onUnreadCountChange', fn: () => void) => void) & ((event: 'trackEvent', eventName: string, metadata?: Record<string, any>) => void) & ((event: 'getVisitorId') => Promise<string>) & ((event: 'startTour', tourId: string | number) => void) & ((event: 'showArticle', articleId: string | number) => void) & ((event: 'showNews', newsItemId: string | number) => void) & ((event: 'startSurvey', surveyId: string | number) => void) & ((event: 'startChecklist', checklistId: string | number) => void) & ((event: 'showTicket', ticketId: string | number) => void) & ((event: 'showConversation', conversationId: string | number) => void) & ((event: 'onUserEmailSupplied', fn: () => void) => void) & ((event: string, ...params: any[]) => void);
|
|
7
|
+
Intercom: ((event: 'boot', data?: InferInput<typeof IntercomOptions>) => void) & ((event: 'shutdown') => void) & ((event: 'update', options?: InferInput<typeof IntercomOptions>) => void) & ((event: 'hide') => void) & ((event: 'show') => void) & ((event: 'showSpace', spaceName: 'home' | 'messages' | 'help' | 'news' | 'tasks' | 'tickets' | (string & {})) => void) & ((event: 'showMessages') => void) & ((event: 'showNewMessage', content?: string) => void) & ((event: 'onHide', fn: () => void) => void) & ((event: 'onShow', fn: () => void) => void) & ((event: 'onUnreadCountChange', fn: () => void) => void) & ((event: 'trackEvent', eventName: string, metadata?: Record<string, any>) => void) & ((event: 'getVisitorId') => Promise<string>) & ((event: 'startTour', tourId: string | number) => void) & ((event: 'showArticle', articleId: string | number) => void) & ((event: 'showNews', newsItemId: string | number) => void) & ((event: 'startSurvey', surveyId: string | number) => void) & ((event: 'startChecklist', checklistId: string | number) => void) & ((event: 'showTicket', ticketId: string | number) => void) & ((event: 'showConversation', conversationId: string | number) => void) & ((event: 'onUserEmailSupplied', fn: () => void) => void) & ((event: (string & {}), ...params: any[]) => void);
|
|
8
8
|
}
|
|
9
9
|
declare global {
|
|
10
10
|
interface Window extends IntercomApi {
|
|
@@ -15,7 +15,7 @@ interface EventObjectProperties {
|
|
|
15
15
|
num_items?: number;
|
|
16
16
|
predicted_ltv?: number;
|
|
17
17
|
search_string?: string;
|
|
18
|
-
status?: 'completed' | 'updated' | 'viewed' | 'added_to_cart' | 'removed_from_cart' | string;
|
|
18
|
+
status?: 'completed' | 'updated' | 'viewed' | 'added_to_cart' | 'removed_from_cart' | (string & {});
|
|
19
19
|
value?: number;
|
|
20
20
|
[key: string]: any;
|
|
21
21
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { RegistryScriptInput } from '#nuxt-scripts/types';
|
|
2
2
|
import { RedditPixelOptions } from './schemas.js';
|
|
3
|
-
type
|
|
3
|
+
type StandardEvents = 'PageVisit' | 'ViewContent' | 'Search' | 'AddToCart' | 'AddToWishlist' | 'Purchase' | 'Lead' | 'SignUp';
|
|
4
|
+
type RdtFns = ((event: 'init', id: string) => void) & ((event: 'track', eventName: StandardEvents | (string & {}), properties?: Record<string, any>) => void);
|
|
4
5
|
export interface RedditPixelApi {
|
|
5
6
|
rdt: RdtFns & {
|
|
6
7
|
sendEvent: (rdt: RedditPixelApi['rdt'], args: unknown[]) => void;
|
|
@@ -39,7 +39,7 @@ export function useScriptRybbitAnalytics(_options) {
|
|
|
39
39
|
return useRegistryScript("rybbitAnalytics", (options) => {
|
|
40
40
|
return {
|
|
41
41
|
scriptInput: {
|
|
42
|
-
"src": "https://app.rybbit.io/api/script.js",
|
|
42
|
+
"src": options?.analyticsHost ? `${options.analyticsHost}/script.js` : "https://app.rybbit.io/api/script.js",
|
|
43
43
|
"data-site-id": String(options?.siteId),
|
|
44
44
|
"data-auto-track-pageview": options?.autoTrackPageview,
|
|
45
45
|
"data-track-spa": options?.trackSpa,
|
|
@@ -673,6 +673,12 @@ export declare const RybbitAnalyticsOptions: import("valibot").ObjectSchema<{
|
|
|
673
673
|
* API key for authenticated tracking.
|
|
674
674
|
*/
|
|
675
675
|
readonly apiKey: import("valibot").OptionalSchema<import("valibot").StringSchema<undefined>, undefined>;
|
|
676
|
+
/**
|
|
677
|
+
* Override the analytics host URL. When first-party mode is enabled, this is
|
|
678
|
+
* auto-injected to route through the proxy. The SDK derives its API endpoint
|
|
679
|
+
* from the script src, so this changes the script src to `${analyticsHost}/script.js`.
|
|
680
|
+
*/
|
|
681
|
+
readonly analyticsHost: import("valibot").OptionalSchema<import("valibot").StringSchema<undefined>, undefined>;
|
|
676
682
|
}, undefined>;
|
|
677
683
|
export declare const SegmentOptions: import("valibot").ObjectSchema<{
|
|
678
684
|
/**
|
|
@@ -670,7 +670,13 @@ export const RybbitAnalyticsOptions = object({
|
|
|
670
670
|
/**
|
|
671
671
|
* API key for authenticated tracking.
|
|
672
672
|
*/
|
|
673
|
-
apiKey: optional(string())
|
|
673
|
+
apiKey: optional(string()),
|
|
674
|
+
/**
|
|
675
|
+
* Override the analytics host URL. When first-party mode is enabled, this is
|
|
676
|
+
* auto-injected to route through the proxy. The SDK derives its API endpoint
|
|
677
|
+
* from the script src, so this changes the script src to `${analyticsHost}/script.js`.
|
|
678
|
+
*/
|
|
679
|
+
analyticsHost: optional(string())
|
|
674
680
|
});
|
|
675
681
|
export const SegmentOptions = object({
|
|
676
682
|
/**
|
|
@@ -23,7 +23,7 @@ interface EventObjectProperties {
|
|
|
23
23
|
[key: string]: any;
|
|
24
24
|
}
|
|
25
25
|
type InitObjectProperties = InferInput<typeof InitObjectPropertiesSchema>;
|
|
26
|
-
type SnapTrFns = ((event: 'track', eventName: StandardEvents |
|
|
26
|
+
type SnapTrFns = ((event: 'track', eventName: StandardEvents | (string & {}), data?: EventObjectProperties) => void) & ((event: 'init', id: string, data?: Record<string, any>) => void) & ((event: 'init', id: string, data?: InitObjectProperties) => void) & ((event: (string & {}), ...params: any[]) => void);
|
|
27
27
|
export interface SnapPixelApi {
|
|
28
28
|
snaptr: SnapTrFns & {
|
|
29
29
|
push: SnapTrFns;
|
|
@@ -23,7 +23,7 @@ interface IdentifyProperties {
|
|
|
23
23
|
phone_number?: string;
|
|
24
24
|
external_id?: string;
|
|
25
25
|
}
|
|
26
|
-
type TtqFns = ((cmd: 'track', event: StandardEvents | string, properties?: EventProperties) => void) & ((cmd: 'page') => void) & ((cmd: 'identify', properties: IdentifyProperties) => void) & ((cmd: string, ...args: any[]) => void);
|
|
26
|
+
type TtqFns = ((cmd: 'track', event: StandardEvents | (string & {}), properties?: EventProperties) => void) & ((cmd: 'page') => void) & ((cmd: 'identify', properties: IdentifyProperties) => void) & ((cmd: (string & {}), ...args: any[]) => void);
|
|
27
27
|
export interface TikTokPixelApi {
|
|
28
28
|
ttq: TtqFns & {
|
|
29
29
|
push: TtqFns;
|
|
@@ -16,7 +16,7 @@ interface EventObjectProperties {
|
|
|
16
16
|
phone_number?: string | null;
|
|
17
17
|
contents: ContentProperties[];
|
|
18
18
|
}
|
|
19
|
-
type TwqFns = ((event: 'event', eventId: string, data?: EventObjectProperties) => void) & ((event: 'config', id: string) => void) & ((event: string, ...params: any[]) => void);
|
|
19
|
+
type TwqFns = ((event: 'event', eventId: string, data?: EventObjectProperties) => void) & ((event: 'config', id: string) => void) & ((event: (string & {}), ...params: any[]) => void);
|
|
20
20
|
export interface XPixelApi {
|
|
21
21
|
twq: TwqFns & {
|
|
22
22
|
loaded: boolean;
|
|
@@ -27,7 +27,7 @@ export default defineEventHandler(async (event) => {
|
|
|
27
27
|
const encoder = new TextEncoder();
|
|
28
28
|
const data = encoder.encode(email.trim().toLowerCase());
|
|
29
29
|
const hashBuffer = await crypto.subtle.digest("SHA-256", data);
|
|
30
|
-
hash = Array.from(new Uint8Array(hashBuffer)
|
|
30
|
+
hash = Array.from(new Uint8Array(hashBuffer), (b) => b.toString(16).padStart(2, "0")).join("");
|
|
31
31
|
}
|
|
32
32
|
if (!hash) {
|
|
33
33
|
throw createError({
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { createError, defineEventHandler, getQuery, setHeader } from "h3";
|
|
2
2
|
import { $fetch } from "ofetch";
|
|
3
|
+
const AMP_RE = /&/g;
|
|
3
4
|
export default defineEventHandler(async (event) => {
|
|
4
5
|
const query = getQuery(event);
|
|
5
|
-
const url = query.url?.replace(
|
|
6
|
+
const url = query.url?.replace(AMP_RE, "&");
|
|
6
7
|
if (!url) {
|
|
7
8
|
throw createError({
|
|
8
9
|
statusCode: 400,
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { createError, defineEventHandler, getQuery, setHeader } from "h3";
|
|
2
2
|
import { $fetch } from "ofetch";
|
|
3
|
+
const AMP_RE = /&/g;
|
|
3
4
|
export default defineEventHandler(async (event) => {
|
|
4
5
|
const query = getQuery(event);
|
|
5
|
-
const url = query.url?.replace(
|
|
6
|
+
const url = query.url?.replace(AMP_RE, "&");
|
|
6
7
|
if (!url) {
|
|
7
8
|
throw createError({
|
|
8
9
|
statusCode: 400,
|
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
import { createError, defineEventHandler, getQuery, setHeader } from "h3";
|
|
2
2
|
import { $fetch } from "ofetch";
|
|
3
|
+
const LINK_RE = /<link[^>]+rel=["']stylesheet["'][^>]+href=["']([^"']+)["'][^>]*>/gi;
|
|
4
|
+
const LINK_RE_2 = /<link[^>]+href=["']([^"']+)["'][^>]+rel=["']stylesheet["'][^>]*>/gi;
|
|
5
|
+
const RSRC_RE = /url\(\/rsrc\.php([^)]+)\)/g;
|
|
6
|
+
const SCRIPT_RE = /<script[\s\S]*?<\/script>/gi;
|
|
7
|
+
const STYLESHEET_RE = /<link[^>]+rel=["']stylesheet["'][^>]*>/gi;
|
|
8
|
+
const CSS_RE = /<link[^>]+href=["'][^"']+\.css[^"']*["'][^>]*>/gi;
|
|
9
|
+
const NOSCRIPT_RE = /<noscript>[\s\S]*?<\/noscript>/gi;
|
|
10
|
+
const SCONTENT_RE = /https:\/\/scontent[^"'\s),]+\.cdninstagram\.com[^"'\s),]+/g;
|
|
11
|
+
const STATIC_CDN_RE = /https:\/\/static\.cdninstagram\.com[^"'\s),]+/g;
|
|
12
|
+
const LOOKASIDE_RE = /https:\/\/lookaside\.instagram\.com[^"'\s),]+/g;
|
|
13
|
+
const AMP_RE = /&/g;
|
|
3
14
|
export default defineEventHandler(async (event) => {
|
|
4
15
|
const query = getQuery(event);
|
|
5
16
|
const postUrl = query.url;
|
|
@@ -41,14 +52,12 @@ export default defineEventHandler(async (event) => {
|
|
|
41
52
|
});
|
|
42
53
|
});
|
|
43
54
|
const cssUrls = [];
|
|
44
|
-
const linkRegex = /<link[^>]+rel=["']stylesheet["'][^>]+href=["']([^"']+)["'][^>]*>/gi;
|
|
45
55
|
let match;
|
|
46
|
-
while ((match =
|
|
56
|
+
while ((match = LINK_RE.exec(html)) !== null) {
|
|
47
57
|
if (match[1])
|
|
48
58
|
cssUrls.push(match[1]);
|
|
49
59
|
}
|
|
50
|
-
|
|
51
|
-
while ((match = linkRegex2.exec(html)) !== null) {
|
|
60
|
+
while ((match = LINK_RE_2.exec(html)) !== null) {
|
|
52
61
|
if (match[1])
|
|
53
62
|
cssUrls.push(match[1]);
|
|
54
63
|
}
|
|
@@ -61,7 +70,7 @@ export default defineEventHandler(async (event) => {
|
|
|
61
70
|
);
|
|
62
71
|
let combinedCss = cssContents.join("\n");
|
|
63
72
|
combinedCss = combinedCss.replace(
|
|
64
|
-
|
|
73
|
+
RSRC_RE,
|
|
65
74
|
(_m, path) => `url(/api/_scripts/instagram-embed-asset?url=${encodeURIComponent(`https://static.cdninstagram.com/rsrc.php${path}`)})`
|
|
66
75
|
);
|
|
67
76
|
const baseStyles = `
|
|
@@ -70,15 +79,15 @@ export default defineEventHandler(async (event) => {
|
|
|
70
79
|
.Embed { opacity: 1 !important; visibility: visible !important; }
|
|
71
80
|
.EmbeddedMedia, .EmbeddedMediaImage { display: block !important; visibility: visible !important; }
|
|
72
81
|
`;
|
|
73
|
-
let rewrittenHtml = html.replace(
|
|
74
|
-
|
|
75
|
-
(m) => `/api/_scripts/instagram-embed-image?url=${encodeURIComponent(m.replace(
|
|
82
|
+
let rewrittenHtml = html.replace(SCRIPT_RE, "").replace(STYLESHEET_RE, "").replace(CSS_RE, "").replace(NOSCRIPT_RE, "").replace(
|
|
83
|
+
SCONTENT_RE,
|
|
84
|
+
(m) => `/api/_scripts/instagram-embed-image?url=${encodeURIComponent(m.replace(AMP_RE, "&"))}`
|
|
76
85
|
).replace(
|
|
77
|
-
|
|
78
|
-
(m) => `/api/_scripts/instagram-embed-asset?url=${encodeURIComponent(m.replace(
|
|
86
|
+
STATIC_CDN_RE,
|
|
87
|
+
(m) => `/api/_scripts/instagram-embed-asset?url=${encodeURIComponent(m.replace(AMP_RE, "&"))}`
|
|
79
88
|
).replace(
|
|
80
|
-
|
|
81
|
-
(m) => `/api/_scripts/instagram-embed-image?url=${encodeURIComponent(m.replace(
|
|
89
|
+
LOOKASIDE_RE,
|
|
90
|
+
(m) => `/api/_scripts/instagram-embed-image?url=${encodeURIComponent(m.replace(AMP_RE, "&"))}`
|
|
82
91
|
);
|
|
83
92
|
rewrittenHtml = rewrittenHtml.replace(
|
|
84
93
|
"</head>",
|
|
@@ -10,6 +10,19 @@ import {
|
|
|
10
10
|
SENSITIVE_HEADERS,
|
|
11
11
|
stripPayloadFingerprinting
|
|
12
12
|
} from "./utils/privacy.js";
|
|
13
|
+
const COMPRESSION_RE = /gzip|deflate|br|compress|base64/i;
|
|
14
|
+
const ROUTE_WILDCARD_RE = /\/\*\*$/;
|
|
15
|
+
const CLIENT_HINT_VERSION_RE = /;v="(\d+)\.[^"]*"/g;
|
|
16
|
+
const SKIP_RESPONSE_HEADERS = /* @__PURE__ */ new Set(["set-cookie", "transfer-encoding", "content-encoding", "content-length"]);
|
|
17
|
+
let sortedRoutesCache;
|
|
18
|
+
function getSortedRoutes(routes) {
|
|
19
|
+
const key = JSON.stringify(routes);
|
|
20
|
+
if (sortedRoutesCache?.key === key)
|
|
21
|
+
return sortedRoutesCache.sorted;
|
|
22
|
+
const sorted = Object.entries(routes).sort((a, b) => b[0].length - a[0].length);
|
|
23
|
+
sortedRoutesCache = { key, sorted };
|
|
24
|
+
return sorted;
|
|
25
|
+
}
|
|
13
26
|
function stripQueryFingerprinting(query, privacy) {
|
|
14
27
|
const stripped = stripPayloadFingerprinting(query, privacy);
|
|
15
28
|
const params = new URLSearchParams();
|
|
@@ -18,11 +31,10 @@ function stripQueryFingerprinting(query, privacy) {
|
|
|
18
31
|
params.set(key, typeof value === "object" ? JSON.stringify(value) : String(value));
|
|
19
32
|
}
|
|
20
33
|
}
|
|
21
|
-
return params.toString();
|
|
34
|
+
return { queryString: params.toString(), stripped };
|
|
22
35
|
}
|
|
23
36
|
export default defineEventHandler(async (event) => {
|
|
24
37
|
const config = useRuntimeConfig();
|
|
25
|
-
const nitro = useNitroApp();
|
|
26
38
|
const proxyConfig = config["nuxt-scripts-proxy"];
|
|
27
39
|
if (!proxyConfig) {
|
|
28
40
|
throw createError({
|
|
@@ -39,11 +51,10 @@ export default defineEventHandler(async (event) => {
|
|
|
39
51
|
let targetBase;
|
|
40
52
|
let matchedPrefix;
|
|
41
53
|
let matchedRoutePattern;
|
|
42
|
-
const
|
|
43
|
-
|
|
44
|
-
const prefix = routePattern.replace(/\/\*\*$/, "");
|
|
54
|
+
for (const [routePattern, target] of getSortedRoutes(routes)) {
|
|
55
|
+
const prefix = routePattern.replace(ROUTE_WILDCARD_RE, "");
|
|
45
56
|
if (path.startsWith(prefix)) {
|
|
46
|
-
targetBase = target.replace(
|
|
57
|
+
targetBase = target.replace(ROUTE_WILDCARD_RE, "");
|
|
47
58
|
matchedPrefix = prefix;
|
|
48
59
|
matchedRoutePattern = routePattern;
|
|
49
60
|
log("[proxy] Matched:", prefix, "->", targetBase);
|
|
@@ -66,22 +77,24 @@ export default defineEventHandler(async (event) => {
|
|
|
66
77
|
const privacy = globalPrivacy !== void 0 ? mergePrivacy(perScriptResolved, globalPrivacy) : perScriptResolved;
|
|
67
78
|
const anyPrivacy = privacy.ip || privacy.userAgent || privacy.language || privacy.screen || privacy.timezone || privacy.hardware;
|
|
68
79
|
const originalHeaders = getHeaders(event);
|
|
80
|
+
const originalQuery = getQuery(event);
|
|
69
81
|
const contentType = originalHeaders["content-type"] || "";
|
|
70
|
-
const compressionParam =
|
|
82
|
+
const compressionParam = originalQuery.compression || "";
|
|
71
83
|
const isBinaryBody = Boolean(
|
|
72
|
-
originalHeaders["content-encoding"] || contentType.includes("octet-stream") || compressionParam &&
|
|
84
|
+
originalHeaders["content-encoding"] || contentType.includes("octet-stream") || compressionParam && COMPRESSION_RE.test(compressionParam)
|
|
73
85
|
);
|
|
74
86
|
let targetPath = path.slice(matchedPrefix.length);
|
|
75
87
|
if (targetPath && !targetPath.startsWith("/")) {
|
|
76
88
|
targetPath = `/${targetPath}`;
|
|
77
89
|
}
|
|
78
90
|
let targetUrl = targetBase + targetPath;
|
|
91
|
+
let strippedQueryRecord;
|
|
79
92
|
if (anyPrivacy) {
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
93
|
+
if (Object.keys(originalQuery).length > 0) {
|
|
94
|
+
const { queryString, stripped } = stripQueryFingerprinting(originalQuery, privacy);
|
|
95
|
+
strippedQueryRecord = stripped;
|
|
83
96
|
const basePath = targetUrl.split("?")[0] || targetUrl;
|
|
84
|
-
targetUrl =
|
|
97
|
+
targetUrl = queryString ? `${basePath}?${queryString}` : basePath;
|
|
85
98
|
}
|
|
86
99
|
}
|
|
87
100
|
const headers = {};
|
|
@@ -89,6 +102,8 @@ export default defineEventHandler(async (event) => {
|
|
|
89
102
|
if (!value)
|
|
90
103
|
continue;
|
|
91
104
|
const lowerKey = key.toLowerCase();
|
|
105
|
+
if (lowerKey === "host")
|
|
106
|
+
continue;
|
|
92
107
|
if (SENSITIVE_HEADERS.includes(lowerKey))
|
|
93
108
|
continue;
|
|
94
109
|
if (lowerKey === "content-length") {
|
|
@@ -112,7 +127,7 @@ export default defineEventHandler(async (event) => {
|
|
|
112
127
|
continue;
|
|
113
128
|
}
|
|
114
129
|
if (lowerKey === "sec-ch-ua" || lowerKey === "sec-ch-ua-full-version-list") {
|
|
115
|
-
headers[lowerKey] = privacy.hardware ? value.replace(
|
|
130
|
+
headers[lowerKey] = privacy.hardware ? value.replace(CLIENT_HINT_VERSION_RE, ';v="$1"') : value;
|
|
116
131
|
continue;
|
|
117
132
|
}
|
|
118
133
|
if (lowerKey === "sec-ch-ua-platform-version" || lowerKey === "sec-ch-ua-arch" || lowerKey === "sec-ch-ua-model" || lowerKey === "sec-ch-ua-bitness") {
|
|
@@ -139,7 +154,6 @@ export default defineEventHandler(async (event) => {
|
|
|
139
154
|
let rawBody;
|
|
140
155
|
let passthroughBody = false;
|
|
141
156
|
const method = event.method?.toUpperCase();
|
|
142
|
-
const originalQuery = getQuery(event);
|
|
143
157
|
const isWriteMethod = method === "POST" || method === "PUT" || method === "PATCH";
|
|
144
158
|
if (isWriteMethod) {
|
|
145
159
|
if (isBinaryBody || !anyPrivacy) {
|
|
@@ -192,6 +206,7 @@ export default defineEventHandler(async (event) => {
|
|
|
192
206
|
}
|
|
193
207
|
}
|
|
194
208
|
}
|
|
209
|
+
const nitro = useNitroApp();
|
|
195
210
|
await nitro.hooks.callHook("nuxt-scripts:proxy", {
|
|
196
211
|
timestamp: Date.now(),
|
|
197
212
|
path: event.path,
|
|
@@ -206,7 +221,7 @@ export default defineEventHandler(async (event) => {
|
|
|
206
221
|
},
|
|
207
222
|
stripped: {
|
|
208
223
|
headers,
|
|
209
|
-
query:
|
|
224
|
+
query: strippedQueryRecord ?? originalQuery,
|
|
210
225
|
body: passthroughBody ? "<passthrough>" : body ?? null
|
|
211
226
|
}
|
|
212
227
|
});
|
|
@@ -233,23 +248,18 @@ export default defineEventHandler(async (event) => {
|
|
|
233
248
|
});
|
|
234
249
|
} catch (err) {
|
|
235
250
|
clearTimeout(timeoutId);
|
|
236
|
-
log("[proxy]
|
|
237
|
-
if (path.includes("/collect") || path.includes("/tr") || path.includes("/events")) {
|
|
238
|
-
event.node.res.statusCode = 204;
|
|
239
|
-
return "";
|
|
240
|
-
}
|
|
241
|
-
const isTimeout = err instanceof Error && (err.message.includes("aborted") || err.message.includes("timeout"));
|
|
251
|
+
log("[proxy] Upstream error:", err);
|
|
242
252
|
throw createError({
|
|
243
|
-
statusCode:
|
|
244
|
-
statusMessage:
|
|
245
|
-
message:
|
|
253
|
+
statusCode: 502,
|
|
254
|
+
statusMessage: "Bad Gateway",
|
|
255
|
+
message: `Proxy upstream request failed: ${targetUrl}`
|
|
246
256
|
});
|
|
257
|
+
} finally {
|
|
258
|
+
clearTimeout(timeoutId);
|
|
247
259
|
}
|
|
248
|
-
clearTimeout(timeoutId);
|
|
249
260
|
log("[proxy] Response:", response.status, response.statusText);
|
|
250
|
-
const skipHeaders = ["set-cookie", "transfer-encoding", "content-encoding", "content-length"];
|
|
251
261
|
response.headers.forEach((value, key) => {
|
|
252
|
-
if (!
|
|
262
|
+
if (!SKIP_RESPONSE_HEADERS.has(key.toLowerCase())) {
|
|
253
263
|
setResponseHeader(event, key, value);
|
|
254
264
|
}
|
|
255
265
|
});
|