@nuxt/scripts 1.0.0-beta.2 → 1.0.0-beta.21
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/README.md +3 -3
- package/dist/client/200.html +1 -1
- package/dist/client/404.html +1 -1
- package/dist/client/_nuxt/{DvH517bE.js → BlmrFwhD.js} +1 -1
- package/dist/client/_nuxt/{DfLgoB--.js → BwCYQWJt.js} +1 -1
- package/dist/client/_nuxt/DvbTvDd0.js +162 -0
- package/dist/client/_nuxt/{B66N9HCo.js → ZrewjUYk.js} +1 -1
- package/dist/client/_nuxt/builds/latest.json +1 -1
- package/dist/client/_nuxt/builds/meta/6660a023-888d-415f-b66d-ce774e6f8f11.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 +27 -18
- package/dist/module.d.ts +178 -0
- package/dist/module.json +1 -1
- package/dist/module.mjs +763 -526
- package/dist/registry.d.ts +6 -0
- package/dist/registry.mjs +109 -21
- package/dist/runtime/components/GoogleMaps/ScriptGoogleMaps.d.vue.ts +2 -2
- package/dist/runtime/components/GoogleMaps/ScriptGoogleMaps.vue +7 -7
- package/dist/runtime/components/GoogleMaps/ScriptGoogleMaps.vue.d.ts +2 -2
- package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsAdvancedMarkerElement.vue +6 -6
- package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsCircle.vue +7 -7
- package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsHeatmapLayer.vue +6 -6
- package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsInfoWindow.vue +12 -12
- package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsMarker.vue +6 -6
- package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsMarkerClusterer.d.vue.ts +1 -1
- package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsMarkerClusterer.vue +6 -6
- package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsMarkerClusterer.vue.d.ts +1 -1
- package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsPinElement.vue +5 -5
- package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsPolygon.vue +7 -7
- package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsPolyline.vue +7 -7
- package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsRectangle.vue +7 -7
- package/dist/runtime/components/ScriptCrisp.vue +1 -1
- package/dist/runtime/components/ScriptGoogleAdsense.vue +1 -1
- package/dist/runtime/components/ScriptGravatar.d.vue.ts +22 -0
- package/dist/runtime/components/ScriptGravatar.vue +46 -0
- package/dist/runtime/components/ScriptGravatar.vue.d.ts +22 -0
- package/dist/runtime/components/ScriptInstagramEmbed.vue +1 -1
- package/dist/runtime/components/ScriptIntercom.vue +4 -3
- package/dist/runtime/components/ScriptPayPalButtons.d.vue.ts +43 -32
- package/dist/runtime/components/ScriptPayPalButtons.vue +48 -79
- package/dist/runtime/components/ScriptPayPalButtons.vue.d.ts +43 -32
- package/dist/runtime/components/ScriptPayPalMessages.d.vue.ts +37 -23
- package/dist/runtime/components/ScriptPayPalMessages.vue +46 -50
- package/dist/runtime/components/ScriptPayPalMessages.vue.d.ts +37 -23
- package/dist/runtime/components/ScriptStripePricingTable.vue +2 -2
- package/dist/runtime/components/ScriptVimeoPlayer.d.vue.ts +9 -0
- package/dist/runtime/components/ScriptVimeoPlayer.vue +13 -10
- package/dist/runtime/components/ScriptVimeoPlayer.vue.d.ts +9 -0
- package/dist/runtime/components/ScriptXEmbed.d.vue.ts +1 -1
- package/dist/runtime/components/ScriptXEmbed.vue +1 -1
- package/dist/runtime/components/ScriptXEmbed.vue.d.ts +1 -1
- package/dist/runtime/components/ScriptYouTubePlayer.d.vue.ts +2 -2
- package/dist/runtime/components/ScriptYouTubePlayer.vue +11 -5
- package/dist/runtime/components/ScriptYouTubePlayer.vue.d.ts +2 -2
- package/dist/runtime/composables/useScript.js +11 -6
- package/dist/runtime/composables/useScriptEventPage.js +2 -2
- package/dist/runtime/composables/useScriptTriggerConsent.js +1 -1
- package/dist/runtime/composables/useScriptTriggerElement.js +1 -1
- package/dist/runtime/composables/useScriptTriggerIdleTimeout.js +1 -1
- package/dist/runtime/registry/clarity.d.ts +10 -15
- package/dist/runtime/registry/clarity.js +22 -31
- package/dist/runtime/registry/cloudflare-web-analytics.d.ts +2 -13
- package/dist/runtime/registry/cloudflare-web-analytics.js +2 -14
- package/dist/runtime/registry/crisp.d.ts +9 -39
- package/dist/runtime/registry/crisp.js +2 -33
- package/dist/runtime/registry/databuddy-analytics.d.ts +2 -35
- package/dist/runtime/registry/databuddy-analytics.js +20 -45
- package/dist/runtime/registry/fathom-analytics.d.ts +6 -25
- package/dist/runtime/registry/fathom-analytics.js +2 -24
- package/dist/runtime/registry/google-adsense.d.ts +2 -10
- package/dist/runtime/registry/google-adsense.js +2 -11
- package/dist/runtime/registry/google-analytics.d.ts +3 -5
- package/dist/runtime/registry/google-analytics.js +3 -8
- package/dist/runtime/registry/google-maps.d.ts +3 -9
- package/dist/runtime/registry/google-maps.js +2 -8
- package/dist/runtime/registry/google-recaptcha.d.ts +2 -6
- package/dist/runtime/registry/google-recaptcha.js +4 -12
- package/dist/runtime/registry/google-sign-in.d.ts +2 -13
- package/dist/runtime/registry/google-sign-in.js +2 -22
- package/dist/runtime/registry/google-tag-manager.d.ts +3 -28
- package/dist/runtime/registry/google-tag-manager.js +4 -27
- package/dist/runtime/registry/gravatar.d.ts +25 -0
- package/dist/runtime/registry/gravatar.js +32 -0
- package/dist/runtime/registry/hotjar.d.ts +3 -5
- package/dist/runtime/registry/hotjar.js +2 -5
- package/dist/runtime/registry/instagram-embed.d.ts +2 -17
- package/dist/runtime/registry/instagram-embed.js +4 -19
- package/dist/runtime/registry/intercom.d.ts +3 -11
- package/dist/runtime/registry/intercom.js +2 -12
- package/dist/runtime/registry/matomo-analytics.d.ts +2 -11
- package/dist/runtime/registry/matomo-analytics.js +3 -12
- package/dist/runtime/registry/meta-pixel.d.ts +3 -5
- package/dist/runtime/registry/meta-pixel.js +2 -4
- package/dist/runtime/registry/npm.d.ts +2 -6
- package/dist/runtime/registry/npm.js +2 -9
- package/dist/runtime/registry/paypal.d.ts +4 -25
- package/dist/runtime/registry/paypal.js +3 -66
- package/dist/runtime/registry/plausible-analytics.js +18 -13
- package/dist/runtime/registry/posthog.d.ts +10 -11
- package/dist/runtime/registry/posthog.js +7 -20
- package/dist/runtime/registry/reddit-pixel.d.ts +4 -5
- package/dist/runtime/registry/reddit-pixel.js +2 -4
- package/dist/runtime/registry/rybbit-analytics.d.ts +2 -14
- package/dist/runtime/registry/rybbit-analytics.js +7 -19
- package/dist/runtime/registry/schemas.d.ts +946 -0
- package/dist/runtime/registry/schemas.js +901 -0
- package/dist/runtime/registry/segment.d.ts +2 -5
- package/dist/runtime/registry/segment.js +2 -5
- package/dist/runtime/registry/snapchat-pixel.d.ts +3 -32
- package/dist/runtime/registry/snapchat-pixel.js +2 -20
- package/dist/runtime/registry/stripe.d.ts +3 -4
- package/dist/runtime/registry/stripe.js +2 -4
- package/dist/runtime/registry/tiktok-pixel.d.ts +3 -6
- package/dist/runtime/registry/tiktok-pixel.js +2 -6
- package/dist/runtime/registry/umami-analytics.d.ts +2 -31
- package/dist/runtime/registry/umami-analytics.js +2 -36
- package/dist/runtime/registry/vercel-analytics.d.ts +29 -0
- package/dist/runtime/registry/vercel-analytics.js +84 -0
- package/dist/runtime/registry/vimeo-player.d.ts +2 -2
- package/dist/runtime/registry/vimeo-player.js +1 -1
- package/dist/runtime/registry/x-embed.d.ts +2 -16
- package/dist/runtime/registry/x-embed.js +2 -17
- package/dist/runtime/registry/x-pixel.d.ts +3 -6
- package/dist/runtime/registry/x-pixel.js +2 -5
- package/dist/runtime/registry/youtube-player.d.ts +7 -7
- package/dist/runtime/registry/youtube-player.js +1 -1
- package/dist/runtime/server/google-static-maps-proxy.js +1 -1
- package/dist/runtime/server/{sw-handler.d.ts → gravatar-proxy.d.ts} +1 -1
- package/dist/runtime/server/gravatar-proxy.js +62 -0
- 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 +22 -13
- package/dist/runtime/server/proxy-handler.js +161 -117
- package/dist/runtime/server/utils/privacy.d.ts +45 -1
- package/dist/runtime/server/utils/privacy.js +103 -40
- package/dist/runtime/server/x-embed.js +3 -2
- package/dist/runtime/types.d.ts +35 -24
- package/dist/runtime/utils/pure.d.ts +0 -4
- package/dist/runtime/utils/pure.js +0 -67
- package/dist/runtime/utils.d.ts +3 -3
- package/dist/runtime/utils.js +12 -7
- package/dist/shared/scripts.Crpn87WB.mjs +318 -0
- package/dist/stats.d.mts +39 -0
- package/dist/stats.d.ts +39 -0
- package/dist/stats.mjs +772 -0
- package/dist/types-source.d.mts +19 -0
- package/dist/types-source.d.ts +19 -0
- package/dist/types-source.mjs +975 -0
- package/package.json +42 -31
- package/dist/client/_nuxt/B8XOar-X.js +0 -162
- package/dist/client/_nuxt/builds/meta/133a46c5-a5c1-4a63-87d1-037947a5bcdb.json +0 -1
- package/dist/client/_nuxt/entry.D45OuV0w.css +0 -1
- package/dist/client/_nuxt/error-404.B57D-jUQ.css +0 -1
- package/dist/client/_nuxt/error-500.DTHUW7BI.css +0 -1
- package/dist/runtime/components/ScriptPayPalMarks.d.vue.ts +0 -52
- package/dist/runtime/components/ScriptPayPalMarks.vue +0 -69
- package/dist/runtime/components/ScriptPayPalMarks.vue.d.ts +0 -52
- package/dist/runtime/plugins/sw-register.client.d.ts +0 -2
- package/dist/runtime/plugins/sw-register.client.js +0 -12
- package/dist/runtime/server/sw-handler.js +0 -25
- package/dist/runtime/sw/proxy-sw.template.d.ts +0 -1
- package/dist/runtime/sw/proxy-sw.template.js +0 -54
package/dist/module.mjs
CHANGED
|
@@ -1,79 +1,36 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { existsSync, readdirSync, readFileSync } from 'node:fs';
|
|
2
|
+
import { useNuxt, addDevServerHandler, extendRouteRules, tryUseNuxt, extendViteConfig, useLogger, addPluginTemplate, addServerHandler, logger as logger$1, addTypeTemplate, defineNuxtModule, createResolver, hasNuxtModule, addImports, addComponentsDir, addTemplate, addBuildPlugin } from '@nuxt/kit';
|
|
3
3
|
import { defu } from 'defu';
|
|
4
|
+
import { join, resolve, relative } from 'pathe';
|
|
4
5
|
import { resolvePackageJSON, readPackageJSON } from 'pkg-types';
|
|
6
|
+
import { lazyEventHandler, eventHandler, createError } from 'h3';
|
|
7
|
+
import { fetch, $fetch } from 'ofetch';
|
|
8
|
+
import { joinURL, parseURL, parseQuery, hasProtocol } from 'ufo';
|
|
9
|
+
import { createStorage } from 'unstorage';
|
|
10
|
+
import fsDriver from 'unstorage/drivers/fs-lite';
|
|
5
11
|
import { addCustomTab } from '@nuxt/devtools-kit';
|
|
12
|
+
import { isCI, provider } from 'std-env';
|
|
13
|
+
import { parseAndWalk, ScopeTracker, walk, ScopeTrackerFunctionParam, ScopeTrackerVariable } from 'oxc-walker';
|
|
14
|
+
import { createUnplugin } from 'unplugin';
|
|
15
|
+
import { pathToFileURL } from 'node:url';
|
|
6
16
|
import { createHash } from 'node:crypto';
|
|
7
17
|
import fsp from 'node:fs/promises';
|
|
8
|
-
import {
|
|
18
|
+
import { colors } from 'consola/utils';
|
|
9
19
|
import MagicString from 'magic-string';
|
|
10
|
-
import { parseAndWalk } from 'oxc-walker';
|
|
11
|
-
import { joinURL, parseURL, parseQuery, hasProtocol } from 'ufo';
|
|
12
20
|
import { hash } from 'ohash';
|
|
13
|
-
import {
|
|
14
|
-
import { colors } from 'consola/utils';
|
|
15
|
-
import { fetch, $fetch } from 'ofetch';
|
|
16
|
-
import { lazyEventHandler, eventHandler, createError } from 'h3';
|
|
17
|
-
import { createStorage } from 'unstorage';
|
|
18
|
-
import fsDriver from 'unstorage/drivers/fs-lite';
|
|
19
|
-
import { rewriteScriptUrls } from '../dist/runtime/utils/pure.js';
|
|
20
|
-
import { pathToFileURL } from 'node:url';
|
|
21
|
-
import { isCI, provider } from 'std-env';
|
|
21
|
+
import { g as getAllProxyConfigs, r as routesToInterceptRules, a as getProxyConfig } from './shared/scripts.Crpn87WB.mjs';
|
|
22
22
|
import { registry } from './registry.mjs';
|
|
23
23
|
|
|
24
|
-
const DEVTOOLS_UI_ROUTE = "/__nuxt-scripts";
|
|
25
|
-
const DEVTOOLS_UI_LOCAL_PORT = 3300;
|
|
26
|
-
|
|
27
|
-
async function setupDevToolsUI(options, resolve, nuxt = useNuxt()) {
|
|
28
|
-
const clientPath = await resolve("./client");
|
|
29
|
-
const isProductionBuild = existsSync(clientPath);
|
|
30
|
-
if (isProductionBuild) {
|
|
31
|
-
nuxt.hook("vite:serverCreated", async (server) => {
|
|
32
|
-
const sirv = await import('sirv').then((r) => r.default || r);
|
|
33
|
-
server.middlewares.use(
|
|
34
|
-
DEVTOOLS_UI_ROUTE,
|
|
35
|
-
sirv(clientPath, { dev: true, single: true })
|
|
36
|
-
);
|
|
37
|
-
});
|
|
38
|
-
} else {
|
|
39
|
-
extendViteConfig((config) => {
|
|
40
|
-
config.server = config.server || {};
|
|
41
|
-
config.server.proxy = config.server.proxy || {};
|
|
42
|
-
config.server.proxy[DEVTOOLS_UI_ROUTE] = {
|
|
43
|
-
target: `http://localhost:${DEVTOOLS_UI_LOCAL_PORT}${DEVTOOLS_UI_ROUTE}`,
|
|
44
|
-
changeOrigin: true,
|
|
45
|
-
followRedirects: true,
|
|
46
|
-
rewrite: (path) => path.replace(DEVTOOLS_UI_ROUTE, "")
|
|
47
|
-
};
|
|
48
|
-
});
|
|
49
|
-
}
|
|
50
|
-
addCustomTab({
|
|
51
|
-
// unique identifier
|
|
52
|
-
name: "nuxt-scripts",
|
|
53
|
-
// title to display in the tab
|
|
54
|
-
title: "Scripts",
|
|
55
|
-
// any icon from Iconify, or a URL to an image
|
|
56
|
-
icon: "carbon:script",
|
|
57
|
-
// iframe view
|
|
58
|
-
view: {
|
|
59
|
-
type: "iframe",
|
|
60
|
-
src: DEVTOOLS_UI_ROUTE
|
|
61
|
-
}
|
|
62
|
-
});
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
const logger = useLogger("@nuxt/scripts");
|
|
66
|
-
|
|
67
24
|
const renderedScript = /* @__PURE__ */ new Map();
|
|
68
25
|
const ONE_YEAR_IN_SECONDS = 60 * 60 * 24 * 365;
|
|
69
|
-
|
|
26
|
+
function bundleStorage() {
|
|
70
27
|
const nuxt = tryUseNuxt();
|
|
71
28
|
return createStorage({
|
|
72
29
|
driver: fsDriver({
|
|
73
30
|
base: resolve(nuxt?.options.rootDir || "", "node_modules/.cache/nuxt/scripts")
|
|
74
31
|
})
|
|
75
32
|
});
|
|
76
|
-
}
|
|
33
|
+
}
|
|
77
34
|
function setupPublicAssetStrategy(options = {}) {
|
|
78
35
|
const assetsBaseURL = options.prefix || "/_scripts";
|
|
79
36
|
const nuxt = useNuxt();
|
|
@@ -123,179 +80,308 @@ function setupPublicAssetStrategy(options = {}) {
|
|
|
123
80
|
};
|
|
124
81
|
}
|
|
125
82
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
{
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
83
|
+
const DEVTOOLS_UI_ROUTE = "/__nuxt-scripts";
|
|
84
|
+
const DEVTOOLS_UI_LOCAL_PORT = 3300;
|
|
85
|
+
|
|
86
|
+
async function setupDevToolsUI(options, resolve, nuxt = useNuxt()) {
|
|
87
|
+
const clientPath = await resolve("./client");
|
|
88
|
+
const isProductionBuild = existsSync(clientPath);
|
|
89
|
+
if (isProductionBuild) {
|
|
90
|
+
nuxt.hook("vite:serverCreated", async (server) => {
|
|
91
|
+
const sirv = await import('sirv').then((r) => r.default || r);
|
|
92
|
+
server.middlewares.use(
|
|
93
|
+
DEVTOOLS_UI_ROUTE,
|
|
94
|
+
sirv(clientPath, { dev: true, single: true })
|
|
95
|
+
);
|
|
96
|
+
});
|
|
97
|
+
} else {
|
|
98
|
+
extendViteConfig((config) => {
|
|
99
|
+
config.server = config.server || {};
|
|
100
|
+
config.server.proxy = config.server.proxy || {};
|
|
101
|
+
config.server.proxy[DEVTOOLS_UI_ROUTE] = {
|
|
102
|
+
target: `http://localhost:${DEVTOOLS_UI_LOCAL_PORT}${DEVTOOLS_UI_ROUTE}`,
|
|
103
|
+
changeOrigin: true,
|
|
104
|
+
followRedirects: true,
|
|
105
|
+
rewrite: (path) => path.replace(DEVTOOLS_UI_ROUTE, "")
|
|
106
|
+
};
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
addCustomTab({
|
|
110
|
+
// unique identifier
|
|
111
|
+
name: "nuxt-scripts",
|
|
112
|
+
// title to display in the tab
|
|
113
|
+
title: "Scripts",
|
|
114
|
+
// any icon from Iconify, or a URL to an image
|
|
115
|
+
icon: "carbon:script",
|
|
116
|
+
// iframe view
|
|
117
|
+
view: {
|
|
118
|
+
type: "iframe",
|
|
119
|
+
src: DEVTOOLS_UI_ROUTE
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
const logger = useLogger("@nuxt/scripts");
|
|
125
|
+
|
|
126
|
+
const AUTO_INJECT_DEFS = [
|
|
127
|
+
{
|
|
128
|
+
registryKey: "posthog",
|
|
129
|
+
configField: "apiHost",
|
|
130
|
+
computeValue: (collectPrefix, config) => {
|
|
131
|
+
const region = config.region || "us";
|
|
132
|
+
return region === "eu" ? `${collectPrefix}/ph-eu` : `${collectPrefix}/ph`;
|
|
133
|
+
}
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
registryKey: "plausibleAnalytics",
|
|
137
|
+
configField: "endpoint",
|
|
138
|
+
computeValue: (collectPrefix) => `${collectPrefix}/plausible/api/event`
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
registryKey: "umamiAnalytics",
|
|
142
|
+
configField: "hostUrl",
|
|
143
|
+
computeValue: (collectPrefix) => `${collectPrefix}/umami`
|
|
144
|
+
},
|
|
145
|
+
{
|
|
146
|
+
registryKey: "rybbitAnalytics",
|
|
147
|
+
configField: "analyticsHost",
|
|
148
|
+
computeValue: (collectPrefix) => `${collectPrefix}/rybbit/api`
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
registryKey: "databuddyAnalytics",
|
|
152
|
+
configField: "apiUrl",
|
|
153
|
+
computeValue: (collectPrefix) => `${collectPrefix}/databuddy-api`
|
|
154
|
+
}
|
|
155
|
+
];
|
|
156
|
+
function autoInjectProxyEndpoints(registry, runtimeConfig, collectPrefix) {
|
|
157
|
+
for (const def of AUTO_INJECT_DEFS) {
|
|
158
|
+
const entry = registry[def.registryKey];
|
|
159
|
+
if (!entry || typeof entry !== "object")
|
|
160
|
+
continue;
|
|
161
|
+
const config = Array.isArray(entry) ? entry[0] : entry;
|
|
162
|
+
if (!config || config[def.configField])
|
|
163
|
+
continue;
|
|
164
|
+
config[def.configField] = def.computeValue(collectPrefix, config);
|
|
165
|
+
const rtScripts = runtimeConfig.public?.scripts;
|
|
166
|
+
const rtEntry = rtScripts?.[def.registryKey];
|
|
167
|
+
if (rtEntry && typeof rtEntry === "object") {
|
|
168
|
+
const rtConfig = Array.isArray(rtEntry) ? rtEntry[0] : rtEntry;
|
|
169
|
+
if (rtConfig)
|
|
170
|
+
rtConfig[def.configField] = config[def.configField];
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
function generateInterceptPluginContents(interceptRules) {
|
|
176
|
+
const rulesJson = JSON.stringify(interceptRules);
|
|
177
|
+
return `export default defineNuxtPlugin({
|
|
178
|
+
name: 'nuxt-scripts:intercept',
|
|
179
|
+
enforce: 'pre',
|
|
180
|
+
setup() {
|
|
181
|
+
const rules = ${rulesJson};
|
|
182
|
+
const origBeacon = typeof navigator !== 'undefined' && navigator.sendBeacon
|
|
183
|
+
? navigator.sendBeacon.bind(navigator)
|
|
184
|
+
: () => false;
|
|
185
|
+
const origFetch = globalThis.fetch.bind(globalThis);
|
|
186
|
+
|
|
187
|
+
function rewriteUrl(url) {
|
|
188
|
+
try {
|
|
189
|
+
const parsed = new URL(url, location.origin);
|
|
190
|
+
for (const rule of rules) {
|
|
191
|
+
if (parsed.hostname === rule.pattern || parsed.hostname.endsWith('.' + rule.pattern)) {
|
|
192
|
+
if (rule.pathPrefix && !parsed.pathname.startsWith(rule.pathPrefix)) continue;
|
|
193
|
+
const path = rule.pathPrefix ? parsed.pathname.slice(rule.pathPrefix.length) : parsed.pathname;
|
|
194
|
+
return location.origin + rule.target + (path.startsWith('/') ? '' : '/') + path + parsed.search;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
} catch {}
|
|
198
|
+
return url;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// XMLHttpRequest wrapper \u2014 intercepts .open() to rewrite URL
|
|
202
|
+
const OrigXHR = XMLHttpRequest;
|
|
203
|
+
class ProxiedXHR extends OrigXHR {
|
|
204
|
+
open() {
|
|
205
|
+
const args = Array.from(arguments);
|
|
206
|
+
if (typeof args[1] === 'string') args[1] = rewriteUrl(args[1]);
|
|
207
|
+
return super.open.apply(this, args);
|
|
244
208
|
}
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
// Metrics/telemetry
|
|
259
|
-
{ from: "metrics.hotjar.io", to: `${collectPrefix}/hotjar-metrics` },
|
|
260
|
-
// Insights (ContentSquare integration)
|
|
261
|
-
{ from: "insights.hotjar.com", to: `${collectPrefix}/hotjar-insights` }
|
|
262
|
-
],
|
|
263
|
-
routes: {
|
|
264
|
-
[`${collectPrefix}/hotjar/**`]: { proxy: "https://static.hotjar.com/**" },
|
|
265
|
-
[`${collectPrefix}/hotjar-script/**`]: { proxy: "https://script.hotjar.com/**" },
|
|
266
|
-
[`${collectPrefix}/hotjar-vars/**`]: { proxy: "https://vars.hotjar.com/**" },
|
|
267
|
-
[`${collectPrefix}/hotjar-in/**`]: { proxy: "https://in.hotjar.com/**" },
|
|
268
|
-
[`${collectPrefix}/hotjar-vc/**`]: { proxy: "https://vc.hotjar.com/**" },
|
|
269
|
-
[`${collectPrefix}/hotjar-metrics/**`]: { proxy: "https://metrics.hotjar.io/**" },
|
|
270
|
-
[`${collectPrefix}/hotjar-insights/**`]: { proxy: "https://insights.hotjar.com/**" }
|
|
209
|
+
}
|
|
210
|
+
// Image wrapper \u2014 intercepts .src setter to rewrite URL
|
|
211
|
+
const OrigImage = Image;
|
|
212
|
+
const origSrcDesc = Object.getOwnPropertyDescriptor(HTMLImageElement.prototype, 'src');
|
|
213
|
+
function ProxiedImage(w, h) {
|
|
214
|
+
const img = arguments.length === 2 ? new OrigImage(w, h)
|
|
215
|
+
: arguments.length === 1 ? new OrigImage(w) : new OrigImage();
|
|
216
|
+
if (origSrcDesc && origSrcDesc.set) {
|
|
217
|
+
Object.defineProperty(img, 'src', {
|
|
218
|
+
get() { return origSrcDesc.get.call(this); },
|
|
219
|
+
set(v) { origSrcDesc.set.call(this, typeof v === 'string' ? rewriteUrl(v) : v); },
|
|
220
|
+
configurable: true,
|
|
221
|
+
});
|
|
271
222
|
}
|
|
223
|
+
return img;
|
|
272
224
|
}
|
|
273
|
-
|
|
225
|
+
|
|
226
|
+
globalThis.__nuxtScripts = {
|
|
227
|
+
sendBeacon: (url, data) => origBeacon(rewriteUrl(url), data),
|
|
228
|
+
fetch: (url, opts) => origFetch(typeof url === 'string' ? rewriteUrl(url) : url, opts),
|
|
229
|
+
XMLHttpRequest: ProxiedXHR,
|
|
230
|
+
Image: ProxiedImage,
|
|
231
|
+
};
|
|
232
|
+
},
|
|
233
|
+
})
|
|
234
|
+
`;
|
|
274
235
|
}
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
236
|
+
|
|
237
|
+
function resolveFirstPartyConfig(config) {
|
|
238
|
+
const enabled = !!config.firstParty;
|
|
239
|
+
const prefix = typeof config.firstParty === "object" ? config.firstParty.prefix : void 0;
|
|
240
|
+
const collectPrefix = typeof config.firstParty === "object" ? config.firstParty.collectPrefix || "/_proxy" : "/_proxy";
|
|
241
|
+
const privacy = typeof config.firstParty === "object" ? config.firstParty.privacy : void 0;
|
|
242
|
+
const assetsPrefix = prefix || config.assets?.prefix || "/_scripts";
|
|
243
|
+
return { enabled, prefix, collectPrefix, privacy, assetsPrefix };
|
|
278
244
|
}
|
|
279
|
-
function
|
|
280
|
-
|
|
245
|
+
async function setupFirstPartyHandlers(firstParty, resolvePath) {
|
|
246
|
+
const interceptRules = [];
|
|
247
|
+
addPluginTemplate({
|
|
248
|
+
filename: "nuxt-scripts-intercept.client.mjs",
|
|
249
|
+
getContents() {
|
|
250
|
+
return generateInterceptPluginContents(interceptRules);
|
|
251
|
+
}
|
|
252
|
+
});
|
|
253
|
+
const proxyHandlerPath = await resolvePath("./runtime/server/proxy-handler");
|
|
254
|
+
logger.debug("[nuxt-scripts] Registering proxy handler:", `${firstParty.collectPrefix}/**`, "->", proxyHandlerPath);
|
|
255
|
+
addServerHandler({
|
|
256
|
+
route: `${firstParty.collectPrefix}/**`,
|
|
257
|
+
handler: proxyHandlerPath
|
|
258
|
+
});
|
|
259
|
+
return interceptRules;
|
|
281
260
|
}
|
|
282
|
-
function
|
|
283
|
-
const
|
|
284
|
-
const
|
|
285
|
-
|
|
286
|
-
|
|
261
|
+
function finalizeFirstParty(opts) {
|
|
262
|
+
const { firstParty, interceptRules, registryScriptsWithImport, nuxtOptions } = opts;
|
|
263
|
+
const proxyConfigs = getAllProxyConfigs(firstParty.collectPrefix);
|
|
264
|
+
const registryKeys = Object.keys(opts.registry || {});
|
|
265
|
+
const scriptByKey = /* @__PURE__ */ new Map();
|
|
266
|
+
for (const script of registryScriptsWithImport) {
|
|
267
|
+
if (script.registryKey) {
|
|
268
|
+
scriptByKey.set(script.registryKey, script);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
const neededRoutes = {};
|
|
272
|
+
const routePrivacyOverrides = {};
|
|
273
|
+
const unsupportedScripts = [];
|
|
274
|
+
const unmatchedScripts = [];
|
|
275
|
+
for (const key of registryKeys) {
|
|
276
|
+
const script = scriptByKey.get(key) || registryScriptsWithImport.find((s) => s.import.name.toLowerCase() === `usescript${key.toLowerCase()}`);
|
|
277
|
+
if (!script) {
|
|
278
|
+
unmatchedScripts.push(key);
|
|
287
279
|
continue;
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
280
|
+
}
|
|
281
|
+
const proxyKey = script?.proxy || void 0;
|
|
282
|
+
if (proxyKey) {
|
|
283
|
+
const proxyConfig = proxyConfigs[proxyKey];
|
|
284
|
+
if (proxyConfig?.routes) {
|
|
285
|
+
Object.assign(neededRoutes, proxyConfig.routes);
|
|
286
|
+
for (const routePath of Object.keys(proxyConfig.routes)) {
|
|
287
|
+
routePrivacyOverrides[routePath] = proxyConfig.privacy;
|
|
288
|
+
}
|
|
289
|
+
} else {
|
|
290
|
+
unsupportedScripts.push(key);
|
|
295
291
|
}
|
|
296
292
|
}
|
|
297
293
|
}
|
|
298
|
-
|
|
294
|
+
if (opts.registry) {
|
|
295
|
+
autoInjectProxyEndpoints(opts.registry, nuxtOptions.runtimeConfig, firstParty.collectPrefix);
|
|
296
|
+
}
|
|
297
|
+
if (unmatchedScripts.length) {
|
|
298
|
+
logger.warn(
|
|
299
|
+
`First-party mode: could not find registry scripts for: ${unmatchedScripts.join(", ")}.
|
|
300
|
+
These scripts will not have proxy routes registered. Check that the registry key matches a known script.`
|
|
301
|
+
);
|
|
302
|
+
}
|
|
303
|
+
if (unsupportedScripts.length && nuxtOptions.dev) {
|
|
304
|
+
logger.warn(
|
|
305
|
+
`First-party mode is enabled but these scripts don't support it yet: ${unsupportedScripts.join(", ")}.
|
|
306
|
+
They will load directly from third-party servers. Request support at https://github.com/nuxt/scripts/issues`
|
|
307
|
+
);
|
|
308
|
+
}
|
|
309
|
+
interceptRules.push(...routesToInterceptRules(neededRoutes));
|
|
310
|
+
const flatRoutes = {};
|
|
311
|
+
for (const [path, config] of Object.entries(neededRoutes)) {
|
|
312
|
+
flatRoutes[path] = config.proxy;
|
|
313
|
+
}
|
|
314
|
+
nuxtOptions.runtimeConfig["nuxt-scripts-proxy"] = {
|
|
315
|
+
routes: flatRoutes,
|
|
316
|
+
privacy: firstParty.privacy,
|
|
317
|
+
routePrivacy: routePrivacyOverrides
|
|
318
|
+
};
|
|
319
|
+
if (Object.keys(neededRoutes).length && nuxtOptions.dev) {
|
|
320
|
+
const routeCount = Object.keys(neededRoutes).length;
|
|
321
|
+
const scriptsCount = registryKeys.length;
|
|
322
|
+
const privacyLabel = firstParty.privacy === void 0 ? "per-script" : typeof firstParty.privacy === "boolean" ? firstParty.privacy ? "anonymize" : "passthrough" : "custom";
|
|
323
|
+
logger.success(`First-party mode enabled for ${scriptsCount} script(s), ${routeCount} proxy route(s) configured (privacy: ${privacyLabel})`);
|
|
324
|
+
if (logger.level >= 4) {
|
|
325
|
+
for (const [path, config] of Object.entries(neededRoutes)) {
|
|
326
|
+
logger.debug(` ${path} \u2192 ${config.proxy}`);
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
const staticPresets = ["static", "github-pages", "cloudflare-pages-static"];
|
|
331
|
+
const preset = process.env.NITRO_PRESET || "";
|
|
332
|
+
if (staticPresets.includes(preset)) {
|
|
333
|
+
logger.warn(
|
|
334
|
+
`First-party collection endpoints require a server runtime (detected: ${preset || "static"}).
|
|
335
|
+
Scripts will be bundled, but collection requests will not be proxied.
|
|
336
|
+
|
|
337
|
+
Options:
|
|
338
|
+
1. Configure platform rewrites (Vercel, Netlify, Cloudflare)
|
|
339
|
+
2. Switch to server-rendered mode (ssr: true)
|
|
340
|
+
3. Disable with firstParty: false
|
|
341
|
+
|
|
342
|
+
See: https://scripts.nuxt.com/docs/guides/first-party#static-hosting`
|
|
343
|
+
);
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
const isStackblitz = provider === "stackblitz";
|
|
348
|
+
async function promptToInstall(name, installCommand, options) {
|
|
349
|
+
if (await resolvePackageJSON(name).catch(() => null))
|
|
350
|
+
return true;
|
|
351
|
+
logger$1.info(`Package ${name} is missing`);
|
|
352
|
+
if (isCI)
|
|
353
|
+
return false;
|
|
354
|
+
if (options.prompt === true || options.prompt !== false && !isStackblitz) {
|
|
355
|
+
const confirm = await logger$1.prompt(`Do you want to install ${name} package?`, {
|
|
356
|
+
type: "confirm",
|
|
357
|
+
name: "confirm",
|
|
358
|
+
initial: true
|
|
359
|
+
});
|
|
360
|
+
if (!confirm)
|
|
361
|
+
return false;
|
|
362
|
+
}
|
|
363
|
+
logger$1.info(`Installing ${name}...`);
|
|
364
|
+
try {
|
|
365
|
+
await installCommand();
|
|
366
|
+
logger$1.success(`Installed ${name}`);
|
|
367
|
+
return true;
|
|
368
|
+
} catch (err) {
|
|
369
|
+
logger$1.error(err);
|
|
370
|
+
return false;
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
const installPrompts = /* @__PURE__ */ new Set();
|
|
374
|
+
function installNuxtModule(name, options) {
|
|
375
|
+
if (installPrompts.has(name))
|
|
376
|
+
return;
|
|
377
|
+
installPrompts.add(name);
|
|
378
|
+
const nuxt = tryUseNuxt();
|
|
379
|
+
if (!nuxt)
|
|
380
|
+
return;
|
|
381
|
+
return promptToInstall(name, async () => {
|
|
382
|
+
const { runCommand } = await import(String("nuxi"));
|
|
383
|
+
await runCommand("module", ["add", name, "--cwd", nuxt.options.rootDir]);
|
|
384
|
+
}, { rootDir: nuxt.options.rootDir, searchPaths: nuxt.options.modulesDir, ...options });
|
|
299
385
|
}
|
|
300
386
|
|
|
301
387
|
function isVue(id, opts = {}) {
|
|
@@ -319,13 +405,301 @@ function isVue(id, opts = {}) {
|
|
|
319
405
|
}
|
|
320
406
|
return true;
|
|
321
407
|
}
|
|
322
|
-
const JS_RE = /\.(?:[cm]?j|t)sx?$/;
|
|
408
|
+
const JS_RE$1 = /\.(?:[cm]?j|t)sx?$/;
|
|
323
409
|
function isJS(id) {
|
|
324
410
|
const { pathname } = parseURL(decodeURIComponent(pathToFileURL(id).href));
|
|
325
|
-
return JS_RE.test(pathname);
|
|
411
|
+
return JS_RE$1.test(pathname);
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
const VUE_RE$1 = /\.vue/;
|
|
415
|
+
function NuxtScriptsCheckScripts() {
|
|
416
|
+
return createUnplugin(() => {
|
|
417
|
+
return {
|
|
418
|
+
name: "nuxt-scripts:check-scripts",
|
|
419
|
+
transform: {
|
|
420
|
+
filter: {
|
|
421
|
+
id: VUE_RE$1
|
|
422
|
+
},
|
|
423
|
+
handler(code, id) {
|
|
424
|
+
if (!isVue(id, { type: ["script"] }))
|
|
425
|
+
return;
|
|
426
|
+
if (!code.includes("useScript"))
|
|
427
|
+
return;
|
|
428
|
+
let nameNode;
|
|
429
|
+
let errorNode;
|
|
430
|
+
parseAndWalk(code, id, (_node) => {
|
|
431
|
+
if (_node.type === "VariableDeclaration" && _node.declarations?.[0]?.id?.type === "ObjectPattern") {
|
|
432
|
+
const objPattern = _node.declarations[0]?.id;
|
|
433
|
+
for (const property of objPattern.properties) {
|
|
434
|
+
if (property.type === "Property" && property.key.type === "Identifier" && property.key.name === "$script" && property.value.type === "Identifier") {
|
|
435
|
+
nameNode = _node;
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
if (nameNode) {
|
|
440
|
+
let sequence = _node.type === "SequenceExpression" ? _node : null;
|
|
441
|
+
let assignmentExpression;
|
|
442
|
+
if (_node.type === "VariableDeclaration") {
|
|
443
|
+
if (_node.declarations[0]?.init?.type === "SequenceExpression") {
|
|
444
|
+
sequence = _node.declarations[0]?.init;
|
|
445
|
+
assignmentExpression = _node.declarations[0]?.init?.expressions?.[0];
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
if (sequence && !assignmentExpression) {
|
|
449
|
+
assignmentExpression = sequence.expressions[0]?.type === "AssignmentExpression" ? sequence.expressions[0] : null;
|
|
450
|
+
}
|
|
451
|
+
if (assignmentExpression) {
|
|
452
|
+
const right = assignmentExpression?.right;
|
|
453
|
+
if (right.callee?.name === "_withAsyncContext") {
|
|
454
|
+
if (right.arguments[0]?.body?.name === "$script" || right.arguments[0]?.body?.callee?.object?.name === "$script") {
|
|
455
|
+
errorNode = nameNode;
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
});
|
|
461
|
+
if (errorNode) {
|
|
462
|
+
return this.error(new Error("You can't use a top-level await on $script as it will never resolve."));
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
};
|
|
467
|
+
});
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
const WORD_OR_DOLLAR_RE = /[\w$]/;
|
|
471
|
+
const GA_COLLECT_RE = /([\w$])?"https:\/\/"\+\(.*?\)\+"\.google-analytics\.com\/g\/collect"/g;
|
|
472
|
+
const GA_ANALYTICS_COLLECT_RE = /([\w$])?"https:\/\/"\+\(.*?\)\+"\.analytics\.google\.com\/g\/collect"/g;
|
|
473
|
+
const FATHOM_SELF_HOSTED_RE = /\.src\.indexOf\("cdn\.usefathom\.com"\)\s*<\s*0/;
|
|
474
|
+
function isPropertyKeyAST(parent, ctx) {
|
|
475
|
+
return parent?.type === "Property" && ctx.key === "key" || parent?.type === "SwitchCase" && ctx.key === "test";
|
|
476
|
+
}
|
|
477
|
+
function matchAndRewrite(value, rewrites) {
|
|
478
|
+
for (const { from, to } of rewrites) {
|
|
479
|
+
const isSuffixMatch = from.startsWith(".");
|
|
480
|
+
const fromSlashIdx = from.indexOf("/");
|
|
481
|
+
const fromHost = fromSlashIdx > 0 ? from.slice(0, fromSlashIdx) : from;
|
|
482
|
+
const fromPath = fromSlashIdx > 0 ? from.slice(fromSlashIdx) : "";
|
|
483
|
+
if (!value.includes(fromHost))
|
|
484
|
+
continue;
|
|
485
|
+
const url = parseURL(value);
|
|
486
|
+
let shouldRewrite = false;
|
|
487
|
+
let rewriteSuffix = "";
|
|
488
|
+
if (url.host) {
|
|
489
|
+
const hostMatches = isSuffixMatch ? url.host.endsWith(fromHost) : url.host === fromHost;
|
|
490
|
+
if (hostMatches) {
|
|
491
|
+
const fullPath = url.pathname + (url.search || "") + (url.hash || "");
|
|
492
|
+
if (fromPath && fullPath.startsWith(fromPath)) {
|
|
493
|
+
shouldRewrite = true;
|
|
494
|
+
rewriteSuffix = fullPath.slice(fromPath.length);
|
|
495
|
+
} else if (!fromPath) {
|
|
496
|
+
shouldRewrite = true;
|
|
497
|
+
rewriteSuffix = fullPath;
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
} else if (value.startsWith("//")) {
|
|
501
|
+
const hostPart = value.slice(2).split("/")[0];
|
|
502
|
+
const hostMatches = isSuffixMatch ? hostPart?.endsWith(fromHost) ?? false : hostPart === fromHost;
|
|
503
|
+
if (hostMatches) {
|
|
504
|
+
const remainder = value.slice(2 + (hostPart?.length ?? 0));
|
|
505
|
+
if (fromPath && remainder.startsWith(fromPath)) {
|
|
506
|
+
shouldRewrite = true;
|
|
507
|
+
rewriteSuffix = remainder.slice(fromPath.length);
|
|
508
|
+
} else if (!fromPath) {
|
|
509
|
+
shouldRewrite = true;
|
|
510
|
+
rewriteSuffix = remainder;
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
} else if (fromPath && (value.startsWith(from) || isSuffixMatch && value.includes(from))) {
|
|
514
|
+
const domainEnd = value.indexOf(from) + from.length;
|
|
515
|
+
const nextChar = value[domainEnd];
|
|
516
|
+
if (!nextChar || nextChar === "/" || nextChar === "?" || nextChar === "#") {
|
|
517
|
+
shouldRewrite = true;
|
|
518
|
+
rewriteSuffix = value.slice(domainEnd);
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
if (shouldRewrite) {
|
|
522
|
+
return rewriteSuffix === "/" || rewriteSuffix.startsWith("?") || rewriteSuffix.startsWith("#") ? to + rewriteSuffix : joinURL(to, rewriteSuffix);
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
return null;
|
|
526
|
+
}
|
|
527
|
+
const WINDOW_GLOBALS = /* @__PURE__ */ new Set(["window", "self", "globalThis"]);
|
|
528
|
+
const NAVIGATOR_GLOBALS = /* @__PURE__ */ new Set(["navigator"]);
|
|
529
|
+
function resolveToGlobal(name, scopeTracker, depth = 0) {
|
|
530
|
+
if (depth > 10)
|
|
531
|
+
return null;
|
|
532
|
+
const decl = scopeTracker.getDeclaration(name);
|
|
533
|
+
if (!decl)
|
|
534
|
+
return name;
|
|
535
|
+
if (decl instanceof ScopeTrackerFunctionParam)
|
|
536
|
+
return null;
|
|
537
|
+
if (decl instanceof ScopeTrackerVariable) {
|
|
538
|
+
const declarators = decl.variableNode.declarations;
|
|
539
|
+
if (!declarators)
|
|
540
|
+
return null;
|
|
541
|
+
for (const declarator of declarators) {
|
|
542
|
+
const id = declarator.id;
|
|
543
|
+
if (!id || id.name !== name)
|
|
544
|
+
continue;
|
|
545
|
+
const init = declarator.init;
|
|
546
|
+
if (!init)
|
|
547
|
+
return null;
|
|
548
|
+
if (init.type === "Identifier")
|
|
549
|
+
return resolveToGlobal(init.name, scopeTracker, depth + 1);
|
|
550
|
+
if (init.type === "MemberExpression" && !init.computed && init.object?.type === "Identifier" && init.property?.type === "Identifier") {
|
|
551
|
+
const objGlobal = resolveToGlobal(init.object.name, scopeTracker, depth + 1);
|
|
552
|
+
if (!objGlobal)
|
|
553
|
+
return null;
|
|
554
|
+
if (WINDOW_GLOBALS.has(objGlobal) || objGlobal === "document")
|
|
555
|
+
return init.property.name;
|
|
556
|
+
return null;
|
|
557
|
+
}
|
|
558
|
+
return null;
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
return null;
|
|
562
|
+
}
|
|
563
|
+
function resolveCalleeTarget(callee, scopeTracker) {
|
|
564
|
+
if (callee?.type !== "MemberExpression")
|
|
565
|
+
return null;
|
|
566
|
+
const propName = callee.computed ? callee.property?.type === "Literal" && typeof callee.property.value === "string" ? callee.property.value : null : callee.property?.name;
|
|
567
|
+
if (!propName)
|
|
568
|
+
return null;
|
|
569
|
+
const obj = callee.object;
|
|
570
|
+
if (!obj || obj.type !== "Identifier")
|
|
571
|
+
return null;
|
|
572
|
+
const resolved = resolveToGlobal(obj.name, scopeTracker);
|
|
573
|
+
if (!resolved)
|
|
574
|
+
return null;
|
|
575
|
+
if (propName === "fetch" && WINDOW_GLOBALS.has(resolved))
|
|
576
|
+
return "fetch";
|
|
577
|
+
if (propName === "sendBeacon" && (NAVIGATOR_GLOBALS.has(resolved) || WINDOW_GLOBALS.has(resolved)))
|
|
578
|
+
return "sendBeacon";
|
|
579
|
+
if (propName === "sendBeacon" && resolved === "navigator")
|
|
580
|
+
return "sendBeacon";
|
|
581
|
+
if (propName === "XMLHttpRequest" && WINDOW_GLOBALS.has(resolved))
|
|
582
|
+
return "XMLHttpRequest";
|
|
583
|
+
if (propName === "Image" && WINDOW_GLOBALS.has(resolved))
|
|
584
|
+
return "Image";
|
|
585
|
+
return null;
|
|
586
|
+
}
|
|
587
|
+
function rewriteScriptUrlsAST(content, filename, rewrites) {
|
|
588
|
+
const s = new MagicString(content);
|
|
589
|
+
function needsLeadingSpace(start) {
|
|
590
|
+
const prev = content[start - 1];
|
|
591
|
+
return prev && WORD_OR_DOLLAR_RE.test(prev) ? " " : "";
|
|
592
|
+
}
|
|
593
|
+
const scopeTracker = new ScopeTracker({ preserveExitedScopes: true });
|
|
594
|
+
const { program } = parseAndWalk(content, filename, { scopeTracker });
|
|
595
|
+
scopeTracker.freeze();
|
|
596
|
+
walk(program, {
|
|
597
|
+
scopeTracker,
|
|
598
|
+
enter(node, parent, ctx) {
|
|
599
|
+
if (node.type === "Literal" && typeof node.value === "string") {
|
|
600
|
+
const value = node.value;
|
|
601
|
+
const rewritten = matchAndRewrite(value, rewrites);
|
|
602
|
+
if (rewritten === null)
|
|
603
|
+
return;
|
|
604
|
+
const quote = content[node.start];
|
|
605
|
+
if (isPropertyKeyAST(parent, ctx)) {
|
|
606
|
+
s.overwrite(node.start, node.end, quote + rewritten + quote);
|
|
607
|
+
} else {
|
|
608
|
+
s.overwrite(node.start, node.end, `${needsLeadingSpace(node.start)}self.location.origin+${quote}${rewritten}${quote}`);
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
if (node.type === "TemplateLiteral" && node.expressions?.length === 0) {
|
|
612
|
+
const quasis = node.quasis;
|
|
613
|
+
if (quasis?.length === 1) {
|
|
614
|
+
const value = quasis[0].value?.cooked ?? quasis[0].value?.raw;
|
|
615
|
+
if (typeof value !== "string")
|
|
616
|
+
return;
|
|
617
|
+
const rewritten = matchAndRewrite(value, rewrites);
|
|
618
|
+
if (rewritten === null)
|
|
619
|
+
return;
|
|
620
|
+
if (isPropertyKeyAST(parent, ctx)) {
|
|
621
|
+
s.overwrite(node.start, node.end, `\`${rewritten}\``);
|
|
622
|
+
} else {
|
|
623
|
+
s.overwrite(node.start, node.end, `${needsLeadingSpace(node.start)}self.location.origin+\`${rewritten}\``);
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
if (node.type === "CallExpression") {
|
|
628
|
+
const callee = node.callee;
|
|
629
|
+
if (callee?.type === "Identifier" && callee.name === "fetch") {
|
|
630
|
+
if (!scopeTracker.getDeclaration("fetch"))
|
|
631
|
+
s.overwrite(callee.start, callee.end, "__nuxtScripts.fetch");
|
|
632
|
+
return;
|
|
633
|
+
}
|
|
634
|
+
const target = resolveCalleeTarget(callee, scopeTracker);
|
|
635
|
+
if (target === "fetch" || target === "sendBeacon") {
|
|
636
|
+
s.overwrite(callee.start, callee.end, `__nuxtScripts.${target}`);
|
|
637
|
+
return;
|
|
638
|
+
}
|
|
639
|
+
if (callee?.type === "MemberExpression" && !callee.computed && callee.property?.name === "sendBeacon" && callee.object?.type === "Identifier") {
|
|
640
|
+
const resolved = resolveToGlobal(callee.object.name, scopeTracker);
|
|
641
|
+
if (resolved === null) {
|
|
642
|
+
s.overwrite(callee.start, callee.end, "__nuxtScripts.sendBeacon");
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
if (node.type === "NewExpression") {
|
|
647
|
+
const callee = node.callee;
|
|
648
|
+
if (callee?.type === "Identifier" && callee.name === "XMLHttpRequest") {
|
|
649
|
+
if (!scopeTracker.getDeclaration("XMLHttpRequest"))
|
|
650
|
+
s.overwrite(callee.start, callee.end, "__nuxtScripts.XMLHttpRequest");
|
|
651
|
+
return;
|
|
652
|
+
}
|
|
653
|
+
if (callee?.type === "Identifier" && callee.name === "Image") {
|
|
654
|
+
if (!scopeTracker.getDeclaration("Image"))
|
|
655
|
+
s.overwrite(callee.start, callee.end, "__nuxtScripts.Image");
|
|
656
|
+
return;
|
|
657
|
+
}
|
|
658
|
+
const target = resolveCalleeTarget(callee, scopeTracker);
|
|
659
|
+
if (target === "XMLHttpRequest" || target === "Image") {
|
|
660
|
+
s.overwrite(callee.start, callee.end, `__nuxtScripts.${target}`);
|
|
661
|
+
return;
|
|
662
|
+
}
|
|
663
|
+
if (callee?.type === "MemberExpression" && callee.object?.type === "Identifier") {
|
|
664
|
+
const propName = callee.computed ? callee.property?.type === "Literal" && typeof callee.property.value === "string" ? callee.property.value : null : callee.property?.name;
|
|
665
|
+
if (propName === "XMLHttpRequest" || propName === "Image") {
|
|
666
|
+
const resolved = resolveToGlobal(callee.object.name, scopeTracker);
|
|
667
|
+
if (resolved === null) {
|
|
668
|
+
s.overwrite(callee.start, callee.end, `__nuxtScripts.${propName}`);
|
|
669
|
+
}
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
}
|
|
674
|
+
});
|
|
675
|
+
let output = s.toString();
|
|
676
|
+
const gaRewrite = rewrites.find((r) => r.from.includes("google-analytics.com/g/collect"));
|
|
677
|
+
if (gaRewrite) {
|
|
678
|
+
output = output.replace(
|
|
679
|
+
GA_COLLECT_RE,
|
|
680
|
+
(_, prevChar) => `${prevChar ? `${prevChar} ` : ""}self.location.origin+"${gaRewrite.to}"`
|
|
681
|
+
);
|
|
682
|
+
output = output.replace(
|
|
683
|
+
GA_ANALYTICS_COLLECT_RE,
|
|
684
|
+
(_, prevChar) => `${prevChar ? `${prevChar} ` : ""}self.location.origin+"${gaRewrite.to}"`
|
|
685
|
+
);
|
|
686
|
+
}
|
|
687
|
+
if (rewrites.some((r) => r.from === "cdn.usefathom.com")) {
|
|
688
|
+
output = output.replace(
|
|
689
|
+
FATHOM_SELF_HOSTED_RE,
|
|
690
|
+
'.src.indexOf("cdn.usefathom.com")<-1'
|
|
691
|
+
);
|
|
692
|
+
}
|
|
693
|
+
return output;
|
|
326
694
|
}
|
|
327
695
|
|
|
328
696
|
const SEVEN_DAYS_IN_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
697
|
+
const PROTOCOL_RELATIVE_RE = /^\/\//;
|
|
698
|
+
const VUE_RE = /\.vue/;
|
|
699
|
+
const JS_RE = /\.[cm]?[jt]sx?$/;
|
|
700
|
+
const TEST_RE = /\.(?:test|spec)\./;
|
|
701
|
+
const UPPERCASE_RE = /^[A-Z]$/;
|
|
702
|
+
const USE_SCRIPT_RE = /^useScript/;
|
|
329
703
|
function calculateIntegrity(content, algorithm = "sha384") {
|
|
330
704
|
const hash = createHash(algorithm).update(content).digest("base64");
|
|
331
705
|
return `${algorithm}-${hash}`;
|
|
@@ -340,12 +714,10 @@ async function isCacheExpired(storage, filename, cacheMaxAge = SEVEN_DAYS_IN_MS)
|
|
|
340
714
|
}
|
|
341
715
|
function normalizeScriptData(src, assetsBaseURL = "/_scripts") {
|
|
342
716
|
if (hasProtocol(src, { acceptRelative: true })) {
|
|
343
|
-
src = src.replace(
|
|
717
|
+
src = src.replace(PROTOCOL_RELATIVE_RE, "https://");
|
|
344
718
|
const url = parseURL(src);
|
|
345
|
-
const
|
|
346
|
-
|
|
347
|
-
// force an extension
|
|
348
|
-
].filter(Boolean).join("-");
|
|
719
|
+
const h = hash(url);
|
|
720
|
+
const file = `${h.startsWith("-") ? `_${h.slice(1)}` : h}.js`;
|
|
349
721
|
const nuxt = tryUseNuxt();
|
|
350
722
|
const cdnURL = nuxt?.options.runtimeConfig?.app?.cdnURL || nuxt?.options.app?.cdnURL || "";
|
|
351
723
|
const baseURL = cdnURL || nuxt?.options.app.baseURL || "";
|
|
@@ -392,7 +764,7 @@ async function downloadScript(opts, renderedScript, fetchOptions, cacheMaxAge) {
|
|
|
392
764
|
await storage.setItemRaw(`bundle:${filename}`, res);
|
|
393
765
|
if (proxyRewrites?.length && res) {
|
|
394
766
|
const content = res.toString("utf-8");
|
|
395
|
-
const rewritten =
|
|
767
|
+
const rewritten = rewriteScriptUrlsAST(content, filename || "script.js", proxyRewrites);
|
|
396
768
|
res = Buffer.from(rewritten, "utf-8");
|
|
397
769
|
logger.debug(`Rewrote ${proxyRewrites.length} URL patterns in ${filename}`);
|
|
398
770
|
}
|
|
@@ -449,8 +821,8 @@ function NuxtScriptBundleTransformer(options = {
|
|
|
449
821
|
transform: {
|
|
450
822
|
filter: {
|
|
451
823
|
id: {
|
|
452
|
-
include: [
|
|
453
|
-
exclude: [
|
|
824
|
+
include: [VUE_RE, JS_RE],
|
|
825
|
+
exclude: [TEST_RE]
|
|
454
826
|
}
|
|
455
827
|
},
|
|
456
828
|
async handler(code, id) {
|
|
@@ -460,11 +832,11 @@ function NuxtScriptBundleTransformer(options = {
|
|
|
460
832
|
return;
|
|
461
833
|
const s = new MagicString(code);
|
|
462
834
|
const deferredOps = [];
|
|
463
|
-
parseAndWalk(code, id,
|
|
835
|
+
parseAndWalk(code, id, (_node) => {
|
|
464
836
|
const calleeName = _node.callee?.name;
|
|
465
837
|
if (!calleeName)
|
|
466
838
|
return;
|
|
467
|
-
const isValidCallee = calleeName === "useScript" || calleeName?.startsWith("useScript") &&
|
|
839
|
+
const isValidCallee = calleeName === "useScript" || calleeName?.startsWith("useScript") && UPPERCASE_RE.test(calleeName?.charAt(9)) && !calleeName.startsWith("useScriptTrigger") && !calleeName.startsWith("useScriptEvent");
|
|
468
840
|
if (_node.type === "CallExpression" && _node.callee.type === "Identifier" && isValidCallee) {
|
|
469
841
|
const fnName = _node.callee?.name;
|
|
470
842
|
const node = _node;
|
|
@@ -472,7 +844,7 @@ function NuxtScriptBundleTransformer(options = {
|
|
|
472
844
|
let src;
|
|
473
845
|
let registryKey;
|
|
474
846
|
if (fnName !== "useScript") {
|
|
475
|
-
const baseName = fnName.replace(
|
|
847
|
+
const baseName = fnName.replace(USE_SCRIPT_RE, "");
|
|
476
848
|
registryKey = baseName.length > 0 ? baseName.charAt(0).toLowerCase() + baseName.slice(1) : void 0;
|
|
477
849
|
}
|
|
478
850
|
if (fnName === "useScript") {
|
|
@@ -652,7 +1024,7 @@ function NuxtScriptBundleTransformer(options = {
|
|
|
652
1024
|
s.appendRight(node.arguments[0].start + 1, ` scriptInput: { src: '${url}'${integrityProps} }, `);
|
|
653
1025
|
}
|
|
654
1026
|
} else {
|
|
655
|
-
s.
|
|
1027
|
+
s.overwrite(node.callee.end, node.end, `({ scriptInput: { src: '${url}'${integrityProps} } })`);
|
|
656
1028
|
}
|
|
657
1029
|
}
|
|
658
1030
|
});
|
|
@@ -676,101 +1048,7 @@ function NuxtScriptBundleTransformer(options = {
|
|
|
676
1048
|
});
|
|
677
1049
|
}
|
|
678
1050
|
|
|
679
|
-
const
|
|
680
|
-
async function promptToInstall(name, installCommand, options) {
|
|
681
|
-
if (await resolvePackageJSON(name).catch(() => null))
|
|
682
|
-
return true;
|
|
683
|
-
logger$1.info(`Package ${name} is missing`);
|
|
684
|
-
if (isCI)
|
|
685
|
-
return false;
|
|
686
|
-
if (options.prompt === true || options.prompt !== false && !isStackblitz) {
|
|
687
|
-
const confirm = await logger$1.prompt(`Do you want to install ${name} package?`, {
|
|
688
|
-
type: "confirm",
|
|
689
|
-
name: "confirm",
|
|
690
|
-
initial: true
|
|
691
|
-
});
|
|
692
|
-
if (!confirm)
|
|
693
|
-
return false;
|
|
694
|
-
}
|
|
695
|
-
logger$1.info(`Installing ${name}...`);
|
|
696
|
-
try {
|
|
697
|
-
await installCommand();
|
|
698
|
-
logger$1.success(`Installed ${name}`);
|
|
699
|
-
return true;
|
|
700
|
-
} catch (err) {
|
|
701
|
-
logger$1.error(err);
|
|
702
|
-
return false;
|
|
703
|
-
}
|
|
704
|
-
}
|
|
705
|
-
const installPrompts = /* @__PURE__ */ new Set();
|
|
706
|
-
function installNuxtModule(name, options) {
|
|
707
|
-
if (installPrompts.has(name))
|
|
708
|
-
return;
|
|
709
|
-
installPrompts.add(name);
|
|
710
|
-
const nuxt = tryUseNuxt();
|
|
711
|
-
if (!nuxt)
|
|
712
|
-
return;
|
|
713
|
-
return promptToInstall(name, async () => {
|
|
714
|
-
const { runCommand } = await import(String("nuxi"));
|
|
715
|
-
await runCommand("module", ["add", name, "--cwd", nuxt.options.rootDir]);
|
|
716
|
-
}, { rootDir: nuxt.options.rootDir, searchPaths: nuxt.options.modulesDir, ...options });
|
|
717
|
-
}
|
|
718
|
-
|
|
719
|
-
function NuxtScriptsCheckScripts() {
|
|
720
|
-
return createUnplugin(() => {
|
|
721
|
-
return {
|
|
722
|
-
name: "nuxt-scripts:check-scripts",
|
|
723
|
-
transform: {
|
|
724
|
-
filter: {
|
|
725
|
-
id: /\.vue/
|
|
726
|
-
},
|
|
727
|
-
handler(code, id) {
|
|
728
|
-
if (!isVue(id, { type: ["script"] }))
|
|
729
|
-
return;
|
|
730
|
-
if (!code.includes("useScript"))
|
|
731
|
-
return;
|
|
732
|
-
let nameNode;
|
|
733
|
-
let errorNode;
|
|
734
|
-
parseAndWalk(code, id, function(_node) {
|
|
735
|
-
if (_node.type === "VariableDeclaration" && _node.declarations?.[0]?.id?.type === "ObjectPattern") {
|
|
736
|
-
const objPattern = _node.declarations[0]?.id;
|
|
737
|
-
for (const property of objPattern.properties) {
|
|
738
|
-
if (property.type === "Property" && property.key.type === "Identifier" && property.key.name === "$script" && property.value.type === "Identifier") {
|
|
739
|
-
nameNode = _node;
|
|
740
|
-
}
|
|
741
|
-
}
|
|
742
|
-
}
|
|
743
|
-
if (nameNode) {
|
|
744
|
-
let sequence = _node.type === "SequenceExpression" ? _node : null;
|
|
745
|
-
let assignmentExpression;
|
|
746
|
-
if (_node.type === "VariableDeclaration") {
|
|
747
|
-
if (_node.declarations[0]?.init?.type === "SequenceExpression") {
|
|
748
|
-
sequence = _node.declarations[0]?.init;
|
|
749
|
-
assignmentExpression = _node.declarations[0]?.init?.expressions?.[0];
|
|
750
|
-
}
|
|
751
|
-
}
|
|
752
|
-
if (sequence && !assignmentExpression) {
|
|
753
|
-
assignmentExpression = sequence.expressions[0]?.type === "AssignmentExpression" ? sequence.expressions[0] : null;
|
|
754
|
-
}
|
|
755
|
-
if (assignmentExpression) {
|
|
756
|
-
const right = assignmentExpression?.right;
|
|
757
|
-
if (right.callee?.name === "_withAsyncContext") {
|
|
758
|
-
if (right.arguments[0]?.body?.name === "$script" || right.arguments[0]?.body?.callee?.object?.name === "$script") {
|
|
759
|
-
errorNode = nameNode;
|
|
760
|
-
}
|
|
761
|
-
}
|
|
762
|
-
}
|
|
763
|
-
}
|
|
764
|
-
});
|
|
765
|
-
if (errorNode) {
|
|
766
|
-
return this.error(new Error("You can't use a top-level await on $script as it will never resolve."));
|
|
767
|
-
}
|
|
768
|
-
}
|
|
769
|
-
}
|
|
770
|
-
};
|
|
771
|
-
});
|
|
772
|
-
}
|
|
773
|
-
|
|
1051
|
+
const TRIGGER_PLACEHOLDER_RE = /"__TRIGGER_PLACEHOLDER__"/g;
|
|
774
1052
|
function registerTypeTemplates({ nuxt, config, newScripts }) {
|
|
775
1053
|
addTypeTemplate({
|
|
776
1054
|
filename: "types/nuxt-scripts-augments.d.ts",
|
|
@@ -782,7 +1060,7 @@ function registerTypeTemplates({ nuxt, config, newScripts }) {
|
|
|
782
1060
|
let augments = `// Generated by @nuxt/scripts
|
|
783
1061
|
declare module '#app' {
|
|
784
1062
|
interface NuxtApp {
|
|
785
|
-
$scripts: Record<${[...Object.keys(config.globals || {}), ...Object.keys(config.registry || {})].map((k) => `'${k}'`)
|
|
1063
|
+
$scripts: Record<${[...[...Object.keys(config.globals || {}), ...Object.keys(config.registry || {})].map((k) => `'${k}'`), ...["string"]].join(" | ")}, import('#nuxt-scripts/types').UseScriptContext<any> | undefined>
|
|
786
1064
|
_scripts: Record<string, import('#nuxt-scripts/types').NuxtDevToolsScriptInstance>
|
|
787
1065
|
}
|
|
788
1066
|
interface RuntimeNuxtHooks {
|
|
@@ -863,7 +1141,7 @@ function templatePlugin(config, registry) {
|
|
|
863
1141
|
let needsInteractionImport = false;
|
|
864
1142
|
let needsServiceWorkerImport = false;
|
|
865
1143
|
for (const [k, c] of Object.entries(config.registry || {})) {
|
|
866
|
-
const importDefinition = registry.find((i) => i.
|
|
1144
|
+
const importDefinition = registry.find((i) => i.import.name.toLowerCase() === `usescript${k.toLowerCase()}`);
|
|
867
1145
|
if (importDefinition) {
|
|
868
1146
|
resolvedRegistryKeys.push(k);
|
|
869
1147
|
imports.unshift(`import { ${importDefinition.import.name} } from '${importDefinition.import.from}'`);
|
|
@@ -875,12 +1153,15 @@ function templatePlugin(config, registry) {
|
|
|
875
1153
|
const triggerResolved = resolveTriggerForTemplate(scriptOptions?.trigger);
|
|
876
1154
|
if (triggerResolved) {
|
|
877
1155
|
scriptOptions.trigger = "__TRIGGER_PLACEHOLDER__";
|
|
878
|
-
if (triggerResolved.includes("useScriptTriggerIdleTimeout"))
|
|
879
|
-
|
|
880
|
-
if (triggerResolved.includes("
|
|
1156
|
+
if (triggerResolved.includes("useScriptTriggerIdleTimeout"))
|
|
1157
|
+
needsIdleTimeoutImport = true;
|
|
1158
|
+
if (triggerResolved.includes("useScriptTriggerInteraction"))
|
|
1159
|
+
needsInteractionImport = true;
|
|
1160
|
+
if (triggerResolved.includes("useScriptTriggerServiceWorker"))
|
|
1161
|
+
needsServiceWorkerImport = true;
|
|
881
1162
|
}
|
|
882
1163
|
const args = { ...input, scriptOptions };
|
|
883
|
-
const argsJson = triggerResolved ? JSON.stringify(args).replace(
|
|
1164
|
+
const argsJson = triggerResolved ? JSON.stringify(args).replace(TRIGGER_PLACEHOLDER_RE, triggerResolved) : JSON.stringify(args);
|
|
884
1165
|
inits.push(`const ${k} = ${importDefinition.import.name}(${argsJson})`);
|
|
885
1166
|
} else {
|
|
886
1167
|
const args = (typeof c !== "object" ? {} : c) || {};
|
|
@@ -895,11 +1176,14 @@ function templatePlugin(config, registry) {
|
|
|
895
1176
|
const options = c[1];
|
|
896
1177
|
const triggerResolved = resolveTriggerForTemplate(options?.trigger);
|
|
897
1178
|
if (triggerResolved) {
|
|
898
|
-
if (triggerResolved.includes("useScriptTriggerIdleTimeout"))
|
|
899
|
-
|
|
900
|
-
if (triggerResolved.includes("
|
|
1179
|
+
if (triggerResolved.includes("useScriptTriggerIdleTimeout"))
|
|
1180
|
+
needsIdleTimeoutImport = true;
|
|
1181
|
+
if (triggerResolved.includes("useScriptTriggerInteraction"))
|
|
1182
|
+
needsInteractionImport = true;
|
|
1183
|
+
if (triggerResolved.includes("useScriptTriggerServiceWorker"))
|
|
1184
|
+
needsServiceWorkerImport = true;
|
|
901
1185
|
const resolvedOptions = { ...options, trigger: "__TRIGGER_PLACEHOLDER__" };
|
|
902
|
-
const optionsJson = JSON.stringify(resolvedOptions).replace(
|
|
1186
|
+
const optionsJson = JSON.stringify(resolvedOptions).replace(TRIGGER_PLACEHOLDER_RE, triggerResolved);
|
|
903
1187
|
inits.push(`const ${k} = useScript(${JSON.stringify({ key: k, ...typeof c[0] === "string" ? { src: c[0] } : c[0] })}, { ...${optionsJson}, use: () => ({ ${k}: window.${k} }) })`);
|
|
904
1188
|
} else {
|
|
905
1189
|
inits.push(`const ${k} = useScript(${JSON.stringify({ key: k, ...typeof c[0] === "string" ? { src: c[0] } : c[0] })}, { ...${JSON.stringify(c[1])}, use: () => ({ ${k}: window.${k} }) })`);
|
|
@@ -907,11 +1191,14 @@ function templatePlugin(config, registry) {
|
|
|
907
1191
|
} else if (typeof c === "object" && c !== null) {
|
|
908
1192
|
const triggerResolved = resolveTriggerForTemplate(c.trigger);
|
|
909
1193
|
if (triggerResolved) {
|
|
910
|
-
if (triggerResolved.includes("useScriptTriggerIdleTimeout"))
|
|
911
|
-
|
|
912
|
-
if (triggerResolved.includes("
|
|
1194
|
+
if (triggerResolved.includes("useScriptTriggerIdleTimeout"))
|
|
1195
|
+
needsIdleTimeoutImport = true;
|
|
1196
|
+
if (triggerResolved.includes("useScriptTriggerInteraction"))
|
|
1197
|
+
needsInteractionImport = true;
|
|
1198
|
+
if (triggerResolved.includes("useScriptTriggerServiceWorker"))
|
|
1199
|
+
needsServiceWorkerImport = true;
|
|
913
1200
|
const resolvedOptions = { ...c, trigger: "__TRIGGER_PLACEHOLDER__" };
|
|
914
|
-
const argsJson = JSON.stringify({ key: k, ...resolvedOptions }).replace(
|
|
1201
|
+
const argsJson = JSON.stringify({ key: k, ...resolvedOptions }).replace(TRIGGER_PLACEHOLDER_RE, triggerResolved);
|
|
915
1202
|
inits.push(`const ${k} = useScript(${argsJson}, { use: () => ({ ${k}: window.${k} }) })`);
|
|
916
1203
|
} else {
|
|
917
1204
|
inits.push(`const ${k} = useScript(${JSON.stringify({ key: k, ...c })}, { use: () => ({ ${k}: window.${k} }) })`);
|
|
@@ -940,12 +1227,93 @@ function templatePlugin(config, registry) {
|
|
|
940
1227
|
` parallel: true,`,
|
|
941
1228
|
` setup() {`,
|
|
942
1229
|
...inits.map((i) => ` ${i}`),
|
|
943
|
-
` return { provide: {
|
|
1230
|
+
` return { provide: { scripts: { ${[...Object.keys(config.globals || {}), ...resolvedRegistryKeys].join(", ")} } } }`,
|
|
944
1231
|
` }`,
|
|
945
1232
|
`})`
|
|
946
1233
|
].join("\n");
|
|
947
1234
|
}
|
|
948
1235
|
|
|
1236
|
+
const SELF_CLOSING_SCRIPT_RE = /<((?:Script[A-Z]|script-)\w[\w-]*)\b([^>]*?)\/\s*>/g;
|
|
1237
|
+
function fixSelfClosingScriptComponents(nuxt) {
|
|
1238
|
+
function expandTags(content) {
|
|
1239
|
+
SELF_CLOSING_SCRIPT_RE.lastIndex = 0;
|
|
1240
|
+
if (!SELF_CLOSING_SCRIPT_RE.test(content))
|
|
1241
|
+
return null;
|
|
1242
|
+
SELF_CLOSING_SCRIPT_RE.lastIndex = 0;
|
|
1243
|
+
return content.replace(SELF_CLOSING_SCRIPT_RE, (_, tag, attrs) => `<${tag}${attrs.trimEnd()}></${tag}>`);
|
|
1244
|
+
}
|
|
1245
|
+
function fixFile(filePath) {
|
|
1246
|
+
if (!existsSync(filePath))
|
|
1247
|
+
return;
|
|
1248
|
+
const content = readFileSync(filePath, "utf-8");
|
|
1249
|
+
const fixed = expandTags(content);
|
|
1250
|
+
if (fixed)
|
|
1251
|
+
nuxt.vfs[filePath] = fixed;
|
|
1252
|
+
}
|
|
1253
|
+
function scanDir(dir) {
|
|
1254
|
+
if (!existsSync(dir))
|
|
1255
|
+
return;
|
|
1256
|
+
for (const entry of readdirSync(dir, { withFileTypes: true })) {
|
|
1257
|
+
const fullPath = resolve(dir, entry.name);
|
|
1258
|
+
if (entry.isDirectory())
|
|
1259
|
+
scanDir(fullPath);
|
|
1260
|
+
else if (entry.name.endsWith(".vue"))
|
|
1261
|
+
fixFile(fullPath);
|
|
1262
|
+
}
|
|
1263
|
+
}
|
|
1264
|
+
const pagesDirs = /* @__PURE__ */ new Set();
|
|
1265
|
+
for (const layer of nuxt.options._layers) {
|
|
1266
|
+
pagesDirs.add(resolve(
|
|
1267
|
+
layer.config.srcDir,
|
|
1268
|
+
layer.config.dir?.pages || "pages"
|
|
1269
|
+
));
|
|
1270
|
+
}
|
|
1271
|
+
for (const dir of pagesDirs) scanDir(dir);
|
|
1272
|
+
if (nuxt.options.dev) {
|
|
1273
|
+
nuxt.hook("builder:watch", (_event, relativePath) => {
|
|
1274
|
+
if (!relativePath.endsWith(".vue"))
|
|
1275
|
+
return;
|
|
1276
|
+
for (const layer of nuxt.options._layers) {
|
|
1277
|
+
const fullPath = resolve(layer.config.srcDir, relativePath);
|
|
1278
|
+
for (const dir of pagesDirs) {
|
|
1279
|
+
if (fullPath.startsWith(`${dir}/`)) {
|
|
1280
|
+
fixFile(fullPath);
|
|
1281
|
+
return;
|
|
1282
|
+
}
|
|
1283
|
+
}
|
|
1284
|
+
}
|
|
1285
|
+
});
|
|
1286
|
+
}
|
|
1287
|
+
}
|
|
1288
|
+
const REGISTRY_ENV_DEFAULTS = {
|
|
1289
|
+
clarity: { id: "" },
|
|
1290
|
+
cloudflareWebAnalytics: { token: "" },
|
|
1291
|
+
crisp: { id: "" },
|
|
1292
|
+
databuddyAnalytics: { clientId: "" },
|
|
1293
|
+
fathomAnalytics: { site: "" },
|
|
1294
|
+
googleAdsense: { client: "" },
|
|
1295
|
+
googleAnalytics: { id: "" },
|
|
1296
|
+
googleMaps: { apiKey: "" },
|
|
1297
|
+
googleRecaptcha: { siteKey: "" },
|
|
1298
|
+
googleSignIn: { clientId: "" },
|
|
1299
|
+
googleTagManager: { id: "" },
|
|
1300
|
+
hotjar: { id: "" },
|
|
1301
|
+
intercom: { app_id: "" },
|
|
1302
|
+
matomoAnalytics: { matomoUrl: "" },
|
|
1303
|
+
metaPixel: { id: "" },
|
|
1304
|
+
paypal: { clientId: "" },
|
|
1305
|
+
plausibleAnalytics: { domain: "" },
|
|
1306
|
+
posthog: { apiKey: "" },
|
|
1307
|
+
redditPixel: { id: "" },
|
|
1308
|
+
rybbitAnalytics: { siteId: "" },
|
|
1309
|
+
segment: { writeKey: "" },
|
|
1310
|
+
snapchatPixel: { id: "" },
|
|
1311
|
+
stripe: {},
|
|
1312
|
+
tiktokPixel: { id: "" },
|
|
1313
|
+
umamiAnalytics: { websiteId: "" },
|
|
1314
|
+
vercelAnalytics: {},
|
|
1315
|
+
xPixel: { id: "" }
|
|
1316
|
+
};
|
|
949
1317
|
const PARTYTOWN_FORWARDS = {
|
|
950
1318
|
googleAnalytics: ["dataLayer.push", "gtag"],
|
|
951
1319
|
plausible: ["plausible"],
|
|
@@ -1009,8 +1377,7 @@ const module$1 = defineNuxtModule({
|
|
|
1009
1377
|
nuxt.options.runtimeConfig["nuxt-scripts"] = {
|
|
1010
1378
|
version,
|
|
1011
1379
|
// Private proxy config with API key (server-side only)
|
|
1012
|
-
googleStaticMapsProxy: config.googleStaticMapsProxy?.enabled ? { apiKey: nuxt.options.runtimeConfig.public.scripts?.googleMaps?.apiKey } : void 0
|
|
1013
|
-
swTemplate: readFileSync(await resolvePath("./runtime/sw/proxy-sw.template.js"), "utf-8")
|
|
1380
|
+
googleStaticMapsProxy: config.googleStaticMapsProxy?.enabled ? { apiKey: nuxt.options.runtimeConfig.public.scripts?.googleMaps?.apiKey } : void 0
|
|
1014
1381
|
};
|
|
1015
1382
|
nuxt.options.runtimeConfig.public["nuxt-scripts"] = {
|
|
1016
1383
|
// expose for devtools
|
|
@@ -1021,9 +1388,26 @@ const module$1 = defineNuxtModule({
|
|
|
1021
1388
|
};
|
|
1022
1389
|
if (config.registry) {
|
|
1023
1390
|
nuxt.options.runtimeConfig.public = nuxt.options.runtimeConfig.public || {};
|
|
1391
|
+
const registryWithDefaults = {};
|
|
1392
|
+
for (const [key, value] of Object.entries(config.registry)) {
|
|
1393
|
+
if (value && REGISTRY_ENV_DEFAULTS[key]) {
|
|
1394
|
+
const envDefaults = REGISTRY_ENV_DEFAULTS[key];
|
|
1395
|
+
if (value === true || value === "mock") {
|
|
1396
|
+
registryWithDefaults[key] = { ...envDefaults };
|
|
1397
|
+
} else if (typeof value === "object" && !Array.isArray(value)) {
|
|
1398
|
+
registryWithDefaults[key] = defu(value, envDefaults);
|
|
1399
|
+
} else if (Array.isArray(value)) {
|
|
1400
|
+
registryWithDefaults[key] = defu(value[0] || {}, envDefaults);
|
|
1401
|
+
} else {
|
|
1402
|
+
registryWithDefaults[key] = value;
|
|
1403
|
+
}
|
|
1404
|
+
} else {
|
|
1405
|
+
registryWithDefaults[key] = value;
|
|
1406
|
+
}
|
|
1407
|
+
}
|
|
1024
1408
|
nuxt.options.runtimeConfig.public.scripts = defu(
|
|
1025
1409
|
nuxt.options.runtimeConfig.public.scripts || {},
|
|
1026
|
-
|
|
1410
|
+
registryWithDefaults
|
|
1027
1411
|
);
|
|
1028
1412
|
}
|
|
1029
1413
|
if (config.defaultScriptOptions?.bundle !== void 0) {
|
|
@@ -1031,14 +1415,8 @@ const module$1 = defineNuxtModule({
|
|
|
1031
1415
|
"`scripts.defaultScriptOptions.bundle` is deprecated. Use `scripts.firstParty: true` instead. First-party mode is now enabled by default."
|
|
1032
1416
|
);
|
|
1033
1417
|
}
|
|
1034
|
-
const
|
|
1035
|
-
const
|
|
1036
|
-
const isStaticPreset = staticPresets.includes(preset);
|
|
1037
|
-
const firstPartyEnabled = !!config.firstParty;
|
|
1038
|
-
const firstPartyPrefix = typeof config.firstParty === "object" ? config.firstParty.prefix : void 0;
|
|
1039
|
-
const firstPartyCollectPrefix = typeof config.firstParty === "object" ? config.firstParty.collectPrefix || "/_proxy" : "/_proxy";
|
|
1040
|
-
const firstPartyPrivacy = typeof config.firstParty === "object" ? config.firstParty.privacy ?? "anonymize" : "anonymize";
|
|
1041
|
-
const assetsPrefix = firstPartyPrefix || config.assets?.prefix || "/_scripts";
|
|
1418
|
+
const firstParty = resolveFirstPartyConfig(config);
|
|
1419
|
+
const assetsPrefix = firstParty.assetsPrefix;
|
|
1042
1420
|
if (config.partytown?.length) {
|
|
1043
1421
|
config.registry = config.registry || {};
|
|
1044
1422
|
const requiredForwards = [];
|
|
@@ -1090,109 +1468,17 @@ const module$1 = defineNuxtModule({
|
|
|
1090
1468
|
path: await resolvePath("./runtime/components"),
|
|
1091
1469
|
pathPrefix: false
|
|
1092
1470
|
});
|
|
1471
|
+
fixSelfClosingScriptComponents(nuxt);
|
|
1093
1472
|
addTemplate({
|
|
1094
1473
|
filename: "nuxt-scripts-trigger-resolver.mjs",
|
|
1095
1474
|
getContents() {
|
|
1096
1475
|
return templateTriggerResolver(config.defaultScriptOptions);
|
|
1097
1476
|
}
|
|
1098
1477
|
});
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
if (
|
|
1102
|
-
|
|
1103
|
-
const swRules = getSWInterceptRules(firstPartyCollectPrefix);
|
|
1104
|
-
addServerHandler({
|
|
1105
|
-
route: swPath,
|
|
1106
|
-
handler: swHandlerPath
|
|
1107
|
-
});
|
|
1108
|
-
addPluginTemplate({
|
|
1109
|
-
filename: "nuxt-scripts-sw-register.client.mjs",
|
|
1110
|
-
getContents() {
|
|
1111
|
-
return `import { defineNuxtPlugin } from 'nuxt/app'
|
|
1112
|
-
|
|
1113
|
-
export default defineNuxtPlugin({
|
|
1114
|
-
name: 'nuxt-scripts:sw-register',
|
|
1115
|
-
enforce: 'pre',
|
|
1116
|
-
async setup() {
|
|
1117
|
-
if (!('serviceWorker' in navigator)) return;
|
|
1118
|
-
|
|
1119
|
-
try {
|
|
1120
|
-
const reg = await navigator.serviceWorker.register('${swPath}', { scope: '/' });
|
|
1121
|
-
|
|
1122
|
-
// Wait for SW to be active and controlling this page
|
|
1123
|
-
if (!navigator.serviceWorker.controller) {
|
|
1124
|
-
await new Promise((resolve) => {
|
|
1125
|
-
const onControllerChange = () => {
|
|
1126
|
-
navigator.serviceWorker.removeEventListener('controllerchange', onControllerChange);
|
|
1127
|
-
resolve();
|
|
1128
|
-
};
|
|
1129
|
-
navigator.serviceWorker.addEventListener('controllerchange', onControllerChange);
|
|
1130
|
-
|
|
1131
|
-
// Fallback timeout
|
|
1132
|
-
setTimeout(resolve, 2000);
|
|
1133
|
-
});
|
|
1134
|
-
}
|
|
1135
|
-
} catch (err) {
|
|
1136
|
-
console.warn('[nuxt-scripts] SW registration failed:', err);
|
|
1137
|
-
}
|
|
1138
|
-
},
|
|
1139
|
-
})
|
|
1140
|
-
`;
|
|
1141
|
-
}
|
|
1142
|
-
});
|
|
1143
|
-
addPluginTemplate({
|
|
1144
|
-
filename: "nuxt-scripts-beacon-intercept.client.mjs",
|
|
1145
|
-
getContents() {
|
|
1146
|
-
const rulesJson = JSON.stringify(swRules);
|
|
1147
|
-
return `export default defineNuxtPlugin({
|
|
1148
|
-
name: 'nuxt-scripts:beacon-intercept',
|
|
1149
|
-
enforce: 'pre',
|
|
1150
|
-
setup() {
|
|
1151
|
-
if (typeof navigator === 'undefined' || !navigator.sendBeacon) return;
|
|
1152
|
-
|
|
1153
|
-
const rules = ${rulesJson};
|
|
1154
|
-
const originalBeacon = navigator.sendBeacon.bind(navigator);
|
|
1155
|
-
|
|
1156
|
-
navigator.sendBeacon = (url, data) => {
|
|
1157
|
-
try {
|
|
1158
|
-
const parsed = new URL(url, window.location.origin);
|
|
1159
|
-
|
|
1160
|
-
// Check if this URL matches any of our proxy rules
|
|
1161
|
-
for (const rule of rules) {
|
|
1162
|
-
if (parsed.hostname === rule.pattern || parsed.hostname.endsWith('.' + rule.pattern)) {
|
|
1163
|
-
// Check path prefix if specified
|
|
1164
|
-
if (rule.pathPrefix && !parsed.pathname.startsWith(rule.pathPrefix)) {
|
|
1165
|
-
continue;
|
|
1166
|
-
}
|
|
1167
|
-
|
|
1168
|
-
// Rewrite to proxy: strip pathPrefix from original, prepend target
|
|
1169
|
-
const pathWithoutPrefix = rule.pathPrefix
|
|
1170
|
-
? parsed.pathname.slice(rule.pathPrefix.length)
|
|
1171
|
-
: parsed.pathname;
|
|
1172
|
-
const separator = pathWithoutPrefix.startsWith('/') ? '' : '/';
|
|
1173
|
-
const proxyUrl = rule.target + separator + pathWithoutPrefix + parsed.search;
|
|
1174
|
-
|
|
1175
|
-
return originalBeacon(proxyUrl, data);
|
|
1176
|
-
}
|
|
1177
|
-
}
|
|
1178
|
-
} catch (e) {
|
|
1179
|
-
// URL parsing failed, pass through
|
|
1180
|
-
}
|
|
1181
|
-
|
|
1182
|
-
return originalBeacon(url, data);
|
|
1183
|
-
};
|
|
1184
|
-
},
|
|
1185
|
-
})
|
|
1186
|
-
`;
|
|
1187
|
-
}
|
|
1188
|
-
});
|
|
1189
|
-
nuxt.options.runtimeConfig.public["nuxt-scripts-sw"] = { path: swPath };
|
|
1190
|
-
const proxyHandlerPath = await resolvePath("./runtime/server/proxy-handler");
|
|
1191
|
-
logger.debug("[nuxt-scripts] Registering proxy handler:", `${firstPartyCollectPrefix}/**`, "->", proxyHandlerPath);
|
|
1192
|
-
addServerHandler({
|
|
1193
|
-
route: `${firstPartyCollectPrefix}/**`,
|
|
1194
|
-
handler: proxyHandlerPath
|
|
1195
|
-
});
|
|
1478
|
+
logger.debug("[nuxt-scripts] First-party config:", firstParty);
|
|
1479
|
+
let interceptRules = [];
|
|
1480
|
+
if (firstParty.enabled) {
|
|
1481
|
+
interceptRules = await setupFirstPartyHandlers(firstParty, resolvePath);
|
|
1196
1482
|
}
|
|
1197
1483
|
const scripts = await registry(resolvePath);
|
|
1198
1484
|
for (const script of scripts) {
|
|
@@ -1221,74 +1507,14 @@ export default defineNuxtPlugin({
|
|
|
1221
1507
|
});
|
|
1222
1508
|
}
|
|
1223
1509
|
const { renderedScript } = setupPublicAssetStrategy(config.assets);
|
|
1224
|
-
if (
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
if (proxyKey) {
|
|
1233
|
-
const proxyConfig = proxyConfigs[proxyKey];
|
|
1234
|
-
if (proxyConfig?.routes) {
|
|
1235
|
-
Object.assign(neededRoutes, proxyConfig.routes);
|
|
1236
|
-
} else {
|
|
1237
|
-
unsupportedScripts.push(key);
|
|
1238
|
-
}
|
|
1239
|
-
}
|
|
1240
|
-
}
|
|
1241
|
-
if (unsupportedScripts.length && nuxt.options.dev) {
|
|
1242
|
-
logger.warn(
|
|
1243
|
-
`First-party mode is enabled but these scripts don't support it yet: ${unsupportedScripts.join(", ")}.
|
|
1244
|
-
They will load directly from third-party servers. Request support at https://github.com/nuxt/scripts/issues`
|
|
1245
|
-
);
|
|
1246
|
-
}
|
|
1247
|
-
const flatRoutes = {};
|
|
1248
|
-
for (const [path, config2] of Object.entries(neededRoutes)) {
|
|
1249
|
-
flatRoutes[path] = config2.proxy;
|
|
1250
|
-
}
|
|
1251
|
-
const allRewrites = [];
|
|
1252
|
-
for (const key of registryKeys) {
|
|
1253
|
-
const script = registryScriptsWithImport.find((s) => s.import.name.toLowerCase() === `usescript${key.toLowerCase()}`);
|
|
1254
|
-
const proxyKey = script?.proxy !== false ? script?.proxy || key : void 0;
|
|
1255
|
-
if (proxyKey) {
|
|
1256
|
-
const proxyConfig = proxyConfigs[proxyKey];
|
|
1257
|
-
if (proxyConfig?.rewrite) {
|
|
1258
|
-
allRewrites.push(...proxyConfig.rewrite);
|
|
1259
|
-
}
|
|
1260
|
-
}
|
|
1261
|
-
}
|
|
1262
|
-
nuxt.options.runtimeConfig["nuxt-scripts-proxy"] = {
|
|
1263
|
-
routes: flatRoutes,
|
|
1264
|
-
privacy: firstPartyPrivacy,
|
|
1265
|
-
rewrites: allRewrites
|
|
1266
|
-
};
|
|
1267
|
-
if (Object.keys(neededRoutes).length) {
|
|
1268
|
-
if (nuxt.options.dev) {
|
|
1269
|
-
const routeCount = Object.keys(neededRoutes).length;
|
|
1270
|
-
const scriptsCount = registryKeys.length;
|
|
1271
|
-
logger.success(`First-party mode enabled for ${scriptsCount} script(s), ${routeCount} proxy route(s) configured (privacy: ${firstPartyPrivacy})`);
|
|
1272
|
-
if (logger.level >= 4) {
|
|
1273
|
-
for (const [path, config2] of Object.entries(neededRoutes)) {
|
|
1274
|
-
logger.debug(` ${path} \u2192 ${config2.proxy}`);
|
|
1275
|
-
}
|
|
1276
|
-
}
|
|
1277
|
-
}
|
|
1278
|
-
}
|
|
1279
|
-
if (isStaticPreset) {
|
|
1280
|
-
logger.warn(
|
|
1281
|
-
`First-party collection endpoints require a server runtime (detected: ${preset || "static"}).
|
|
1282
|
-
Scripts will be bundled, but collection requests will not be proxied.
|
|
1283
|
-
|
|
1284
|
-
Options:
|
|
1285
|
-
1. Configure platform rewrites (Vercel, Netlify, Cloudflare)
|
|
1286
|
-
2. Switch to server-rendered mode (ssr: true)
|
|
1287
|
-
3. Disable with firstParty: false
|
|
1288
|
-
|
|
1289
|
-
See: https://scripts.nuxt.com/docs/guides/first-party#static-hosting`
|
|
1290
|
-
);
|
|
1291
|
-
}
|
|
1510
|
+
if (firstParty.enabled) {
|
|
1511
|
+
finalizeFirstParty({
|
|
1512
|
+
firstParty,
|
|
1513
|
+
interceptRules,
|
|
1514
|
+
registry: config.registry,
|
|
1515
|
+
registryScriptsWithImport,
|
|
1516
|
+
nuxtOptions: nuxt.options
|
|
1517
|
+
});
|
|
1292
1518
|
}
|
|
1293
1519
|
const moduleInstallPromises = /* @__PURE__ */ new Map();
|
|
1294
1520
|
addBuildPlugin(NuxtScriptsCheckScripts(), {
|
|
@@ -1297,9 +1523,9 @@ See: https://scripts.nuxt.com/docs/guides/first-party#static-hosting`
|
|
|
1297
1523
|
addBuildPlugin(NuxtScriptBundleTransformer({
|
|
1298
1524
|
scripts: registryScriptsWithImport,
|
|
1299
1525
|
registryConfig: nuxt.options.runtimeConfig.public.scripts,
|
|
1300
|
-
defaultBundle:
|
|
1301
|
-
firstPartyEnabled,
|
|
1302
|
-
firstPartyCollectPrefix,
|
|
1526
|
+
defaultBundle: firstParty.enabled || config.defaultScriptOptions?.bundle,
|
|
1527
|
+
firstPartyEnabled: firstParty.enabled,
|
|
1528
|
+
firstPartyCollectPrefix: firstParty.collectPrefix,
|
|
1303
1529
|
moduleDetected(module) {
|
|
1304
1530
|
if (nuxt.options.dev && module !== "@nuxt/scripts" && !moduleInstallPromises.has(module) && !hasNuxtModule(module))
|
|
1305
1531
|
moduleInstallPromises.set(module, () => installNuxtModule(module));
|
|
@@ -1312,7 +1538,7 @@ See: https://scripts.nuxt.com/docs/guides/first-party#static-hosting`
|
|
|
1312
1538
|
renderedScript
|
|
1313
1539
|
}));
|
|
1314
1540
|
nuxt.hooks.hook("build:done", async () => {
|
|
1315
|
-
const initPromise =
|
|
1541
|
+
const initPromise = [...moduleInstallPromises.values()];
|
|
1316
1542
|
for (const p of initPromise)
|
|
1317
1543
|
await p?.();
|
|
1318
1544
|
});
|
|
@@ -1323,6 +1549,17 @@ See: https://scripts.nuxt.com/docs/guides/first-party#static-hosting`
|
|
|
1323
1549
|
handler: await resolvePath("./runtime/server/google-static-maps-proxy")
|
|
1324
1550
|
});
|
|
1325
1551
|
}
|
|
1552
|
+
if (config.registry?.gravatar) {
|
|
1553
|
+
const gravatarConfig = typeof config.registry.gravatar === "object" && !Array.isArray(config.registry.gravatar) ? config.registry.gravatar : {};
|
|
1554
|
+
nuxt.options.runtimeConfig.public["nuxt-scripts"] = defu(
|
|
1555
|
+
{ gravatarProxy: { cacheMaxAge: gravatarConfig.cacheMaxAge ?? 3600 } },
|
|
1556
|
+
nuxt.options.runtimeConfig.public["nuxt-scripts"]
|
|
1557
|
+
);
|
|
1558
|
+
addServerHandler({
|
|
1559
|
+
route: "/_scripts/gravatar-proxy",
|
|
1560
|
+
handler: await resolvePath("./runtime/server/gravatar-proxy")
|
|
1561
|
+
});
|
|
1562
|
+
}
|
|
1326
1563
|
addServerHandler({
|
|
1327
1564
|
route: "/api/_scripts/x-embed",
|
|
1328
1565
|
handler: await resolvePath("./runtime/server/x-embed")
|