@nuxt/scripts 2.0.0-beta.5 → 2.0.0-beta.7
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/LICENSE.md +9 -0
- package/dist/devtools-client/200.html +1 -1
- package/dist/devtools-client/404.html +1 -1
- package/dist/devtools-client/_nuxt/BI6wdYky.js +1 -0
- package/dist/devtools-client/_nuxt/BQKaRBnk.js +179 -0
- package/dist/devtools-client/_nuxt/BckE5qrE.js +1 -0
- package/dist/devtools-client/_nuxt/CIwvJvFr.js +1 -0
- package/dist/devtools-client/_nuxt/Car86Ubo.js +3 -0
- package/dist/devtools-client/_nuxt/{Dat651Oh.js → ClT2ZYzs.js} +1 -1
- package/dist/devtools-client/_nuxt/Cs0md1ml.js +1 -0
- package/dist/devtools-client/_nuxt/D4iN56En.js +1 -0
- package/dist/devtools-client/_nuxt/DN3hUMR_.js +1 -0
- package/dist/devtools-client/_nuxt/DXEYGql4.js +1 -0
- package/dist/devtools-client/_nuxt/Divy0_cA.js +8 -0
- package/dist/devtools-client/_nuxt/QMsSHdby.js +6 -0
- package/dist/devtools-client/_nuxt/WbNXtEed.js +2 -0
- package/dist/devtools-client/_nuxt/builds/latest.json +1 -1
- package/dist/devtools-client/_nuxt/builds/meta/7f4505e1-4a64-4e0a-b3dd-aa394b0cd7f2.json +1 -0
- package/dist/devtools-client/_nuxt/entry.-RqqMwHr.css +2 -0
- package/dist/devtools-client/_nuxt/error-404.BJ1JSMYb.css +1 -0
- package/dist/devtools-client/_nuxt/error-500.BBf0uW5X.css +1 -0
- package/dist/devtools-client/_nuxt/{pages.aU4WirOM.css → pages.BTJrCFzE.css} +1 -1
- package/dist/devtools-client/docs/index.html +1 -1
- package/dist/devtools-client/first-party/index.html +1 -1
- package/dist/devtools-client/index.html +1 -1
- package/dist/devtools-client/registry/index.html +1 -1
- package/dist/module.d.mts +1 -0
- package/dist/module.d.ts +1 -0
- package/dist/module.json +1 -1
- package/dist/module.mjs +4 -1
- package/dist/registry.mjs +24 -1
- package/dist/runtime/components/Leaflet/ScriptLeafletMap.d.vue.ts +5 -5
- package/dist/runtime/components/Leaflet/ScriptLeafletMap.vue.d.ts +5 -5
- package/dist/runtime/components/MapLibre/ScriptMapLibreGeoJson.d.vue.ts +14 -35
- package/dist/runtime/components/MapLibre/ScriptMapLibreGeoJson.vue +194 -12
- package/dist/runtime/components/MapLibre/ScriptMapLibreGeoJson.vue.d.ts +14 -35
- package/dist/runtime/components/MapLibre/ScriptMapLibreMap.d.vue.ts +22 -86
- package/dist/runtime/components/MapLibre/ScriptMapLibreMap.vue +16 -4
- package/dist/runtime/components/MapLibre/ScriptMapLibreMap.vue.d.ts +22 -86
- package/dist/runtime/components/MapLibre/ScriptMapLibreMarker.d.vue.ts +9 -18
- package/dist/runtime/components/MapLibre/ScriptMapLibreMarker.vue.d.ts +9 -18
- package/dist/runtime/components/MapLibre/ScriptMapLibreNavigationControl.d.vue.ts +3 -8
- package/dist/runtime/components/MapLibre/ScriptMapLibreNavigationControl.vue.d.ts +3 -8
- package/dist/runtime/components/MapLibre/ScriptMapLibrePopup.d.vue.ts +7 -14
- package/dist/runtime/components/MapLibre/ScriptMapLibrePopup.vue.d.ts +7 -14
- package/dist/runtime/components/MapLibre/types.d.ts +186 -0
- package/dist/runtime/components/MapLibre/types.js +0 -0
- package/dist/runtime/components/MapLibre/useMapLibreResource.d.ts +8 -1
- package/dist/runtime/components/MapLibre/useMapLibreResource.js +9 -2
- package/dist/runtime/components/ScriptCarbonAds.vue +3 -1
- package/dist/runtime/components/ScriptGoogleAdsense.d.vue.ts +1 -1
- package/dist/runtime/components/ScriptGoogleAdsense.vue.d.ts +1 -1
- package/dist/runtime/registry/pulse-analytics.d.ts +32 -0
- package/dist/runtime/registry/pulse-analytics.js +80 -0
- package/dist/runtime/registry/schemas.d.ts +42 -0
- package/dist/runtime/registry/schemas.js +42 -0
- package/dist/runtime/registry/tawk-to.d.ts +126 -0
- package/dist/runtime/registry/tawk-to.js +147 -0
- package/dist/runtime/server/proxy-handler.d.ts +0 -4
- package/dist/runtime/server/proxy-handler.js +109 -38
- package/dist/runtime/server/utils/network-dispatcher.platform.d.ts +2 -2
- package/dist/runtime/server/utils/network-dispatcher.platform.js +4 -1
- package/dist/runtime/types.d.ts +6 -1
- package/dist/stats.mjs +81 -0
- package/dist/types-source.mjs +159 -6
- package/dist/types.d.mts +2 -0
- package/package.json +23 -23
- package/dist/devtools-client/_nuxt/2p1_IuX2.js +0 -1
- package/dist/devtools-client/_nuxt/9elIQxwW.js +0 -1
- package/dist/devtools-client/_nuxt/B-kTnbRv.js +0 -1
- package/dist/devtools-client/_nuxt/BDNMzG2s.js +0 -1
- package/dist/devtools-client/_nuxt/BNPn63Jz.js +0 -1
- package/dist/devtools-client/_nuxt/BuTlAAeI.js +0 -152
- package/dist/devtools-client/_nuxt/C41E8Pp1.js +0 -8
- package/dist/devtools-client/_nuxt/CDDBpkXG.js +0 -3
- package/dist/devtools-client/_nuxt/Cbmw_5H5.js +0 -1
- package/dist/devtools-client/_nuxt/DAsiyhPm.js +0 -6
- package/dist/devtools-client/_nuxt/DabLKy7M.js +0 -1
- package/dist/devtools-client/_nuxt/DiZU_C4m.js +0 -1
- package/dist/devtools-client/_nuxt/KsX6Az5B.js +0 -1
- package/dist/devtools-client/_nuxt/LFNkKKtz.js +0 -28
- package/dist/devtools-client/_nuxt/UmWNrBO5.js +0 -2
- package/dist/devtools-client/_nuxt/builds/meta/778de0a6-ec82-430f-966c-9a96d75eb772.json +0 -1
- package/dist/devtools-client/_nuxt/entry.CYUdJFoE.css +0 -2
- package/dist/devtools-client/_nuxt/error-404.DnwL1N6v.css +0 -1
- package/dist/devtools-client/_nuxt/error-500.DEbXRLdm.css +0 -1
|
@@ -753,6 +753,34 @@ export const RedditPixelOptions = object({
|
|
|
753
753
|
*/
|
|
754
754
|
id: string()
|
|
755
755
|
});
|
|
756
|
+
export const PulseAnalyticsOptions = object({
|
|
757
|
+
/**
|
|
758
|
+
* The site domain as registered in Pulse.
|
|
759
|
+
* @see https://docs.ciphera.net/pulse/script-installation
|
|
760
|
+
*/
|
|
761
|
+
domain: string(),
|
|
762
|
+
/**
|
|
763
|
+
* The API origin the tracker posts events to. Only needed for a self-hosted
|
|
764
|
+
* or reverse-proxied Pulse API.
|
|
765
|
+
* @default 'https://pulse-api.ciphera.net'
|
|
766
|
+
*/
|
|
767
|
+
apiUrl: optional(string()),
|
|
768
|
+
/**
|
|
769
|
+
* Record scroll depth.
|
|
770
|
+
* @default true
|
|
771
|
+
*/
|
|
772
|
+
trackScroll: optional(boolean()),
|
|
773
|
+
/**
|
|
774
|
+
* Record outbound link clicks as `outbound_link` events.
|
|
775
|
+
* @default true
|
|
776
|
+
*/
|
|
777
|
+
trackOutbound: optional(boolean()),
|
|
778
|
+
/**
|
|
779
|
+
* Record file download clicks as `file_download` events.
|
|
780
|
+
* @default true
|
|
781
|
+
*/
|
|
782
|
+
trackDownloads: optional(boolean())
|
|
783
|
+
});
|
|
756
784
|
export const RybbitAnalyticsOptions = object({
|
|
757
785
|
/**
|
|
758
786
|
* Your Rybbit site ID.
|
|
@@ -1107,6 +1135,20 @@ export const StripeOptions = object({
|
|
|
1107
1135
|
*/
|
|
1108
1136
|
version: optional(union([literal("v3"), literal("acacia"), literal("basil"), literal("clover"), literal("dahlia"), string()]))
|
|
1109
1137
|
});
|
|
1138
|
+
export const TawkToOptions = object({
|
|
1139
|
+
/**
|
|
1140
|
+
* Your Tawk.to property ID: the first path segment of the widget embed URL
|
|
1141
|
+
* `https://embed.tawk.to/<propertyId>/<widgetId>`.
|
|
1142
|
+
* @see https://dashboard.tawk.to/
|
|
1143
|
+
*/
|
|
1144
|
+
propertyId: pipe(string(), minLength(1)),
|
|
1145
|
+
/**
|
|
1146
|
+
* Your Tawk.to widget ID: the second path segment of the widget embed URL
|
|
1147
|
+
* `https://embed.tawk.to/<propertyId>/<widgetId>`.
|
|
1148
|
+
* @see https://dashboard.tawk.to/
|
|
1149
|
+
*/
|
|
1150
|
+
widgetId: pipe(string(), minLength(1))
|
|
1151
|
+
});
|
|
1110
1152
|
export const TikTokPixelOptions = object({
|
|
1111
1153
|
/**
|
|
1112
1154
|
* Your TikTok Pixel ID.
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import type { Ref } from 'vue';
|
|
2
|
+
import type { RegistryScriptInput, UseScriptContext } from '#nuxt-scripts/types';
|
|
3
|
+
import { TawkToOptions } from './schemas.js';
|
|
4
|
+
export { TawkToOptions };
|
|
5
|
+
export type TawkToInput = RegistryScriptInput<typeof TawkToOptions, false, false>;
|
|
6
|
+
export type TawkToStatus = 'online' | 'away' | 'offline';
|
|
7
|
+
export type TawkToWindowType = 'inline' | 'embed';
|
|
8
|
+
export type TawkToWidgetPosition = 'br' | 'bl' | 'cr' | 'cl' | 'tr' | 'tl';
|
|
9
|
+
export interface TawkToVisitor {
|
|
10
|
+
name?: string;
|
|
11
|
+
email?: string;
|
|
12
|
+
/** Visitor phone number in E.164 format (e.g. `+15551234567`). */
|
|
13
|
+
phone?: string;
|
|
14
|
+
/** HMAC-SHA256 signature for Tawk's Secure Mode, generated server-side by the consumer. */
|
|
15
|
+
hash?: string;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* The `window.Tawk_API` surface, as exposed through `proxy`. `proxy` is
|
|
19
|
+
* fire-and-forget: unhead's script proxy queues/replays calls but always
|
|
20
|
+
* discards their return value, even once the script is fully loaded (and it
|
|
21
|
+
* has no `set` trap, so plain property assignment through it goes nowhere).
|
|
22
|
+
* That means only void-returning actions belong here - real getters and the
|
|
23
|
+
* `visitor` setter live on `useScriptTawkTo()`'s own return value instead
|
|
24
|
+
* (see `TawkToEvents`), backed directly by `window.Tawk_API`.
|
|
25
|
+
* @see https://developer.tawk.to/jsapi/
|
|
26
|
+
*/
|
|
27
|
+
export interface TawkToApi {
|
|
28
|
+
/** Starts the chat. Pass `{ showWidget: true }` to also show the widget. */
|
|
29
|
+
start: (options?: {
|
|
30
|
+
showWidget?: boolean;
|
|
31
|
+
}) => void;
|
|
32
|
+
shutdown: () => void;
|
|
33
|
+
maximize: () => void;
|
|
34
|
+
minimize: () => void;
|
|
35
|
+
toggle: () => void;
|
|
36
|
+
popup: () => void;
|
|
37
|
+
showWidget: () => void;
|
|
38
|
+
hideWidget: () => void;
|
|
39
|
+
toggleVisibility: () => void;
|
|
40
|
+
endChat: () => void;
|
|
41
|
+
getWindowType: () => TawkToWindowType;
|
|
42
|
+
getStatus: () => TawkToStatus;
|
|
43
|
+
isChatMaximized: () => boolean;
|
|
44
|
+
isChatMinimized: () => boolean;
|
|
45
|
+
isChatHidden: () => boolean;
|
|
46
|
+
isChatOngoing: () => boolean;
|
|
47
|
+
isVisitorEngaged: () => boolean;
|
|
48
|
+
/** Set by Tawk once the widget has finished loading. The embed writes a boolean (`!0`), not a number. */
|
|
49
|
+
onLoaded?: boolean;
|
|
50
|
+
/** Set by Tawk before the widget begins loading. */
|
|
51
|
+
onBeforeLoaded?: boolean;
|
|
52
|
+
widgetPosition: () => TawkToWidgetPosition;
|
|
53
|
+
visitor?: TawkToVisitor;
|
|
54
|
+
setAttributes: (attributes: Record<string, string>, callback?: (error: Error | null) => void) => void;
|
|
55
|
+
addEvent: (event: string, metadata?: Record<string, unknown>, callback?: (error: Error | null) => void) => void;
|
|
56
|
+
addTags: (tags: string[], callback?: (error: Error | null) => void) => void;
|
|
57
|
+
removeTags: (tags: string[], callback?: (error: Error | null) => void) => void;
|
|
58
|
+
switchWidget: (data: {
|
|
59
|
+
propertyId: string;
|
|
60
|
+
widgetId: string;
|
|
61
|
+
}, callback?: (error: Error | null) => void) => void;
|
|
62
|
+
}
|
|
63
|
+
declare global {
|
|
64
|
+
interface Window {
|
|
65
|
+
Tawk_API?: TawkToApi;
|
|
66
|
+
Tawk_LoadStart?: Date;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* The subset of `TawkToApi` that `proxy` actually exposes: the getters, the
|
|
71
|
+
* `visitor` setter and the `onLoaded`/`onBeforeLoaded` flags are omitted since
|
|
72
|
+
* none of them work through the fire-and-forget proxy (see `TawkToApi`'s doc
|
|
73
|
+
* comment). They're still real members of the underlying `window.Tawk_API`
|
|
74
|
+
* object, just not reachable via `proxy`.
|
|
75
|
+
*/
|
|
76
|
+
export type TawkToProxyApi = Omit<TawkToApi, 'getWindowType' | 'getStatus' | 'isChatMaximized' | 'isChatMinimized' | 'isChatHidden' | 'isChatOngoing' | 'isVisitorEngaged' | 'widgetPosition' | 'visitor' | 'onLoaded' | 'onBeforeLoaded'>;
|
|
77
|
+
/**
|
|
78
|
+
* Reactive state and typed event listeners bridged from the `window`
|
|
79
|
+
* `CustomEvent`s Tawk's embed script dispatches (`tawkLoad`, `tawkStatusChange`, etc).
|
|
80
|
+
* These aren't part of the documented `Tawk_API.onXxx = fn` callback-property API -
|
|
81
|
+
* they're a separate, verified-in-the-browser signal the embed script also fires.
|
|
82
|
+
*/
|
|
83
|
+
export interface TawkToEvents {
|
|
84
|
+
isHidden: Readonly<Ref<boolean>>;
|
|
85
|
+
isMinimized: Readonly<Ref<boolean>>;
|
|
86
|
+
isMaximized: Readonly<Ref<boolean>>;
|
|
87
|
+
/** The operator status Tawk reports (`getStatus()`) — not to be confused with `status`, the script's own load state. */
|
|
88
|
+
chatStatus: Readonly<Ref<TawkToStatus>>;
|
|
89
|
+
unreadCount: Readonly<Ref<number>>;
|
|
90
|
+
getWindowType: () => TawkToWindowType | undefined;
|
|
91
|
+
getStatus: () => TawkToStatus | undefined;
|
|
92
|
+
isChatMaximized: () => boolean;
|
|
93
|
+
isChatMinimized: () => boolean;
|
|
94
|
+
isChatHidden: () => boolean;
|
|
95
|
+
isChatOngoing: () => boolean;
|
|
96
|
+
isVisitorEngaged: () => boolean;
|
|
97
|
+
widgetPosition: () => TawkToWidgetPosition | undefined;
|
|
98
|
+
/**
|
|
99
|
+
* Sets `Tawk_API.visitor` directly - assigning through `proxy.visitor` is a no-op
|
|
100
|
+
* (no `set` trap). Pre-insertion only: Tawk honors `Tawk_API.visitor` until the
|
|
101
|
+
* embed script is requested, so a call after that warns and does nothing - use
|
|
102
|
+
* `window.Tawk_API.setAttributes()` for post-load identity changes.
|
|
103
|
+
*/
|
|
104
|
+
setVisitor: (data: TawkToVisitor) => void;
|
|
105
|
+
onLoad: (cb: () => void) => () => void;
|
|
106
|
+
onBeforeLoad: (cb: () => void) => () => void;
|
|
107
|
+
onStatusChange: (cb: (status: TawkToStatus) => void) => () => void;
|
|
108
|
+
onChatMaximized: (cb: () => void) => () => void;
|
|
109
|
+
onChatMinimized: (cb: () => void) => () => void;
|
|
110
|
+
onChatHidden: (cb: () => void) => () => void;
|
|
111
|
+
onChatStarted: (cb: () => void) => () => void;
|
|
112
|
+
onChatEnded: (cb: () => void) => () => void;
|
|
113
|
+
onPrechatSubmit: (cb: (data: Record<string, unknown>) => void) => () => void;
|
|
114
|
+
onOfflineSubmit: (cb: (data: Record<string, unknown>) => void) => () => void;
|
|
115
|
+
onChatMessageVisitor: (cb: (message: string) => void) => () => void;
|
|
116
|
+
onChatMessageAgent: (cb: (message: string) => void) => () => void;
|
|
117
|
+
onChatMessageSystem: (cb: (message: string) => void) => () => void;
|
|
118
|
+
onAgentJoinChat: (cb: (data: Record<string, unknown>) => void) => () => void;
|
|
119
|
+
onAgentLeaveChat: (cb: (data: Record<string, unknown>) => void) => () => void;
|
|
120
|
+
onChatSatisfaction: (cb: (satisfaction: number) => void) => () => void;
|
|
121
|
+
onVisitorNameChanged: (cb: (visitorName: string) => void) => () => void;
|
|
122
|
+
onFileUpload: (cb: (link: string) => void) => () => void;
|
|
123
|
+
onTagsUpdated: (cb: (data: Record<string, unknown>) => void) => () => void;
|
|
124
|
+
onUnreadCountChanged: (cb: (count: number) => void) => () => void;
|
|
125
|
+
}
|
|
126
|
+
export declare function useScriptTawkTo<T extends TawkToProxyApi>(_options?: TawkToInput): UseScriptContext<T> & TawkToEvents;
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import { joinURL } from "ufo";
|
|
2
|
+
import { ref } from "vue";
|
|
3
|
+
import { useRegistryScript } from "../utils.js";
|
|
4
|
+
import { TawkToOptions } from "./schemas.js";
|
|
5
|
+
export { TawkToOptions };
|
|
6
|
+
const isHidden = ref(false);
|
|
7
|
+
const isMinimized = ref(false);
|
|
8
|
+
const isMaximized = ref(false);
|
|
9
|
+
const chatStatus = ref("offline");
|
|
10
|
+
const unreadCount = ref(0);
|
|
11
|
+
function listen(event, cb) {
|
|
12
|
+
if (import.meta.server)
|
|
13
|
+
return () => {
|
|
14
|
+
};
|
|
15
|
+
const handler = (e) => cb(e.detail);
|
|
16
|
+
window.addEventListener(event, handler);
|
|
17
|
+
return () => window.removeEventListener(event, handler);
|
|
18
|
+
}
|
|
19
|
+
let stateBridged = false;
|
|
20
|
+
function ensureStateBridge() {
|
|
21
|
+
if (stateBridged)
|
|
22
|
+
return;
|
|
23
|
+
stateBridged = true;
|
|
24
|
+
listen("tawkLoad", () => {
|
|
25
|
+
isHidden.value = !!window.Tawk_API?.isChatHidden?.();
|
|
26
|
+
isMinimized.value = !!window.Tawk_API?.isChatMinimized?.();
|
|
27
|
+
isMaximized.value = !!window.Tawk_API?.isChatMaximized?.();
|
|
28
|
+
chatStatus.value = window.Tawk_API?.getStatus?.() ?? "offline";
|
|
29
|
+
});
|
|
30
|
+
listen("tawkStatusChange", (detail) => {
|
|
31
|
+
chatStatus.value = detail;
|
|
32
|
+
});
|
|
33
|
+
listen("tawkChatHidden", () => {
|
|
34
|
+
isHidden.value = true;
|
|
35
|
+
});
|
|
36
|
+
listen("tawkChatMinimized", () => {
|
|
37
|
+
isMinimized.value = true;
|
|
38
|
+
isMaximized.value = false;
|
|
39
|
+
});
|
|
40
|
+
listen("tawkChatMaximized", () => {
|
|
41
|
+
isMaximized.value = true;
|
|
42
|
+
isMinimized.value = false;
|
|
43
|
+
});
|
|
44
|
+
listen("tawkUnreadCountChanged", (detail) => {
|
|
45
|
+
unreadCount.value = detail;
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
function resyncHiddenState() {
|
|
49
|
+
if (import.meta.server)
|
|
50
|
+
return;
|
|
51
|
+
isHidden.value = !!window.Tawk_API?.isChatHidden?.();
|
|
52
|
+
}
|
|
53
|
+
const visibilityCommands = /* @__PURE__ */ new Set(["hideWidget", "showWidget", "toggleVisibility"]);
|
|
54
|
+
const TAWK_PROXY_DECORATED = Symbol("nuxt-scripts.tawk-proxy-decorated");
|
|
55
|
+
export function useScriptTawkTo(_options) {
|
|
56
|
+
const instance = useRegistryScript("tawkTo", (options) => ({
|
|
57
|
+
scriptInput: {
|
|
58
|
+
src: joinURL("https://embed.tawk.to", options.propertyId, options.widgetId),
|
|
59
|
+
async: true,
|
|
60
|
+
crossorigin: "anonymous"
|
|
61
|
+
},
|
|
62
|
+
schema: import.meta.dev ? TawkToOptions : void 0,
|
|
63
|
+
scriptOptions: {
|
|
64
|
+
resolve({ waitFor }) {
|
|
65
|
+
if (window.Tawk_API?.onLoaded)
|
|
66
|
+
return window.Tawk_API;
|
|
67
|
+
return waitFor((resolve, reject) => {
|
|
68
|
+
const stop = listen("tawkLoad", () => {
|
|
69
|
+
stop();
|
|
70
|
+
if (window.Tawk_API)
|
|
71
|
+
resolve(window.Tawk_API);
|
|
72
|
+
else
|
|
73
|
+
reject(new Error("[nuxt-scripts] Tawk.to reported ready without exposing window.Tawk_API"));
|
|
74
|
+
});
|
|
75
|
+
return stop;
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
clientInit: import.meta.server ? void 0 : () => {
|
|
80
|
+
window.Tawk_API = window.Tawk_API || {};
|
|
81
|
+
window.Tawk_LoadStart = /* @__PURE__ */ new Date();
|
|
82
|
+
}
|
|
83
|
+
}), _options);
|
|
84
|
+
if (!import.meta.server) {
|
|
85
|
+
ensureStateBridge();
|
|
86
|
+
const shared = instance.script || instance;
|
|
87
|
+
if (shared.proxy && !shared[TAWK_PROXY_DECORATED]) {
|
|
88
|
+
shared.proxy = new Proxy(shared.proxy, {
|
|
89
|
+
get(target, prop, receiver) {
|
|
90
|
+
const value = Reflect.get(target, prop, receiver);
|
|
91
|
+
if (!(typeof prop === "string" && visibilityCommands.has(prop)) || typeof value !== "function")
|
|
92
|
+
return value;
|
|
93
|
+
return (...args) => {
|
|
94
|
+
;
|
|
95
|
+
value(...args);
|
|
96
|
+
resyncHiddenState();
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
Object.defineProperty(shared, TAWK_PROXY_DECORATED, { value: true });
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
instance.isHidden = isHidden;
|
|
104
|
+
instance.isMinimized = isMinimized;
|
|
105
|
+
instance.isMaximized = isMaximized;
|
|
106
|
+
instance.chatStatus = chatStatus;
|
|
107
|
+
instance.unreadCount = unreadCount;
|
|
108
|
+
instance.onLoad = (cb) => listen("tawkLoad", cb);
|
|
109
|
+
instance.onBeforeLoad = (cb) => listen("tawkBeforeLoad", cb);
|
|
110
|
+
instance.onStatusChange = (cb) => listen("tawkStatusChange", cb);
|
|
111
|
+
instance.onChatMaximized = (cb) => listen("tawkChatMaximized", cb);
|
|
112
|
+
instance.onChatMinimized = (cb) => listen("tawkChatMinimized", cb);
|
|
113
|
+
instance.onChatHidden = (cb) => listen("tawkChatHidden", cb);
|
|
114
|
+
instance.onChatStarted = (cb) => listen("tawkChatStarted", cb);
|
|
115
|
+
instance.onChatEnded = (cb) => listen("tawkChatEnded", cb);
|
|
116
|
+
instance.onPrechatSubmit = (cb) => listen("tawkPrechatSubmit", cb);
|
|
117
|
+
instance.onOfflineSubmit = (cb) => listen("tawkOfflineSubmit", cb);
|
|
118
|
+
instance.onChatMessageVisitor = (cb) => listen("tawkChatMessageVisitor", cb);
|
|
119
|
+
instance.onChatMessageAgent = (cb) => listen("tawkChatMessageAgent", cb);
|
|
120
|
+
instance.onChatMessageSystem = (cb) => listen("tawkChatMessageSystem", cb);
|
|
121
|
+
instance.onAgentJoinChat = (cb) => listen("tawkAgentJoinChat", cb);
|
|
122
|
+
instance.onAgentLeaveChat = (cb) => listen("tawkAgentLeaveChat", cb);
|
|
123
|
+
instance.onChatSatisfaction = (cb) => listen("tawkChatSatisfaction", cb);
|
|
124
|
+
instance.onVisitorNameChanged = (cb) => listen("tawkVisitorNameChanged", cb);
|
|
125
|
+
instance.onFileUpload = (cb) => listen("tawkFileUpload", cb);
|
|
126
|
+
instance.onTagsUpdated = (cb) => listen("tawkTagsUpdated", cb);
|
|
127
|
+
instance.onUnreadCountChanged = (cb) => listen("tawkUnreadCountChanged", cb);
|
|
128
|
+
instance.getWindowType = () => import.meta.server ? void 0 : window.Tawk_API?.getWindowType?.();
|
|
129
|
+
instance.getStatus = () => import.meta.server ? void 0 : window.Tawk_API?.getStatus?.();
|
|
130
|
+
instance.isChatMaximized = () => !import.meta.server && !!window.Tawk_API?.isChatMaximized?.();
|
|
131
|
+
instance.isChatMinimized = () => !import.meta.server && !!window.Tawk_API?.isChatMinimized?.();
|
|
132
|
+
instance.isChatHidden = () => !import.meta.server && !!window.Tawk_API?.isChatHidden?.();
|
|
133
|
+
instance.isChatOngoing = () => !import.meta.server && !!window.Tawk_API?.isChatOngoing?.();
|
|
134
|
+
instance.isVisitorEngaged = () => !import.meta.server && !!window.Tawk_API?.isVisitorEngaged?.();
|
|
135
|
+
instance.widgetPosition = () => import.meta.server ? void 0 : window.Tawk_API?.widgetPosition?.();
|
|
136
|
+
instance.setVisitor = (data) => {
|
|
137
|
+
if (import.meta.server)
|
|
138
|
+
return;
|
|
139
|
+
window.Tawk_API = window.Tawk_API || {};
|
|
140
|
+
if (instance.status.value !== "awaitingLoad" || window.Tawk_API.onLoaded) {
|
|
141
|
+
console.warn("[nuxt-scripts] Tawk.to: setVisitor() only works before the widget script is inserted. Tawk drops visitor data written after that - set it before the widget loads, or use window.Tawk_API.setAttributes({ name, email, phone, hash }) afterwards.");
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
window.Tawk_API.visitor = data;
|
|
145
|
+
};
|
|
146
|
+
return instance;
|
|
147
|
+
}
|
|
@@ -1,8 +1,4 @@
|
|
|
1
1
|
export declare const SKIP_REQUEST_HEADERS: Set<string>;
|
|
2
2
|
export declare function withResponseBodyIdleTimeout(body: ReadableStream<Uint8Array>, timeoutMs: number, onTimeout: () => void): ReadableStream<Uint8Array>;
|
|
3
|
-
/**
|
|
4
|
-
* Privacy-aware proxy handler for first-party script collection endpoints.
|
|
5
|
-
* Routes requests to third-party analytics while protecting user privacy.
|
|
6
|
-
*/
|
|
7
3
|
declare const _default: import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<void | null>>;
|
|
8
4
|
export default _default;
|
|
@@ -15,6 +15,9 @@ const COMPRESSION_RE = /gzip|deflate|br|compress|base64/i;
|
|
|
15
15
|
const CLIENT_HINT_VERSION_RE = /;v="(\d+)\.[^"]*"/g;
|
|
16
16
|
const MAX_TRANSFORM_BODY_SIZE = 2 * 1024 * 1024;
|
|
17
17
|
const UPSTREAM_TIMEOUT_MS = 15e3;
|
|
18
|
+
const MAX_UPSTREAM_REDIRECTS = 5;
|
|
19
|
+
const REDIRECT_STATUSES = /* @__PURE__ */ new Set([301, 302, 303, 307, 308]);
|
|
20
|
+
const REQUEST_BODY_HEADERS = ["content-encoding", "content-language", "content-length", "content-location", "content-type"];
|
|
18
21
|
const SKIP_RESPONSE_HEADERS = /* @__PURE__ */ new Set([
|
|
19
22
|
"alt-svc",
|
|
20
23
|
"clear-site-data",
|
|
@@ -46,7 +49,7 @@ export const SKIP_REQUEST_HEADERS = /* @__PURE__ */ new Set([
|
|
|
46
49
|
"transfer-encoding",
|
|
47
50
|
"upgrade"
|
|
48
51
|
]);
|
|
49
|
-
async function
|
|
52
|
+
async function readBodyBytes(event) {
|
|
50
53
|
const contentLength = Number(getHeaders(event)["content-length"] || 0);
|
|
51
54
|
if (Number.isFinite(contentLength) && contentLength > MAX_TRANSFORM_BODY_SIZE) {
|
|
52
55
|
throw createError({ statusCode: 413, statusMessage: "Proxy request body too large" });
|
|
@@ -83,7 +86,7 @@ async function readTransformBody(event) {
|
|
|
83
86
|
body.set(chunk, offset);
|
|
84
87
|
offset += chunk.byteLength;
|
|
85
88
|
}
|
|
86
|
-
return
|
|
89
|
+
return body;
|
|
87
90
|
}
|
|
88
91
|
export function withResponseBodyIdleTimeout(body, timeoutMs, onTimeout) {
|
|
89
92
|
const reader = body.getReader();
|
|
@@ -145,6 +148,64 @@ function stripQueryFingerprinting(query, privacy) {
|
|
|
145
148
|
}
|
|
146
149
|
return { queryString: params.toString(), stripped };
|
|
147
150
|
}
|
|
151
|
+
function isUpstreamRedirect(status) {
|
|
152
|
+
return REDIRECT_STATUSES.has(status);
|
|
153
|
+
}
|
|
154
|
+
function upstreamFetchError(err, timedOut) {
|
|
155
|
+
const blockedPrivateNetwork = isPrivateNetworkResolutionError(err);
|
|
156
|
+
return createError({
|
|
157
|
+
statusCode: blockedPrivateNetwork ? 403 : timedOut ? 504 : 502,
|
|
158
|
+
statusMessage: blockedPrivateNetwork ? "Local network targets are not allowed" : timedOut ? "Gateway Timeout" : "Bad Gateway",
|
|
159
|
+
message: "Proxy upstream request failed",
|
|
160
|
+
cause: err,
|
|
161
|
+
data: {
|
|
162
|
+
errorName: err?.name,
|
|
163
|
+
errorCode: timedOut ? "TIMEOUT" : err?.code
|
|
164
|
+
}
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
function resolveProxyRedirect(response, state, redirectCount, urlAllowed) {
|
|
168
|
+
const location = response.headers.get("location");
|
|
169
|
+
if (!location) {
|
|
170
|
+
throw createError({
|
|
171
|
+
statusCode: 502,
|
|
172
|
+
statusMessage: "Invalid upstream redirect",
|
|
173
|
+
message: "Upstream redirect has no Location header"
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
if (redirectCount >= MAX_UPSTREAM_REDIRECTS) {
|
|
177
|
+
throw createError({
|
|
178
|
+
statusCode: 502,
|
|
179
|
+
statusMessage: "Too many upstream redirects",
|
|
180
|
+
message: "Upstream redirect limit exceeded"
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
let nextUrl;
|
|
184
|
+
try {
|
|
185
|
+
nextUrl = new URL(location, state.url);
|
|
186
|
+
} catch (cause) {
|
|
187
|
+
throw createError({
|
|
188
|
+
statusCode: 502,
|
|
189
|
+
statusMessage: "Invalid upstream redirect",
|
|
190
|
+
message: "Upstream redirect URL is invalid",
|
|
191
|
+
cause
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
if (!urlAllowed(nextUrl)) {
|
|
195
|
+
throw createError({
|
|
196
|
+
statusCode: 502,
|
|
197
|
+
statusMessage: "Unsafe upstream redirect",
|
|
198
|
+
message: `Upstream redirect target is not allowed: ${nextUrl.origin}`
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
const switchToGet = response.status === 303 && state.method !== "GET" && state.method !== "HEAD" || (response.status === 301 || response.status === 302) && state.method === "POST";
|
|
202
|
+
if (!switchToGet)
|
|
203
|
+
return { ...state, url: nextUrl };
|
|
204
|
+
const headers = { ...state.headers };
|
|
205
|
+
for (const header of REQUEST_BODY_HEADERS)
|
|
206
|
+
delete headers[header];
|
|
207
|
+
return { url: nextUrl, method: "GET", body: void 0, headers };
|
|
208
|
+
}
|
|
148
209
|
export default defineEventHandler(async (event) => {
|
|
149
210
|
const config = useRuntimeConfig();
|
|
150
211
|
const proxyConfig = config["nuxt-scripts-proxy"];
|
|
@@ -282,12 +343,14 @@ export default defineEventHandler(async (event) => {
|
|
|
282
343
|
}
|
|
283
344
|
let body;
|
|
284
345
|
let rawBody;
|
|
346
|
+
let rawBodyBytes;
|
|
285
347
|
let passthroughBody = false;
|
|
286
348
|
if (isWriteMethod) {
|
|
349
|
+
rawBodyBytes = await readBodyBytes(event);
|
|
287
350
|
if (!shouldTransformBody) {
|
|
288
351
|
passthroughBody = true;
|
|
289
352
|
} else if (transformableBodyType === "form") {
|
|
290
|
-
const formBody =
|
|
353
|
+
const formBody = rawBodyBytes === void 0 ? void 0 : new TextDecoder().decode(rawBodyBytes);
|
|
291
354
|
rawBody = formBody;
|
|
292
355
|
if (formBody != null) {
|
|
293
356
|
const params = new URLSearchParams(formBody);
|
|
@@ -315,7 +378,7 @@ export default defineEventHandler(async (event) => {
|
|
|
315
378
|
body = transformed.toString();
|
|
316
379
|
}
|
|
317
380
|
} else {
|
|
318
|
-
const jsonBody =
|
|
381
|
+
const jsonBody = rawBodyBytes === void 0 ? void 0 : new TextDecoder().decode(rawBodyBytes);
|
|
319
382
|
if (jsonBody !== void 0) {
|
|
320
383
|
try {
|
|
321
384
|
rawBody = JSON.parse(jsonBody);
|
|
@@ -365,55 +428,63 @@ export default defineEventHandler(async (event) => {
|
|
|
365
428
|
controller.abort();
|
|
366
429
|
}, UPSTREAM_TIMEOUT_MS);
|
|
367
430
|
let fetchBody;
|
|
368
|
-
if (passthroughBody
|
|
369
|
-
|
|
431
|
+
if (passthroughBody) {
|
|
432
|
+
if (rawBodyBytes && rawBodyBytes.byteLength > 0)
|
|
433
|
+
fetchBody = rawBodyBytes;
|
|
370
434
|
} else if (body !== void 0) {
|
|
371
435
|
fetchBody = transformableBodyType === "json" ? JSON.stringify(body) : String(body);
|
|
372
436
|
}
|
|
437
|
+
const hopAllowed = (url) => url.protocol === "https:" && !url.username && !url.password && (!url.port || url.port === "443") && isPublicNetworkHostname(url.hostname) && Object.keys(domainPrivacy).some((configDomain) => matchDomain(url.hostname, configDomain));
|
|
373
438
|
let response;
|
|
374
439
|
let network;
|
|
375
440
|
try {
|
|
376
441
|
network = await createPublicNetworkDispatcher();
|
|
377
|
-
|
|
442
|
+
let state = {
|
|
443
|
+
url: new URL(targetUrl),
|
|
378
444
|
method: method || "GET",
|
|
379
|
-
headers,
|
|
380
445
|
body: fetchBody,
|
|
381
|
-
|
|
382
|
-
// Don't send cookies to third parties
|
|
383
|
-
signal: controller.signal,
|
|
384
|
-
redirect: "manual",
|
|
385
|
-
duplex: fetchBody instanceof ReadableStream ? "half" : void 0
|
|
446
|
+
headers
|
|
386
447
|
};
|
|
387
|
-
|
|
448
|
+
for (let redirectCount = 0; ; redirectCount++) {
|
|
449
|
+
let hop;
|
|
450
|
+
try {
|
|
451
|
+
hop = await network.fetch(state.url.toString(), {
|
|
452
|
+
method: state.method,
|
|
453
|
+
headers: state.headers,
|
|
454
|
+
body: state.body,
|
|
455
|
+
credentials: "omit",
|
|
456
|
+
// Don't send cookies to third parties
|
|
457
|
+
signal: controller.signal,
|
|
458
|
+
redirect: "manual"
|
|
459
|
+
});
|
|
460
|
+
} catch (err) {
|
|
461
|
+
log("[proxy] Upstream error:", err);
|
|
462
|
+
throw upstreamFetchError(err, timedOut);
|
|
463
|
+
}
|
|
464
|
+
log("[proxy] Response:", hop.status, hop.statusText);
|
|
465
|
+
if (!isUpstreamRedirect(hop.status)) {
|
|
466
|
+
response = hop;
|
|
467
|
+
break;
|
|
468
|
+
}
|
|
469
|
+
let next;
|
|
470
|
+
try {
|
|
471
|
+
next = resolveProxyRedirect(hop, state, redirectCount, hopAllowed);
|
|
472
|
+
} catch (err) {
|
|
473
|
+
await hop.body?.cancel(err).catch((cancelError) => Object.assign(err, { cleanupError: cancelError }));
|
|
474
|
+
throw err;
|
|
475
|
+
}
|
|
476
|
+
const redirectDiscarded = new Error("Upstream redirect response body discarded");
|
|
477
|
+
await hop.body?.cancel(redirectDiscarded).catch((cancelError) => Object.assign(redirectDiscarded, { cause: cancelError }));
|
|
478
|
+
log("[proxy] Following redirect:", next.url.toString());
|
|
479
|
+
state = next;
|
|
480
|
+
}
|
|
388
481
|
clearTimeout(timeoutId);
|
|
389
482
|
} catch (err) {
|
|
390
483
|
clearTimeout(timeoutId);
|
|
391
484
|
await closePublicNetworkDispatcher(network, err);
|
|
392
|
-
|
|
393
|
-
const blockedPrivateNetwork = isPrivateNetworkResolutionError(err);
|
|
394
|
-
throw createError({
|
|
395
|
-
statusCode: blockedPrivateNetwork ? 403 : timedOut ? 504 : 502,
|
|
396
|
-
statusMessage: blockedPrivateNetwork ? "Local network targets are not allowed" : timedOut ? "Gateway Timeout" : "Bad Gateway",
|
|
397
|
-
message: "Proxy upstream request failed",
|
|
398
|
-
cause: err,
|
|
399
|
-
data: {
|
|
400
|
-
errorName: err?.name,
|
|
401
|
-
errorCode: timedOut ? "TIMEOUT" : err?.code
|
|
402
|
-
}
|
|
403
|
-
});
|
|
404
|
-
}
|
|
405
|
-
log("[proxy] Response:", response.status, response.statusText);
|
|
406
|
-
if (response.status >= 300 && response.status < 400 && response.status !== 304) {
|
|
407
|
-
clearTimeout(timeoutId);
|
|
408
|
-
const redirectError = createError({
|
|
409
|
-
statusCode: 502,
|
|
410
|
-
statusMessage: "Unsafe upstream redirect",
|
|
411
|
-
message: "Proxy upstream returned a redirect that was not followed"
|
|
412
|
-
});
|
|
413
|
-
await response.body?.cancel(redirectError).catch((cancelError) => Object.assign(redirectError, { cleanupError: cancelError }));
|
|
414
|
-
await closePublicNetworkDispatcher(network, redirectError);
|
|
415
|
-
throw redirectError;
|
|
485
|
+
throw err;
|
|
416
486
|
}
|
|
487
|
+
log("[proxy] Upstream settled:", response.status);
|
|
417
488
|
const responseConnectionHeaders = new Set(
|
|
418
489
|
(response.headers.get("connection") || "").split(",").map((header) => header.trim().toLowerCase()).filter(Boolean)
|
|
419
490
|
);
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
export declare const createNetworkDispatcher:
|
|
1
|
+
import type { PublicNetworkDispatcher } from './network-host.js';
|
|
2
|
+
export declare const createNetworkDispatcher: () => Promise<PublicNetworkDispatcher>;
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
export const createNetworkDispatcher = async () => ({
|
|
2
|
-
fetch:
|
|
2
|
+
// workerd's native fetch throws `TypeError: Illegal invocation` when a
|
|
3
|
+
// detached reference is called as a method (e.g. `dispatcher.fetch(...)`),
|
|
4
|
+
// so pin the receiver before handing the function to callers.
|
|
5
|
+
fetch: globalThis.fetch.bind(globalThis),
|
|
3
6
|
close: async () => {
|
|
4
7
|
}
|
|
5
8
|
});
|
package/dist/runtime/types.d.ts
CHANGED
|
@@ -34,12 +34,14 @@ import type { NpmInput } from './registry/npm.js';
|
|
|
34
34
|
import type { PayPalInput } from './registry/paypal.js';
|
|
35
35
|
import type { PlausibleAnalyticsInput } from './registry/plausible-analytics.js';
|
|
36
36
|
import type { PostHogInput } from './registry/posthog.js';
|
|
37
|
+
import type { PulseAnalyticsInput } from './registry/pulse-analytics.js';
|
|
37
38
|
import type { RedditPixelInput } from './registry/reddit-pixel.js';
|
|
38
39
|
import type { RybbitAnalyticsInput } from './registry/rybbit-analytics.js';
|
|
39
40
|
import type { SegmentInput } from './registry/segment.js';
|
|
40
41
|
import type { SnapTrPixelInput } from './registry/snapchat-pixel.js';
|
|
41
42
|
import type { SpeedCurveInput } from './registry/speedcurve.js';
|
|
42
43
|
import type { StripeInput } from './registry/stripe.js';
|
|
44
|
+
import type { TawkToInput } from './registry/tawk-to.js';
|
|
43
45
|
import type { TikTokPixelInput } from './registry/tiktok-pixel.js';
|
|
44
46
|
import type { UmamiAnalyticsInput } from './registry/umami-analytics.js';
|
|
45
47
|
import type { UsercentricsInput } from './registry/usercentrics.js';
|
|
@@ -51,6 +53,7 @@ import type { YouTubePlayerInput } from './registry/youtube-player.js';
|
|
|
51
53
|
import type { ProxyPrivacyInput } from './server/utils/privacy.js';
|
|
52
54
|
export type { Cluster, ClusterStats, MarkerClustererContext, MarkerClustererInstance, MarkerClustererOptions } from './components/GoogleMaps/types.js';
|
|
53
55
|
export { MARKER_CLUSTERER_INJECTION_KEY } from './components/GoogleMaps/types.js';
|
|
56
|
+
export type { ScriptMapLibreGeoJsonEmits, ScriptMapLibreGeoJsonLayer, ScriptMapLibreGeoJsonProps, ScriptMapLibreGeoJsonResource, ScriptMapLibreMapEmits, ScriptMapLibreMapExpose, ScriptMapLibreMapProps, ScriptMapLibreMapSlots, ScriptMapLibreMarkerEmits, ScriptMapLibreMarkerProps, ScriptMapLibreNavigationControlProps, ScriptMapLibrePopupEmits, ScriptMapLibrePopupProps, } from './components/MapLibre/types.js';
|
|
54
57
|
export type WarmupStrategy = false | 'preload' | 'preconnect' | 'dns-prefetch';
|
|
55
58
|
/**
|
|
56
59
|
* GCMv2 consent category value.
|
|
@@ -265,6 +268,7 @@ export interface ScriptRegistry {
|
|
|
265
268
|
linkedinInsight?: LinkedInInsightInput;
|
|
266
269
|
paypal?: PayPalInput;
|
|
267
270
|
posthog?: PostHogInput;
|
|
271
|
+
pulseAnalytics?: PulseAnalyticsInput;
|
|
268
272
|
matomoAnalytics?: MatomoAnalyticsInput;
|
|
269
273
|
mixpanelAnalytics?: MixpanelAnalyticsInput;
|
|
270
274
|
rybbitAnalytics?: RybbitAnalyticsInput;
|
|
@@ -272,6 +276,7 @@ export interface ScriptRegistry {
|
|
|
272
276
|
segment?: SegmentInput;
|
|
273
277
|
speedcurve?: SpeedCurveInput;
|
|
274
278
|
stripe?: StripeInput;
|
|
279
|
+
tawkTo?: TawkToInput;
|
|
275
280
|
tiktokPixel?: TikTokPixelInput;
|
|
276
281
|
xEmbed?: XEmbedInput;
|
|
277
282
|
xPixel?: XPixelInput;
|
|
@@ -289,7 +294,7 @@ export interface ScriptRegistry {
|
|
|
289
294
|
* Built-in registry script keys — not affected by module augmentation.
|
|
290
295
|
* Use this to type-check records that must enumerate all built-in scripts (logos, meta, etc.).
|
|
291
296
|
*/
|
|
292
|
-
export type BuiltInRegistryScriptKey = 'ahrefsAnalytics' | 'bingUet' | 'blueskyEmbed' | 'calendly' | 'carbonAds' | 'crisp' | 'clarity' | 'cloudflareWebAnalytics' | 'databuddyAnalytics' | 'deskcrew' | 'metaPixel' | 'fathomAnalytics' | 'instagramEmbed' | 'plausibleAnalytics' | 'googleAdsense' | 'googleAnalytics' | 'googleMaps' | 'leaflet' | 'maplibre' | 'googleRecaptcha' | 'googleSignIn' | 'lemonSqueezy' | 'googleTagManager' | 'hotjar' | 'intercom' | 'linkedinInsight' | 'paypal' | 'posthog' | 'matomoAnalytics' | 'mixpanelAnalytics' | 'rybbitAnalytics' | 'redditPixel' | 'segment' | 'stripe' | 'tiktokPixel' | 'xEmbed' | 'xPixel' | 'snapchatPixel' | 'speedcurve' | 'youtubePlayer' | 'vercelAnalytics' | 'vimeoPlayer' | 'umamiAnalytics' | 'usercentrics' | 'gravatar' | 'npm';
|
|
297
|
+
export type BuiltInRegistryScriptKey = 'ahrefsAnalytics' | 'bingUet' | 'blueskyEmbed' | 'calendly' | 'carbonAds' | 'crisp' | 'clarity' | 'cloudflareWebAnalytics' | 'databuddyAnalytics' | 'deskcrew' | 'metaPixel' | 'fathomAnalytics' | 'instagramEmbed' | 'plausibleAnalytics' | 'googleAdsense' | 'googleAnalytics' | 'googleMaps' | 'leaflet' | 'maplibre' | 'googleRecaptcha' | 'googleSignIn' | 'lemonSqueezy' | 'googleTagManager' | 'hotjar' | 'intercom' | 'linkedinInsight' | 'paypal' | 'posthog' | 'pulseAnalytics' | 'matomoAnalytics' | 'mixpanelAnalytics' | 'rybbitAnalytics' | 'redditPixel' | 'segment' | 'stripe' | 'tawkTo' | 'tiktokPixel' | 'xEmbed' | 'xPixel' | 'snapchatPixel' | 'speedcurve' | 'youtubePlayer' | 'vercelAnalytics' | 'vimeoPlayer' | 'umamiAnalytics' | 'usercentrics' | 'gravatar' | 'npm';
|
|
293
298
|
/**
|
|
294
299
|
* Union of all explicit registry script keys (excludes npm pattern).
|
|
295
300
|
* Includes both built-in and augmented keys.
|