@nuxt/scripts 1.0.0-beta.19 → 1.0.0-beta.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client/200.html +1 -1
- package/dist/client/404.html +1 -1
- package/dist/client/_nuxt/{BAII0Gd6.js → 9LJPrOyI.js} +1 -1
- package/dist/client/_nuxt/DFEfk2pB.js +162 -0
- package/dist/client/_nuxt/{BFIM6xmj.js → DMlY-BNa.js} +1 -1
- package/dist/client/_nuxt/{XsmoCkZQ.js → __ZZTkMj.js} +1 -1
- package/dist/client/_nuxt/builds/latest.json +1 -1
- package/dist/client/_nuxt/builds/meta/8212d4fa-7985-421b-815a-03a886e667d4.json +1 -0
- package/dist/client/_nuxt/entry.CACgbLJl.css +1 -0
- package/dist/client/_nuxt/error-404.CHeaW3dp.css +1 -0
- package/dist/client/_nuxt/error-500.DvOvWme_.css +1 -0
- package/dist/client/index.html +1 -1
- package/dist/module.d.mts +7 -5
- package/dist/module.d.ts +7 -5
- package/dist/module.json +1 -1
- package/dist/module.mjs +389 -197
- package/dist/registry.mjs +5 -2
- package/dist/runtime/components/GoogleMaps/ScriptGoogleMaps.vue +1 -1
- package/dist/runtime/components/ScriptYouTubePlayer.vue +2 -1
- package/dist/runtime/registry/clarity.d.ts +8 -8
- package/dist/runtime/registry/crisp.d.ts +7 -7
- package/dist/runtime/registry/databuddy-analytics.js +18 -0
- package/dist/runtime/registry/fathom-analytics.d.ts +4 -3
- package/dist/runtime/registry/fathom-analytics.js +0 -1
- package/dist/runtime/registry/google-analytics.d.ts +1 -1
- package/dist/runtime/registry/google-recaptcha.js +1 -1
- package/dist/runtime/registry/google-tag-manager.js +1 -1
- package/dist/runtime/registry/hotjar.d.ts +1 -1
- package/dist/runtime/registry/instagram-embed.js +2 -1
- package/dist/runtime/registry/intercom.d.ts +1 -1
- package/dist/runtime/registry/meta-pixel.d.ts +1 -1
- package/dist/runtime/registry/reddit-pixel.d.ts +2 -1
- package/dist/runtime/registry/rybbit-analytics.js +1 -1
- package/dist/runtime/registry/schemas.d.ts +6 -0
- package/dist/runtime/registry/schemas.js +7 -1
- package/dist/runtime/registry/snapchat-pixel.d.ts +1 -1
- package/dist/runtime/registry/tiktok-pixel.d.ts +1 -1
- package/dist/runtime/registry/x-pixel.d.ts +1 -1
- package/dist/runtime/server/gravatar-proxy.js +1 -1
- package/dist/runtime/server/instagram-embed-asset.js +2 -1
- package/dist/runtime/server/instagram-embed-image.js +2 -1
- package/dist/runtime/server/instagram-embed.js +21 -12
- package/dist/runtime/server/proxy-handler.js +37 -27
- package/dist/runtime/server/utils/privacy.js +14 -7
- package/dist/runtime/server/x-embed.js +3 -2
- package/dist/runtime/utils.js +7 -3
- package/dist/shared/{scripts.Bg4pl9Yo.mjs → scripts.Crpn87WB.mjs} +15 -7
- package/dist/stats.mjs +7 -4
- package/dist/types-source.mjs +29 -18
- package/package.json +14 -14
- package/dist/client/_nuxt/8nZpL1GZ.js +0 -162
- package/dist/client/_nuxt/builds/meta/4f48c83d-e40d-436a-afd0-3b8e6ac6f303.json +0 -1
- package/dist/client/_nuxt/entry.D45OuV0w.css +0 -1
- package/dist/client/_nuxt/error-404.Cqp3ffuH.css +0 -1
- package/dist/client/_nuxt/error-500.B9hH8BAi.css +0 -1
package/dist/module.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { existsSync, readdirSync, readFileSync } from 'node:fs';
|
|
2
|
-
import { useNuxt, addDevServerHandler, extendRouteRules, tryUseNuxt, extendViteConfig, logger as logger$1,
|
|
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
4
|
import { join, resolve, relative } from 'pathe';
|
|
5
5
|
import { resolvePackageJSON, readPackageJSON } from 'pkg-types';
|
|
@@ -10,7 +10,7 @@ import { createStorage } from 'unstorage';
|
|
|
10
10
|
import fsDriver from 'unstorage/drivers/fs-lite';
|
|
11
11
|
import { addCustomTab } from '@nuxt/devtools-kit';
|
|
12
12
|
import { isCI, provider } from 'std-env';
|
|
13
|
-
import { parseAndWalk } from 'oxc-walker';
|
|
13
|
+
import { parseAndWalk, ScopeTracker, walk, ScopeTrackerFunctionParam, ScopeTrackerVariable } from 'oxc-walker';
|
|
14
14
|
import { createUnplugin } from 'unplugin';
|
|
15
15
|
import { pathToFileURL } from 'node:url';
|
|
16
16
|
import { createHash } from 'node:crypto';
|
|
@@ -18,7 +18,7 @@ import fsp from 'node:fs/promises';
|
|
|
18
18
|
import { colors } from 'consola/utils';
|
|
19
19
|
import MagicString from 'magic-string';
|
|
20
20
|
import { hash } from 'ohash';
|
|
21
|
-
import {
|
|
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
24
|
const renderedScript = /* @__PURE__ */ new Map();
|
|
@@ -121,6 +121,212 @@ async function setupDevToolsUI(options, resolve, nuxt = useNuxt()) {
|
|
|
121
121
|
});
|
|
122
122
|
}
|
|
123
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);
|
|
208
|
+
}
|
|
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
|
+
});
|
|
222
|
+
}
|
|
223
|
+
return img;
|
|
224
|
+
}
|
|
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
|
+
`;
|
|
235
|
+
}
|
|
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 };
|
|
244
|
+
}
|
|
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;
|
|
260
|
+
}
|
|
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 neededRoutes = {};
|
|
266
|
+
const routePrivacyOverrides = {};
|
|
267
|
+
const unsupportedScripts = [];
|
|
268
|
+
for (const key of registryKeys) {
|
|
269
|
+
const script = registryScriptsWithImport.find((s) => s.import.name.toLowerCase() === `usescript${key.toLowerCase()}`);
|
|
270
|
+
const proxyKey = script?.proxy || void 0;
|
|
271
|
+
if (proxyKey) {
|
|
272
|
+
const proxyConfig = proxyConfigs[proxyKey];
|
|
273
|
+
if (proxyConfig?.routes) {
|
|
274
|
+
Object.assign(neededRoutes, proxyConfig.routes);
|
|
275
|
+
for (const routePath of Object.keys(proxyConfig.routes)) {
|
|
276
|
+
routePrivacyOverrides[routePath] = proxyConfig.privacy;
|
|
277
|
+
}
|
|
278
|
+
} else {
|
|
279
|
+
unsupportedScripts.push(key);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
if (opts.registry) {
|
|
284
|
+
autoInjectProxyEndpoints(opts.registry, nuxtOptions.runtimeConfig, firstParty.collectPrefix);
|
|
285
|
+
}
|
|
286
|
+
if (unsupportedScripts.length && nuxtOptions.dev) {
|
|
287
|
+
logger.warn(
|
|
288
|
+
`First-party mode is enabled but these scripts don't support it yet: ${unsupportedScripts.join(", ")}.
|
|
289
|
+
They will load directly from third-party servers. Request support at https://github.com/nuxt/scripts/issues`
|
|
290
|
+
);
|
|
291
|
+
}
|
|
292
|
+
interceptRules.push(...routesToInterceptRules(neededRoutes));
|
|
293
|
+
const flatRoutes = {};
|
|
294
|
+
for (const [path, config] of Object.entries(neededRoutes)) {
|
|
295
|
+
flatRoutes[path] = config.proxy;
|
|
296
|
+
}
|
|
297
|
+
nuxtOptions.runtimeConfig["nuxt-scripts-proxy"] = {
|
|
298
|
+
routes: flatRoutes,
|
|
299
|
+
privacy: firstParty.privacy,
|
|
300
|
+
routePrivacy: routePrivacyOverrides
|
|
301
|
+
};
|
|
302
|
+
if (Object.keys(neededRoutes).length && nuxtOptions.dev) {
|
|
303
|
+
const routeCount = Object.keys(neededRoutes).length;
|
|
304
|
+
const scriptsCount = registryKeys.length;
|
|
305
|
+
const privacyLabel = firstParty.privacy === void 0 ? "per-script" : typeof firstParty.privacy === "boolean" ? firstParty.privacy ? "anonymize" : "passthrough" : "custom";
|
|
306
|
+
logger.success(`First-party mode enabled for ${scriptsCount} script(s), ${routeCount} proxy route(s) configured (privacy: ${privacyLabel})`);
|
|
307
|
+
if (logger.level >= 4) {
|
|
308
|
+
for (const [path, config] of Object.entries(neededRoutes)) {
|
|
309
|
+
logger.debug(` ${path} \u2192 ${config.proxy}`);
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
const staticPresets = ["static", "github-pages", "cloudflare-pages-static"];
|
|
314
|
+
const preset = process.env.NITRO_PRESET || "";
|
|
315
|
+
if (staticPresets.includes(preset)) {
|
|
316
|
+
logger.warn(
|
|
317
|
+
`First-party collection endpoints require a server runtime (detected: ${preset || "static"}).
|
|
318
|
+
Scripts will be bundled, but collection requests will not be proxied.
|
|
319
|
+
|
|
320
|
+
Options:
|
|
321
|
+
1. Configure platform rewrites (Vercel, Netlify, Cloudflare)
|
|
322
|
+
2. Switch to server-rendered mode (ssr: true)
|
|
323
|
+
3. Disable with firstParty: false
|
|
324
|
+
|
|
325
|
+
See: https://scripts.nuxt.com/docs/guides/first-party#static-hosting`
|
|
326
|
+
);
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
|
|
124
330
|
const isStackblitz = provider === "stackblitz";
|
|
125
331
|
async function promptToInstall(name, installCommand, options) {
|
|
126
332
|
if (await resolvePackageJSON(name).catch(() => null))
|
|
@@ -161,8 +367,6 @@ function installNuxtModule(name, options) {
|
|
|
161
367
|
}, { rootDir: nuxt.options.rootDir, searchPaths: nuxt.options.modulesDir, ...options });
|
|
162
368
|
}
|
|
163
369
|
|
|
164
|
-
const logger = useLogger("@nuxt/scripts");
|
|
165
|
-
|
|
166
370
|
function isVue(id, opts = {}) {
|
|
167
371
|
const { search } = parseURL(decodeURIComponent(pathToFileURL(id).href));
|
|
168
372
|
if (id.endsWith(".vue") && !search) {
|
|
@@ -184,19 +388,20 @@ function isVue(id, opts = {}) {
|
|
|
184
388
|
}
|
|
185
389
|
return true;
|
|
186
390
|
}
|
|
187
|
-
const JS_RE = /\.(?:[cm]?j|t)sx?$/;
|
|
391
|
+
const JS_RE$1 = /\.(?:[cm]?j|t)sx?$/;
|
|
188
392
|
function isJS(id) {
|
|
189
393
|
const { pathname } = parseURL(decodeURIComponent(pathToFileURL(id).href));
|
|
190
|
-
return JS_RE.test(pathname);
|
|
394
|
+
return JS_RE$1.test(pathname);
|
|
191
395
|
}
|
|
192
396
|
|
|
397
|
+
const VUE_RE$1 = /\.vue/;
|
|
193
398
|
function NuxtScriptsCheckScripts() {
|
|
194
399
|
return createUnplugin(() => {
|
|
195
400
|
return {
|
|
196
401
|
name: "nuxt-scripts:check-scripts",
|
|
197
402
|
transform: {
|
|
198
403
|
filter: {
|
|
199
|
-
id:
|
|
404
|
+
id: VUE_RE$1
|
|
200
405
|
},
|
|
201
406
|
handler(code, id) {
|
|
202
407
|
if (!isVue(id, { type: ["script"] }))
|
|
@@ -245,6 +450,10 @@ function NuxtScriptsCheckScripts() {
|
|
|
245
450
|
});
|
|
246
451
|
}
|
|
247
452
|
|
|
453
|
+
const WORD_OR_DOLLAR_RE = /[\w$]/;
|
|
454
|
+
const GA_COLLECT_RE = /([\w$])?"https:\/\/"\+\(.*?\)\+"\.google-analytics\.com\/g\/collect"/g;
|
|
455
|
+
const GA_ANALYTICS_COLLECT_RE = /([\w$])?"https:\/\/"\+\(.*?\)\+"\.analytics\.google\.com\/g\/collect"/g;
|
|
456
|
+
const FATHOM_SELF_HOSTED_RE = /\.src\.indexOf\("cdn\.usefathom\.com"\)\s*<\s*0/;
|
|
248
457
|
function isPropertyKeyAST(parent, ctx) {
|
|
249
458
|
return parent?.type === "Property" && ctx.key === "key" || parent?.type === "SwitchCase" && ctx.key === "test";
|
|
250
459
|
}
|
|
@@ -298,51 +507,151 @@ function matchAndRewrite(value, rewrites) {
|
|
|
298
507
|
}
|
|
299
508
|
return null;
|
|
300
509
|
}
|
|
510
|
+
const WINDOW_GLOBALS = /* @__PURE__ */ new Set(["window", "self", "globalThis"]);
|
|
511
|
+
const NAVIGATOR_GLOBALS = /* @__PURE__ */ new Set(["navigator"]);
|
|
512
|
+
function resolveToGlobal(name, scopeTracker, depth = 0) {
|
|
513
|
+
if (depth > 10)
|
|
514
|
+
return null;
|
|
515
|
+
const decl = scopeTracker.getDeclaration(name);
|
|
516
|
+
if (!decl)
|
|
517
|
+
return name;
|
|
518
|
+
if (decl instanceof ScopeTrackerFunctionParam)
|
|
519
|
+
return null;
|
|
520
|
+
if (decl instanceof ScopeTrackerVariable) {
|
|
521
|
+
const declarators = decl.variableNode.declarations;
|
|
522
|
+
if (!declarators)
|
|
523
|
+
return null;
|
|
524
|
+
for (const declarator of declarators) {
|
|
525
|
+
const id = declarator.id;
|
|
526
|
+
if (!id || id.name !== name)
|
|
527
|
+
continue;
|
|
528
|
+
const init = declarator.init;
|
|
529
|
+
if (!init)
|
|
530
|
+
return null;
|
|
531
|
+
if (init.type === "Identifier")
|
|
532
|
+
return resolveToGlobal(init.name, scopeTracker, depth + 1);
|
|
533
|
+
if (init.type === "MemberExpression" && !init.computed && init.object?.type === "Identifier" && init.property?.type === "Identifier") {
|
|
534
|
+
const objGlobal = resolveToGlobal(init.object.name, scopeTracker, depth + 1);
|
|
535
|
+
if (!objGlobal)
|
|
536
|
+
return null;
|
|
537
|
+
if (WINDOW_GLOBALS.has(objGlobal) || objGlobal === "document")
|
|
538
|
+
return init.property.name;
|
|
539
|
+
return null;
|
|
540
|
+
}
|
|
541
|
+
return null;
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
return null;
|
|
545
|
+
}
|
|
546
|
+
function resolveCalleeTarget(callee, scopeTracker) {
|
|
547
|
+
if (callee?.type !== "MemberExpression")
|
|
548
|
+
return null;
|
|
549
|
+
const propName = callee.computed ? callee.property?.type === "Literal" && typeof callee.property.value === "string" ? callee.property.value : null : callee.property?.name;
|
|
550
|
+
if (!propName)
|
|
551
|
+
return null;
|
|
552
|
+
const obj = callee.object;
|
|
553
|
+
if (!obj || obj.type !== "Identifier")
|
|
554
|
+
return null;
|
|
555
|
+
const resolved = resolveToGlobal(obj.name, scopeTracker);
|
|
556
|
+
if (!resolved)
|
|
557
|
+
return null;
|
|
558
|
+
if (propName === "fetch" && WINDOW_GLOBALS.has(resolved))
|
|
559
|
+
return "fetch";
|
|
560
|
+
if (propName === "sendBeacon" && (NAVIGATOR_GLOBALS.has(resolved) || WINDOW_GLOBALS.has(resolved)))
|
|
561
|
+
return "sendBeacon";
|
|
562
|
+
if (propName === "sendBeacon" && resolved === "navigator")
|
|
563
|
+
return "sendBeacon";
|
|
564
|
+
if (propName === "XMLHttpRequest" && WINDOW_GLOBALS.has(resolved))
|
|
565
|
+
return "XMLHttpRequest";
|
|
566
|
+
if (propName === "Image" && WINDOW_GLOBALS.has(resolved))
|
|
567
|
+
return "Image";
|
|
568
|
+
return null;
|
|
569
|
+
}
|
|
301
570
|
function rewriteScriptUrlsAST(content, filename, rewrites) {
|
|
302
571
|
const s = new MagicString(content);
|
|
303
572
|
function needsLeadingSpace(start) {
|
|
304
573
|
const prev = content[start - 1];
|
|
305
|
-
return prev &&
|
|
574
|
+
return prev && WORD_OR_DOLLAR_RE.test(prev) ? " " : "";
|
|
306
575
|
}
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
s.overwrite(node.start, node.end, quote + rewritten + quote);
|
|
316
|
-
} else {
|
|
317
|
-
s.overwrite(node.start, node.end, `${needsLeadingSpace(node.start)}self.location.origin+${quote}${rewritten}${quote}`);
|
|
318
|
-
}
|
|
319
|
-
}
|
|
320
|
-
if (node.type === "TemplateLiteral" && node.expressions?.length === 0) {
|
|
321
|
-
const quasis = node.quasis;
|
|
322
|
-
if (quasis?.length === 1) {
|
|
323
|
-
const value = quasis[0].value?.cooked ?? quasis[0].value?.raw;
|
|
324
|
-
if (typeof value !== "string")
|
|
325
|
-
return;
|
|
576
|
+
const scopeTracker = new ScopeTracker({ preserveExitedScopes: true });
|
|
577
|
+
const { program } = parseAndWalk(content, filename, { scopeTracker });
|
|
578
|
+
scopeTracker.freeze();
|
|
579
|
+
walk(program, {
|
|
580
|
+
scopeTracker,
|
|
581
|
+
enter(node, parent, ctx) {
|
|
582
|
+
if (node.type === "Literal" && typeof node.value === "string") {
|
|
583
|
+
const value = node.value;
|
|
326
584
|
const rewritten = matchAndRewrite(value, rewrites);
|
|
327
585
|
if (rewritten === null)
|
|
328
586
|
return;
|
|
587
|
+
const quote = content[node.start];
|
|
329
588
|
if (isPropertyKeyAST(parent, ctx)) {
|
|
330
|
-
s.overwrite(node.start, node.end,
|
|
589
|
+
s.overwrite(node.start, node.end, quote + rewritten + quote);
|
|
331
590
|
} else {
|
|
332
|
-
s.overwrite(node.start, node.end, `${needsLeadingSpace(node.start)}self.location.origin
|
|
591
|
+
s.overwrite(node.start, node.end, `${needsLeadingSpace(node.start)}self.location.origin+${quote}${rewritten}${quote}`);
|
|
333
592
|
}
|
|
334
593
|
}
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
594
|
+
if (node.type === "TemplateLiteral" && node.expressions?.length === 0) {
|
|
595
|
+
const quasis = node.quasis;
|
|
596
|
+
if (quasis?.length === 1) {
|
|
597
|
+
const value = quasis[0].value?.cooked ?? quasis[0].value?.raw;
|
|
598
|
+
if (typeof value !== "string")
|
|
599
|
+
return;
|
|
600
|
+
const rewritten = matchAndRewrite(value, rewrites);
|
|
601
|
+
if (rewritten === null)
|
|
602
|
+
return;
|
|
603
|
+
if (isPropertyKeyAST(parent, ctx)) {
|
|
604
|
+
s.overwrite(node.start, node.end, `\`${rewritten}\``);
|
|
605
|
+
} else {
|
|
606
|
+
s.overwrite(node.start, node.end, `${needsLeadingSpace(node.start)}self.location.origin+\`${rewritten}\``);
|
|
607
|
+
}
|
|
608
|
+
}
|
|
340
609
|
}
|
|
341
|
-
if (
|
|
342
|
-
|
|
610
|
+
if (node.type === "CallExpression") {
|
|
611
|
+
const callee = node.callee;
|
|
612
|
+
if (callee?.type === "Identifier" && callee.name === "fetch") {
|
|
613
|
+
if (!scopeTracker.getDeclaration("fetch"))
|
|
614
|
+
s.overwrite(callee.start, callee.end, "__nuxtScripts.fetch");
|
|
615
|
+
return;
|
|
616
|
+
}
|
|
617
|
+
const target = resolveCalleeTarget(callee, scopeTracker);
|
|
618
|
+
if (target === "fetch" || target === "sendBeacon") {
|
|
619
|
+
s.overwrite(callee.start, callee.end, `__nuxtScripts.${target}`);
|
|
620
|
+
return;
|
|
621
|
+
}
|
|
622
|
+
if (callee?.type === "MemberExpression" && !callee.computed && callee.property?.name === "sendBeacon" && callee.object?.type === "Identifier") {
|
|
623
|
+
const resolved = resolveToGlobal(callee.object.name, scopeTracker);
|
|
624
|
+
if (resolved === null) {
|
|
625
|
+
s.overwrite(callee.start, callee.end, "__nuxtScripts.sendBeacon");
|
|
626
|
+
}
|
|
627
|
+
}
|
|
343
628
|
}
|
|
344
|
-
if (
|
|
345
|
-
|
|
629
|
+
if (node.type === "NewExpression") {
|
|
630
|
+
const callee = node.callee;
|
|
631
|
+
if (callee?.type === "Identifier" && callee.name === "XMLHttpRequest") {
|
|
632
|
+
if (!scopeTracker.getDeclaration("XMLHttpRequest"))
|
|
633
|
+
s.overwrite(callee.start, callee.end, "__nuxtScripts.XMLHttpRequest");
|
|
634
|
+
return;
|
|
635
|
+
}
|
|
636
|
+
if (callee?.type === "Identifier" && callee.name === "Image") {
|
|
637
|
+
if (!scopeTracker.getDeclaration("Image"))
|
|
638
|
+
s.overwrite(callee.start, callee.end, "__nuxtScripts.Image");
|
|
639
|
+
return;
|
|
640
|
+
}
|
|
641
|
+
const target = resolveCalleeTarget(callee, scopeTracker);
|
|
642
|
+
if (target === "XMLHttpRequest" || target === "Image") {
|
|
643
|
+
s.overwrite(callee.start, callee.end, `__nuxtScripts.${target}`);
|
|
644
|
+
return;
|
|
645
|
+
}
|
|
646
|
+
if (callee?.type === "MemberExpression" && callee.object?.type === "Identifier") {
|
|
647
|
+
const propName = callee.computed ? callee.property?.type === "Literal" && typeof callee.property.value === "string" ? callee.property.value : null : callee.property?.name;
|
|
648
|
+
if (propName === "XMLHttpRequest" || propName === "Image") {
|
|
649
|
+
const resolved = resolveToGlobal(callee.object.name, scopeTracker);
|
|
650
|
+
if (resolved === null) {
|
|
651
|
+
s.overwrite(callee.start, callee.end, `__nuxtScripts.${propName}`);
|
|
652
|
+
}
|
|
653
|
+
}
|
|
654
|
+
}
|
|
346
655
|
}
|
|
347
656
|
}
|
|
348
657
|
});
|
|
@@ -350,18 +659,30 @@ function rewriteScriptUrlsAST(content, filename, rewrites) {
|
|
|
350
659
|
const gaRewrite = rewrites.find((r) => r.from.includes("google-analytics.com/g/collect"));
|
|
351
660
|
if (gaRewrite) {
|
|
352
661
|
output = output.replace(
|
|
353
|
-
|
|
662
|
+
GA_COLLECT_RE,
|
|
354
663
|
(_, prevChar) => `${prevChar ? `${prevChar} ` : ""}self.location.origin+"${gaRewrite.to}"`
|
|
355
664
|
);
|
|
356
665
|
output = output.replace(
|
|
357
|
-
|
|
666
|
+
GA_ANALYTICS_COLLECT_RE,
|
|
358
667
|
(_, prevChar) => `${prevChar ? `${prevChar} ` : ""}self.location.origin+"${gaRewrite.to}"`
|
|
359
668
|
);
|
|
360
669
|
}
|
|
670
|
+
if (rewrites.some((r) => r.from === "cdn.usefathom.com")) {
|
|
671
|
+
output = output.replace(
|
|
672
|
+
FATHOM_SELF_HOSTED_RE,
|
|
673
|
+
'.src.indexOf("cdn.usefathom.com")<-1'
|
|
674
|
+
);
|
|
675
|
+
}
|
|
361
676
|
return output;
|
|
362
677
|
}
|
|
363
678
|
|
|
364
679
|
const SEVEN_DAYS_IN_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
680
|
+
const PROTOCOL_RELATIVE_RE = /^\/\//;
|
|
681
|
+
const VUE_RE = /\.vue/;
|
|
682
|
+
const JS_RE = /\.[cm]?[jt]sx?$/;
|
|
683
|
+
const TEST_RE = /\.(?:test|spec)\./;
|
|
684
|
+
const UPPERCASE_RE = /^[A-Z]$/;
|
|
685
|
+
const USE_SCRIPT_RE = /^useScript/;
|
|
365
686
|
function calculateIntegrity(content, algorithm = "sha384") {
|
|
366
687
|
const hash = createHash(algorithm).update(content).digest("base64");
|
|
367
688
|
return `${algorithm}-${hash}`;
|
|
@@ -376,7 +697,7 @@ async function isCacheExpired(storage, filename, cacheMaxAge = SEVEN_DAYS_IN_MS)
|
|
|
376
697
|
}
|
|
377
698
|
function normalizeScriptData(src, assetsBaseURL = "/_scripts") {
|
|
378
699
|
if (hasProtocol(src, { acceptRelative: true })) {
|
|
379
|
-
src = src.replace(
|
|
700
|
+
src = src.replace(PROTOCOL_RELATIVE_RE, "https://");
|
|
380
701
|
const url = parseURL(src);
|
|
381
702
|
const h = hash(url);
|
|
382
703
|
const file = `${h.startsWith("-") ? `_${h.slice(1)}` : h}.js`;
|
|
@@ -483,8 +804,8 @@ function NuxtScriptBundleTransformer(options = {
|
|
|
483
804
|
transform: {
|
|
484
805
|
filter: {
|
|
485
806
|
id: {
|
|
486
|
-
include: [
|
|
487
|
-
exclude: [
|
|
807
|
+
include: [VUE_RE, JS_RE],
|
|
808
|
+
exclude: [TEST_RE]
|
|
488
809
|
}
|
|
489
810
|
},
|
|
490
811
|
async handler(code, id) {
|
|
@@ -498,7 +819,7 @@ function NuxtScriptBundleTransformer(options = {
|
|
|
498
819
|
const calleeName = _node.callee?.name;
|
|
499
820
|
if (!calleeName)
|
|
500
821
|
return;
|
|
501
|
-
const isValidCallee = calleeName === "useScript" || calleeName?.startsWith("useScript") &&
|
|
822
|
+
const isValidCallee = calleeName === "useScript" || calleeName?.startsWith("useScript") && UPPERCASE_RE.test(calleeName?.charAt(9)) && !calleeName.startsWith("useScriptTrigger") && !calleeName.startsWith("useScriptEvent");
|
|
502
823
|
if (_node.type === "CallExpression" && _node.callee.type === "Identifier" && isValidCallee) {
|
|
503
824
|
const fnName = _node.callee?.name;
|
|
504
825
|
const node = _node;
|
|
@@ -506,7 +827,7 @@ function NuxtScriptBundleTransformer(options = {
|
|
|
506
827
|
let src;
|
|
507
828
|
let registryKey;
|
|
508
829
|
if (fnName !== "useScript") {
|
|
509
|
-
const baseName = fnName.replace(
|
|
830
|
+
const baseName = fnName.replace(USE_SCRIPT_RE, "");
|
|
510
831
|
registryKey = baseName.length > 0 ? baseName.charAt(0).toLowerCase() + baseName.slice(1) : void 0;
|
|
511
832
|
}
|
|
512
833
|
if (fnName === "useScript") {
|
|
@@ -710,6 +1031,7 @@ function NuxtScriptBundleTransformer(options = {
|
|
|
710
1031
|
});
|
|
711
1032
|
}
|
|
712
1033
|
|
|
1034
|
+
const TRIGGER_PLACEHOLDER_RE = /"__TRIGGER_PLACEHOLDER__"/g;
|
|
713
1035
|
function registerTypeTemplates({ nuxt, config, newScripts }) {
|
|
714
1036
|
addTypeTemplate({
|
|
715
1037
|
filename: "types/nuxt-scripts-augments.d.ts",
|
|
@@ -721,7 +1043,7 @@ function registerTypeTemplates({ nuxt, config, newScripts }) {
|
|
|
721
1043
|
let augments = `// Generated by @nuxt/scripts
|
|
722
1044
|
declare module '#app' {
|
|
723
1045
|
interface NuxtApp {
|
|
724
|
-
$scripts: Record<${[...Object.keys(config.globals || {}), ...Object.keys(config.registry || {})].map((k) => `'${k}'`)
|
|
1046
|
+
$scripts: Record<${[...[...Object.keys(config.globals || {}), ...Object.keys(config.registry || {})].map((k) => `'${k}'`), ...["string"]].join(" | ")}, import('#nuxt-scripts/types').UseScriptContext<any> | undefined>
|
|
725
1047
|
_scripts: Record<string, import('#nuxt-scripts/types').NuxtDevToolsScriptInstance>
|
|
726
1048
|
}
|
|
727
1049
|
interface RuntimeNuxtHooks {
|
|
@@ -822,7 +1144,7 @@ function templatePlugin(config, registry) {
|
|
|
822
1144
|
needsServiceWorkerImport = true;
|
|
823
1145
|
}
|
|
824
1146
|
const args = { ...input, scriptOptions };
|
|
825
|
-
const argsJson = triggerResolved ? JSON.stringify(args).replace(
|
|
1147
|
+
const argsJson = triggerResolved ? JSON.stringify(args).replace(TRIGGER_PLACEHOLDER_RE, triggerResolved) : JSON.stringify(args);
|
|
826
1148
|
inits.push(`const ${k} = ${importDefinition.import.name}(${argsJson})`);
|
|
827
1149
|
} else {
|
|
828
1150
|
const args = (typeof c !== "object" ? {} : c) || {};
|
|
@@ -844,7 +1166,7 @@ function templatePlugin(config, registry) {
|
|
|
844
1166
|
if (triggerResolved.includes("useScriptTriggerServiceWorker"))
|
|
845
1167
|
needsServiceWorkerImport = true;
|
|
846
1168
|
const resolvedOptions = { ...options, trigger: "__TRIGGER_PLACEHOLDER__" };
|
|
847
|
-
const optionsJson = JSON.stringify(resolvedOptions).replace(
|
|
1169
|
+
const optionsJson = JSON.stringify(resolvedOptions).replace(TRIGGER_PLACEHOLDER_RE, triggerResolved);
|
|
848
1170
|
inits.push(`const ${k} = useScript(${JSON.stringify({ key: k, ...typeof c[0] === "string" ? { src: c[0] } : c[0] })}, { ...${optionsJson}, use: () => ({ ${k}: window.${k} }) })`);
|
|
849
1171
|
} else {
|
|
850
1172
|
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} }) })`);
|
|
@@ -859,7 +1181,7 @@ function templatePlugin(config, registry) {
|
|
|
859
1181
|
if (triggerResolved.includes("useScriptTriggerServiceWorker"))
|
|
860
1182
|
needsServiceWorkerImport = true;
|
|
861
1183
|
const resolvedOptions = { ...c, trigger: "__TRIGGER_PLACEHOLDER__" };
|
|
862
|
-
const argsJson = JSON.stringify({ key: k, ...resolvedOptions }).replace(
|
|
1184
|
+
const argsJson = JSON.stringify({ key: k, ...resolvedOptions }).replace(TRIGGER_PLACEHOLDER_RE, triggerResolved);
|
|
863
1185
|
inits.push(`const ${k} = useScript(${argsJson}, { use: () => ({ ${k}: window.${k} }) })`);
|
|
864
1186
|
} else {
|
|
865
1187
|
inits.push(`const ${k} = useScript(${JSON.stringify({ key: k, ...c })}, { use: () => ({ ${k}: window.${k} }) })`);
|
|
@@ -1076,14 +1398,8 @@ const module$1 = defineNuxtModule({
|
|
|
1076
1398
|
"`scripts.defaultScriptOptions.bundle` is deprecated. Use `scripts.firstParty: true` instead. First-party mode is now enabled by default."
|
|
1077
1399
|
);
|
|
1078
1400
|
}
|
|
1079
|
-
const
|
|
1080
|
-
const
|
|
1081
|
-
const isStaticPreset = staticPresets.includes(preset);
|
|
1082
|
-
const firstPartyEnabled = !!config.firstParty;
|
|
1083
|
-
const firstPartyPrefix = typeof config.firstParty === "object" ? config.firstParty.prefix : void 0;
|
|
1084
|
-
const firstPartyCollectPrefix = typeof config.firstParty === "object" ? config.firstParty.collectPrefix || "/_proxy" : "/_proxy";
|
|
1085
|
-
const firstPartyPrivacy = typeof config.firstParty === "object" ? config.firstParty.privacy : void 0;
|
|
1086
|
-
const assetsPrefix = firstPartyPrefix || config.assets?.prefix || "/_scripts";
|
|
1401
|
+
const firstParty = resolveFirstPartyConfig(config);
|
|
1402
|
+
const assetsPrefix = firstParty.assetsPrefix;
|
|
1087
1403
|
if (config.partytown?.length) {
|
|
1088
1404
|
config.registry = config.registry || {};
|
|
1089
1405
|
const requiredForwards = [];
|
|
@@ -1142,52 +1458,10 @@ const module$1 = defineNuxtModule({
|
|
|
1142
1458
|
return templateTriggerResolver(config.defaultScriptOptions);
|
|
1143
1459
|
}
|
|
1144
1460
|
});
|
|
1145
|
-
logger.debug("[nuxt-scripts] First-party config:",
|
|
1461
|
+
logger.debug("[nuxt-scripts] First-party config:", firstParty);
|
|
1146
1462
|
let interceptRules = [];
|
|
1147
|
-
if (
|
|
1148
|
-
|
|
1149
|
-
filename: "nuxt-scripts-intercept.client.mjs",
|
|
1150
|
-
getContents() {
|
|
1151
|
-
const rulesJson = JSON.stringify(interceptRules);
|
|
1152
|
-
return `export default defineNuxtPlugin({
|
|
1153
|
-
name: 'nuxt-scripts:intercept',
|
|
1154
|
-
enforce: 'pre',
|
|
1155
|
-
setup() {
|
|
1156
|
-
const rules = ${rulesJson};
|
|
1157
|
-
const origBeacon = typeof navigator !== 'undefined' && navigator.sendBeacon
|
|
1158
|
-
? navigator.sendBeacon.bind(navigator)
|
|
1159
|
-
: () => false;
|
|
1160
|
-
const origFetch = globalThis.fetch.bind(globalThis);
|
|
1161
|
-
|
|
1162
|
-
function rewriteUrl(url) {
|
|
1163
|
-
try {
|
|
1164
|
-
const parsed = new URL(url, location.origin);
|
|
1165
|
-
for (const rule of rules) {
|
|
1166
|
-
if (parsed.hostname === rule.pattern || parsed.hostname.endsWith('.' + rule.pattern)) {
|
|
1167
|
-
if (rule.pathPrefix && !parsed.pathname.startsWith(rule.pathPrefix)) continue;
|
|
1168
|
-
const path = rule.pathPrefix ? parsed.pathname.slice(rule.pathPrefix.length) : parsed.pathname;
|
|
1169
|
-
return location.origin + rule.target + (path.startsWith('/') ? '' : '/') + path + parsed.search;
|
|
1170
|
-
}
|
|
1171
|
-
}
|
|
1172
|
-
} catch {}
|
|
1173
|
-
return url;
|
|
1174
|
-
}
|
|
1175
|
-
|
|
1176
|
-
globalThis.__nuxtScripts = {
|
|
1177
|
-
sendBeacon: (url, data) => origBeacon(rewriteUrl(url), data),
|
|
1178
|
-
fetch: (url, opts) => origFetch(typeof url === 'string' ? rewriteUrl(url) : url, opts),
|
|
1179
|
-
};
|
|
1180
|
-
},
|
|
1181
|
-
})
|
|
1182
|
-
`;
|
|
1183
|
-
}
|
|
1184
|
-
});
|
|
1185
|
-
const proxyHandlerPath = await resolvePath("./runtime/server/proxy-handler");
|
|
1186
|
-
logger.debug("[nuxt-scripts] Registering proxy handler:", `${firstPartyCollectPrefix}/**`, "->", proxyHandlerPath);
|
|
1187
|
-
addServerHandler({
|
|
1188
|
-
route: `${firstPartyCollectPrefix}/**`,
|
|
1189
|
-
handler: proxyHandlerPath
|
|
1190
|
-
});
|
|
1463
|
+
if (firstParty.enabled) {
|
|
1464
|
+
interceptRules = await setupFirstPartyHandlers(firstParty, resolvePath);
|
|
1191
1465
|
}
|
|
1192
1466
|
const scripts = await registry(resolvePath);
|
|
1193
1467
|
for (const script of scripts) {
|
|
@@ -1216,96 +1490,14 @@ const module$1 = defineNuxtModule({
|
|
|
1216
1490
|
});
|
|
1217
1491
|
}
|
|
1218
1492
|
const { renderedScript } = setupPublicAssetStrategy(config.assets);
|
|
1219
|
-
if (
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
const proxyKey = script?.proxy || void 0;
|
|
1228
|
-
if (proxyKey) {
|
|
1229
|
-
const proxyConfig = proxyConfigs[proxyKey];
|
|
1230
|
-
if (proxyConfig?.routes) {
|
|
1231
|
-
Object.assign(neededRoutes, proxyConfig.routes);
|
|
1232
|
-
for (const routePath of Object.keys(proxyConfig.routes)) {
|
|
1233
|
-
routePrivacyOverrides[routePath] = proxyConfig.privacy;
|
|
1234
|
-
}
|
|
1235
|
-
} else {
|
|
1236
|
-
unsupportedScripts.push(key);
|
|
1237
|
-
}
|
|
1238
|
-
}
|
|
1239
|
-
}
|
|
1240
|
-
if (config.registry?.posthog && typeof config.registry.posthog === "object") {
|
|
1241
|
-
const phConfig = Array.isArray(config.registry.posthog) ? config.registry.posthog[0] : config.registry.posthog;
|
|
1242
|
-
if (phConfig && !phConfig.apiHost) {
|
|
1243
|
-
const region = phConfig.region || "us";
|
|
1244
|
-
phConfig.apiHost = region === "eu" ? `${firstPartyCollectPrefix}/ph-eu` : `${firstPartyCollectPrefix}/ph`;
|
|
1245
|
-
const rtScripts = nuxt.options.runtimeConfig.public.scripts;
|
|
1246
|
-
if (rtScripts?.posthog && typeof rtScripts.posthog === "object") {
|
|
1247
|
-
const rtPhConfig = Array.isArray(rtScripts.posthog) ? rtScripts.posthog[0] : rtScripts.posthog;
|
|
1248
|
-
if (rtPhConfig)
|
|
1249
|
-
rtPhConfig.apiHost = phConfig.apiHost;
|
|
1250
|
-
}
|
|
1251
|
-
}
|
|
1252
|
-
}
|
|
1253
|
-
if (config.registry?.plausibleAnalytics && typeof config.registry.plausibleAnalytics === "object") {
|
|
1254
|
-
const paConfig = Array.isArray(config.registry.plausibleAnalytics) ? config.registry.plausibleAnalytics[0] : config.registry.plausibleAnalytics;
|
|
1255
|
-
if (paConfig && !paConfig.endpoint) {
|
|
1256
|
-
paConfig.endpoint = `${firstPartyCollectPrefix}/plausible/api/event`;
|
|
1257
|
-
const rtScripts = nuxt.options.runtimeConfig.public.scripts;
|
|
1258
|
-
if (rtScripts?.plausibleAnalytics && typeof rtScripts.plausibleAnalytics === "object") {
|
|
1259
|
-
const rtPaConfig = Array.isArray(rtScripts.plausibleAnalytics) ? rtScripts.plausibleAnalytics[0] : rtScripts.plausibleAnalytics;
|
|
1260
|
-
if (rtPaConfig)
|
|
1261
|
-
rtPaConfig.endpoint = paConfig.endpoint;
|
|
1262
|
-
}
|
|
1263
|
-
}
|
|
1264
|
-
}
|
|
1265
|
-
if (unsupportedScripts.length && nuxt.options.dev) {
|
|
1266
|
-
logger.warn(
|
|
1267
|
-
`First-party mode is enabled but these scripts don't support it yet: ${unsupportedScripts.join(", ")}.
|
|
1268
|
-
They will load directly from third-party servers. Request support at https://github.com/nuxt/scripts/issues`
|
|
1269
|
-
);
|
|
1270
|
-
}
|
|
1271
|
-
interceptRules = routesToInterceptRules(neededRoutes);
|
|
1272
|
-
const flatRoutes = {};
|
|
1273
|
-
for (const [path, config2] of Object.entries(neededRoutes)) {
|
|
1274
|
-
flatRoutes[path] = config2.proxy;
|
|
1275
|
-
}
|
|
1276
|
-
nuxt.options.runtimeConfig["nuxt-scripts-proxy"] = {
|
|
1277
|
-
routes: flatRoutes,
|
|
1278
|
-
privacy: firstPartyPrivacy,
|
|
1279
|
-
// undefined = use per-script defaults, set = global override
|
|
1280
|
-
routePrivacy: routePrivacyOverrides
|
|
1281
|
-
// per-script privacy from registry
|
|
1282
|
-
};
|
|
1283
|
-
if (Object.keys(neededRoutes).length) {
|
|
1284
|
-
if (nuxt.options.dev) {
|
|
1285
|
-
const routeCount = Object.keys(neededRoutes).length;
|
|
1286
|
-
const scriptsCount = registryKeys.length;
|
|
1287
|
-
const privacyLabel = firstPartyPrivacy === void 0 ? "per-script" : typeof firstPartyPrivacy === "boolean" ? firstPartyPrivacy ? "anonymize" : "passthrough" : "custom";
|
|
1288
|
-
logger.success(`First-party mode enabled for ${scriptsCount} script(s), ${routeCount} proxy route(s) configured (privacy: ${privacyLabel})`);
|
|
1289
|
-
if (logger.level >= 4) {
|
|
1290
|
-
for (const [path, config2] of Object.entries(neededRoutes)) {
|
|
1291
|
-
logger.debug(` ${path} \u2192 ${config2.proxy}`);
|
|
1292
|
-
}
|
|
1293
|
-
}
|
|
1294
|
-
}
|
|
1295
|
-
}
|
|
1296
|
-
if (isStaticPreset) {
|
|
1297
|
-
logger.warn(
|
|
1298
|
-
`First-party collection endpoints require a server runtime (detected: ${preset || "static"}).
|
|
1299
|
-
Scripts will be bundled, but collection requests will not be proxied.
|
|
1300
|
-
|
|
1301
|
-
Options:
|
|
1302
|
-
1. Configure platform rewrites (Vercel, Netlify, Cloudflare)
|
|
1303
|
-
2. Switch to server-rendered mode (ssr: true)
|
|
1304
|
-
3. Disable with firstParty: false
|
|
1305
|
-
|
|
1306
|
-
See: https://scripts.nuxt.com/docs/guides/first-party#static-hosting`
|
|
1307
|
-
);
|
|
1308
|
-
}
|
|
1493
|
+
if (firstParty.enabled) {
|
|
1494
|
+
finalizeFirstParty({
|
|
1495
|
+
firstParty,
|
|
1496
|
+
interceptRules,
|
|
1497
|
+
registry: config.registry,
|
|
1498
|
+
registryScriptsWithImport,
|
|
1499
|
+
nuxtOptions: nuxt.options
|
|
1500
|
+
});
|
|
1309
1501
|
}
|
|
1310
1502
|
const moduleInstallPromises = /* @__PURE__ */ new Map();
|
|
1311
1503
|
addBuildPlugin(NuxtScriptsCheckScripts(), {
|
|
@@ -1314,9 +1506,9 @@ See: https://scripts.nuxt.com/docs/guides/first-party#static-hosting`
|
|
|
1314
1506
|
addBuildPlugin(NuxtScriptBundleTransformer({
|
|
1315
1507
|
scripts: registryScriptsWithImport,
|
|
1316
1508
|
registryConfig: nuxt.options.runtimeConfig.public.scripts,
|
|
1317
|
-
defaultBundle:
|
|
1318
|
-
firstPartyEnabled,
|
|
1319
|
-
firstPartyCollectPrefix,
|
|
1509
|
+
defaultBundle: firstParty.enabled || config.defaultScriptOptions?.bundle,
|
|
1510
|
+
firstPartyEnabled: firstParty.enabled,
|
|
1511
|
+
firstPartyCollectPrefix: firstParty.collectPrefix,
|
|
1320
1512
|
moduleDetected(module) {
|
|
1321
1513
|
if (nuxt.options.dev && module !== "@nuxt/scripts" && !moduleInstallPromises.has(module) && !hasNuxtModule(module))
|
|
1322
1514
|
moduleInstallPromises.set(module, () => installNuxtModule(module));
|
|
@@ -1329,7 +1521,7 @@ See: https://scripts.nuxt.com/docs/guides/first-party#static-hosting`
|
|
|
1329
1521
|
renderedScript
|
|
1330
1522
|
}));
|
|
1331
1523
|
nuxt.hooks.hook("build:done", async () => {
|
|
1332
|
-
const initPromise =
|
|
1524
|
+
const initPromise = [...moduleInstallPromises.values()];
|
|
1333
1525
|
for (const p of initPromise)
|
|
1334
1526
|
await p?.();
|
|
1335
1527
|
});
|