@nuxt/scripts 1.0.0-rc.1 → 1.0.0-rc.11
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/bin/cli.mjs +2 -0
- package/dist/cli.d.mts +2 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.mjs +50 -0
- package/dist/devtools-client/200.html +1 -1
- package/dist/devtools-client/404.html +1 -1
- package/dist/devtools-client/_nuxt/{ajngqPCs.js → BgPDxVUn.js} +1 -1
- package/dist/devtools-client/_nuxt/{DKL6PHO3.js → BmlapxLP.js} +1 -1
- package/dist/devtools-client/_nuxt/CM2vefXI.js +188 -0
- package/dist/devtools-client/_nuxt/{CfOsp0mU.js → DAF5Qk9P.js} +1 -1
- package/dist/devtools-client/_nuxt/{B3kN3DAy.js → Dx6HhVmj.js} +1 -1
- package/dist/devtools-client/_nuxt/{dlaR8P-P.js → S8LiR9M1.js} +1 -1
- package/dist/devtools-client/_nuxt/builds/latest.json +1 -1
- package/dist/devtools-client/_nuxt/builds/meta/d788053e-f511-4867-b557-1952fcbcae82.json +1 -0
- package/dist/devtools-client/_nuxt/{entry.BwpOBArY.css → entry.BKkVrcJj.css} +1 -1
- package/dist/devtools-client/_nuxt/error-404.d44aGwWI.css +1 -0
- package/dist/devtools-client/_nuxt/error-500.NthMfIEt.css +1 -0
- package/dist/devtools-client/_nuxt/index.DZD1lwyI.css +1 -0
- package/dist/devtools-client/_nuxt/vBkR1GJq.js +1 -0
- package/dist/devtools-client/docs/index.html +1 -1
- package/dist/devtools-client/first-party/index.html +1 -1
- package/dist/devtools-client/index.html +1 -1
- package/dist/devtools-client/registry/index.html +1 -1
- package/dist/module.d.mts +66 -2
- package/dist/module.d.ts +66 -2
- package/dist/module.json +1 -1
- package/dist/module.mjs +151 -30
- package/dist/registry.d.mts +1 -0
- package/dist/registry.d.ts +1 -0
- package/dist/registry.mjs +14 -14
- package/dist/runtime/components/GoogleMaps/ScriptGoogleMaps.d.vue.ts +73 -97
- package/dist/runtime/components/GoogleMaps/ScriptGoogleMaps.vue +81 -58
- package/dist/runtime/components/GoogleMaps/ScriptGoogleMaps.vue.d.ts +73 -97
- package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsInfoWindow.d.vue.ts +2 -3
- package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsInfoWindow.vue +1 -0
- package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsInfoWindow.vue.d.ts +2 -3
- package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsMarker.d.vue.ts +2 -3
- package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsMarker.vue +2 -1
- package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsMarker.vue.d.ts +2 -3
- package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsMarkerClusterer.d.vue.ts +10 -43
- package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsMarkerClusterer.vue +3 -1
- package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsMarkerClusterer.vue.d.ts +10 -43
- package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsOverlayView.d.vue.ts +50 -30
- package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsOverlayView.vue +145 -104
- package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsOverlayView.vue.d.ts +50 -30
- package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsStaticMap.vue +7 -2
- package/dist/runtime/components/GoogleMaps/types.d.ts +42 -0
- package/dist/runtime/components/GoogleMaps/types.js +1 -0
- package/dist/runtime/components/GoogleMaps/useGoogleMapsResource.d.ts +50 -0
- package/dist/runtime/components/GoogleMaps/useGoogleMapsResource.js +76 -1
- package/dist/runtime/components/ScriptBlueskyEmbed.d.vue.ts +10 -12
- package/dist/runtime/components/ScriptBlueskyEmbed.vue +13 -10
- package/dist/runtime/components/ScriptBlueskyEmbed.vue.d.ts +10 -12
- package/dist/runtime/components/ScriptCarbonAds.d.vue.ts +4 -7
- package/dist/runtime/components/ScriptCarbonAds.vue +1 -0
- package/dist/runtime/components/ScriptCarbonAds.vue.d.ts +4 -7
- package/dist/runtime/components/ScriptCrisp.d.vue.ts +7 -11
- package/dist/runtime/components/ScriptCrisp.vue +1 -0
- package/dist/runtime/components/ScriptCrisp.vue.d.ts +7 -11
- package/dist/runtime/components/ScriptGoogleAdsense.d.vue.ts +4 -7
- package/dist/runtime/components/ScriptGoogleAdsense.vue +1 -0
- package/dist/runtime/components/ScriptGoogleAdsense.vue.d.ts +4 -7
- package/dist/runtime/components/ScriptInstagramEmbed.d.vue.ts +11 -13
- package/dist/runtime/components/ScriptInstagramEmbed.vue +4 -1
- package/dist/runtime/components/ScriptInstagramEmbed.vue.d.ts +11 -13
- package/dist/runtime/components/ScriptIntercom.d.vue.ts +7 -11
- package/dist/runtime/components/ScriptIntercom.vue +1 -0
- package/dist/runtime/components/ScriptIntercom.vue.d.ts +7 -11
- package/dist/runtime/components/ScriptLemonSqueezy.d.vue.ts +2 -3
- package/dist/runtime/components/ScriptLemonSqueezy.vue +1 -0
- package/dist/runtime/components/ScriptLemonSqueezy.vue.d.ts +2 -3
- package/dist/runtime/components/ScriptPayPalButtons.d.vue.ts +8 -13
- package/dist/runtime/components/ScriptPayPalButtons.vue +1 -0
- package/dist/runtime/components/ScriptPayPalButtons.vue.d.ts +8 -13
- package/dist/runtime/components/ScriptPayPalMessages.d.vue.ts +8 -13
- package/dist/runtime/components/ScriptPayPalMessages.vue +1 -0
- package/dist/runtime/components/ScriptPayPalMessages.vue.d.ts +8 -13
- package/dist/runtime/components/ScriptStripePricingTable.d.vue.ts +5 -9
- package/dist/runtime/components/ScriptStripePricingTable.vue +1 -0
- package/dist/runtime/components/ScriptStripePricingTable.vue.d.ts +5 -9
- package/dist/runtime/components/ScriptVimeoPlayer.d.vue.ts +8 -11
- package/dist/runtime/components/ScriptVimeoPlayer.vue +1 -0
- package/dist/runtime/components/ScriptVimeoPlayer.vue.d.ts +8 -11
- package/dist/runtime/components/ScriptXEmbed.d.vue.ts +10 -12
- package/dist/runtime/components/ScriptXEmbed.vue +12 -9
- package/dist/runtime/components/ScriptXEmbed.vue.d.ts +10 -12
- package/dist/runtime/components/ScriptYouTubePlayer.d.vue.ts +8 -13
- package/dist/runtime/components/ScriptYouTubePlayer.vue +1 -0
- package/dist/runtime/components/ScriptYouTubePlayer.vue.d.ts +8 -13
- package/dist/runtime/composables/useScript.js +17 -6
- package/dist/runtime/composables/useScriptProxyToken.d.ts +12 -0
- package/dist/runtime/composables/useScriptProxyToken.js +4 -0
- package/dist/runtime/composables/useScriptProxyUrl.d.ts +12 -0
- package/dist/runtime/composables/useScriptProxyUrl.js +27 -0
- package/dist/runtime/plugins/proxy-token.server.d.ts +10 -0
- package/dist/runtime/plugins/proxy-token.server.js +17 -0
- package/dist/runtime/registry/bing-uet.d.ts +189 -11
- package/dist/runtime/registry/bing-uet.js +16 -2
- package/dist/runtime/registry/bluesky-embed.d.ts +0 -4
- package/dist/runtime/registry/bluesky-embed.js +0 -4
- package/dist/runtime/registry/clarity.d.ts +6 -2
- package/dist/runtime/registry/clarity.js +12 -1
- package/dist/runtime/registry/google-analytics.d.ts +6 -2
- package/dist/runtime/registry/google-analytics.js +12 -1
- package/dist/runtime/registry/google-tag-manager.d.ts +6 -2
- package/dist/runtime/registry/google-tag-manager.js +10 -1
- package/dist/runtime/registry/gravatar.js +10 -13
- package/dist/runtime/registry/matomo-analytics.d.ts +9 -3
- package/dist/runtime/registry/matomo-analytics.js +28 -1
- package/dist/runtime/registry/meta-pixel.d.ts +8 -2
- package/dist/runtime/registry/meta-pixel.js +10 -1
- package/dist/runtime/registry/mixpanel-analytics.d.ts +12 -2
- package/dist/runtime/registry/mixpanel-analytics.js +16 -4
- package/dist/runtime/registry/posthog.d.ts +8 -2
- package/dist/runtime/registry/posthog.js +15 -4
- package/dist/runtime/registry/schemas.d.ts +65 -0
- package/dist/runtime/registry/schemas.js +75 -8
- package/dist/runtime/registry/tiktok-pixel.d.ts +16 -2
- package/dist/runtime/registry/tiktok-pixel.js +22 -1
- package/dist/runtime/registry/x-embed.d.ts +0 -4
- package/dist/runtime/registry/x-embed.js +0 -4
- package/dist/runtime/server/bluesky-embed-image.d.ts +1 -1
- package/dist/runtime/server/bluesky-embed.d.ts +1 -15
- package/dist/runtime/server/bluesky-embed.js +25 -6
- package/dist/runtime/server/google-maps-geocode-proxy.js +12 -8
- package/dist/runtime/server/google-static-maps-proxy.d.ts +1 -1
- package/dist/runtime/server/google-static-maps-proxy.js +17 -11
- package/dist/runtime/server/gravatar-proxy.d.ts +1 -1
- package/dist/runtime/server/gravatar-proxy.js +10 -10
- package/dist/runtime/server/instagram-embed-asset.d.ts +1 -1
- package/dist/runtime/server/instagram-embed-image.d.ts +1 -1
- package/dist/runtime/server/instagram-embed.d.ts +1 -16
- package/dist/runtime/server/instagram-embed.js +26 -125
- package/dist/runtime/server/proxy-handler.js +1 -2
- package/dist/runtime/server/utils/cached-upstream.d.ts +55 -0
- package/dist/runtime/server/utils/cached-upstream.js +65 -0
- package/dist/runtime/server/utils/embed-rewriters.d.ts +19 -0
- package/dist/runtime/server/utils/embed-rewriters.js +41 -0
- package/dist/runtime/server/utils/image-proxy.d.ts +3 -1
- package/dist/runtime/server/utils/image-proxy.js +11 -8
- package/dist/runtime/server/utils/instagram-embed.d.ts +16 -0
- package/dist/runtime/server/utils/instagram-embed.js +153 -0
- package/dist/runtime/server/utils/proxy-url.d.ts +9 -0
- package/dist/runtime/server/utils/proxy-url.js +21 -0
- package/dist/runtime/server/utils/sign-constants.d.ts +16 -0
- package/dist/runtime/server/utils/sign-constants.js +5 -0
- package/dist/runtime/server/utils/sign.d.ts +101 -0
- package/dist/runtime/server/utils/sign.js +91 -0
- package/dist/runtime/server/utils/withSigning.d.ts +23 -0
- package/dist/runtime/server/utils/withSigning.js +19 -0
- package/dist/runtime/server/x-embed-image.d.ts +1 -1
- package/dist/runtime/server/x-embed.js +23 -4
- package/dist/runtime/types.d.ts +41 -6
- package/dist/runtime/types.js +1 -0
- package/dist/stats.mjs +298 -338
- package/dist/types-source.mjs +537 -164
- package/dist/types.d.mts +2 -2
- package/package.json +10 -6
- package/dist/devtools-client/_nuxt/C8jhSQ8l.js +0 -1
- package/dist/devtools-client/_nuxt/CJD6wrkT.js +0 -188
- package/dist/devtools-client/_nuxt/builds/meta/b800a0be-5cab-4ea6-89e3-dd3a85690a73.json +0 -1
- package/dist/devtools-client/_nuxt/error-404.CvOVjXeC.css +0 -1
- package/dist/devtools-client/_nuxt/error-500.BIm53nmx.css +0 -1
- package/dist/devtools-client/_nuxt/index.CA-OpSj0.css +0 -1
package/dist/module.mjs
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { createHash, randomBytes } from 'node:crypto';
|
|
2
|
+
import { existsSync, readFileSync, appendFileSync, writeFileSync, readdirSync } from 'node:fs';
|
|
3
|
+
import { useNuxt, addDevServerHandler, extendRouteRules, tryUseNuxt, createResolver, extendViteConfig, logger as logger$1, useLogger, addTypeTemplate, defineNuxtModule, addPluginTemplate, addServerHandler, addImports, addComponentsDir, addTemplate, hasNuxtModule, addBuildPlugin, addPlugin } from '@nuxt/kit';
|
|
3
4
|
import { defu } from 'defu';
|
|
4
5
|
import { join, resolve } from 'pathe';
|
|
5
6
|
import { resolvePackageJSON, readPackageJSON } from 'pkg-types';
|
|
@@ -12,7 +13,6 @@ import { isCI, provider } from 'std-env';
|
|
|
12
13
|
import { parseAndWalk, ScopeTracker, walk, ScopeTrackerFunction, ScopeTrackerIdentifier, ScopeTrackerFunctionParam, ScopeTrackerVariable } from 'oxc-walker';
|
|
13
14
|
import { createUnplugin } from 'unplugin';
|
|
14
15
|
import { pathToFileURL } from 'node:url';
|
|
15
|
-
import { createHash } from 'node:crypto';
|
|
16
16
|
import fsp from 'node:fs/promises';
|
|
17
17
|
import { colors } from 'consola/utils';
|
|
18
18
|
import MagicString from 'magic-string';
|
|
@@ -288,7 +288,7 @@ function migrateDeprecatedRegistryKeys(registry, warn) {
|
|
|
288
288
|
}
|
|
289
289
|
}
|
|
290
290
|
}
|
|
291
|
-
function normalizeRegistryConfig(registry, warn) {
|
|
291
|
+
function normalizeRegistryConfig(registry, warn, componentOnlyKeys) {
|
|
292
292
|
for (const key of Object.keys(registry)) {
|
|
293
293
|
const entry = registry[key];
|
|
294
294
|
if (!entry) {
|
|
@@ -296,6 +296,10 @@ function normalizeRegistryConfig(registry, warn) {
|
|
|
296
296
|
continue;
|
|
297
297
|
}
|
|
298
298
|
if (entry === true) {
|
|
299
|
+
if (componentOnlyKeys?.has(key)) {
|
|
300
|
+
registry[key] = [{}];
|
|
301
|
+
continue;
|
|
302
|
+
}
|
|
299
303
|
warn?.(`[nuxt-scripts] registry.${key}: \`true\` shorthand is deprecated. Use \`{ trigger: 'onNuxtReady' }\` instead.`);
|
|
300
304
|
registry[key] = [{}, { trigger: "onNuxtReady" }];
|
|
301
305
|
continue;
|
|
@@ -416,7 +420,8 @@ function NuxtScriptsCheckScripts() {
|
|
|
416
420
|
});
|
|
417
421
|
}
|
|
418
422
|
|
|
419
|
-
function generateInterceptPluginContents(proxyPrefix) {
|
|
423
|
+
function generateInterceptPluginContents(proxyPrefix, options) {
|
|
424
|
+
const testMode = options?.testMode ?? false;
|
|
420
425
|
return `export default defineNuxtPlugin({
|
|
421
426
|
name: 'nuxt-scripts:intercept',
|
|
422
427
|
enforce: 'pre',
|
|
@@ -461,8 +466,14 @@ function generateInterceptPluginContents(proxyPrefix) {
|
|
|
461
466
|
return img;
|
|
462
467
|
}
|
|
463
468
|
|
|
464
|
-
globalThis.__nuxtScripts = {
|
|
465
|
-
|
|
469
|
+
globalThis.__nuxtScripts = {${testMode ? `
|
|
470
|
+
// Test mode: replace sendBeacon with fetch for immediate, observable requests
|
|
471
|
+
sendBeacon: (url, data) => {
|
|
472
|
+
const proxied = proxyUrl(url);
|
|
473
|
+
origFetch(proxied, { method: 'POST', body: data, keepalive: true }).catch(() => {});
|
|
474
|
+
return true;
|
|
475
|
+
},` : `
|
|
476
|
+
sendBeacon: (url, data) => origBeacon(proxyUrl(url), data),`}
|
|
466
477
|
fetch: (url, opts) => {
|
|
467
478
|
if (typeof url === 'string') return origFetch(proxyUrl(url), opts);
|
|
468
479
|
if (url instanceof Request) return origFetch(new Request(proxyUrl(url.url), url), opts);
|
|
@@ -908,6 +919,7 @@ function NuxtScriptBundleTransformer(options = {
|
|
|
908
919
|
const node = _node;
|
|
909
920
|
let scriptSrcNode;
|
|
910
921
|
let src;
|
|
922
|
+
let registryConfig = {};
|
|
911
923
|
let registryKey;
|
|
912
924
|
if (fnName !== "useScript") {
|
|
913
925
|
const baseName = fnName.replace(USE_SCRIPT_RE, "");
|
|
@@ -930,7 +942,7 @@ function NuxtScriptBundleTransformer(options = {
|
|
|
930
942
|
const bundleResolve = getBundleResolve(registryNode);
|
|
931
943
|
if (!bundleResolve && !registryNode.src)
|
|
932
944
|
return;
|
|
933
|
-
|
|
945
|
+
registryConfig = options.registryConfig?.[registryKey || ""] || {};
|
|
934
946
|
const fnArg0 = {};
|
|
935
947
|
if (node.arguments[0]?.type === "ObjectExpression") {
|
|
936
948
|
const optionsNode = node.arguments[0];
|
|
@@ -978,12 +990,14 @@ function NuxtScriptBundleTransformer(options = {
|
|
|
978
990
|
const registryScript = fnName !== "useScript" ? options.scripts?.find((s2) => s2.import.name === fnName) : void 0;
|
|
979
991
|
let canBundle = !!registryScript?.bundle;
|
|
980
992
|
let forceDownload = false;
|
|
993
|
+
let explicitBundleInCall = false;
|
|
981
994
|
if (node.arguments[1]?.type === "ObjectExpression") {
|
|
982
995
|
const scriptOptionsArg = node.arguments[1];
|
|
983
996
|
const bundleProperty = scriptOptionsArg.properties.find(
|
|
984
997
|
(p) => (p.key?.name === "bundle" || p.key?.value === "bundle") && p.type === "Property"
|
|
985
998
|
);
|
|
986
999
|
if (bundleProperty && bundleProperty.value.type === "Literal") {
|
|
1000
|
+
explicitBundleInCall = true;
|
|
987
1001
|
const bundleValue = bundleProperty.value.value;
|
|
988
1002
|
if (bundleValue !== true && bundleValue !== "force" && String(bundleValue) !== "true") {
|
|
989
1003
|
canBundle = false;
|
|
@@ -1008,10 +1022,16 @@ function NuxtScriptBundleTransformer(options = {
|
|
|
1008
1022
|
return prop.type === "Property" && prop.key?.name === "bundle" && prop.value.type === "Literal";
|
|
1009
1023
|
});
|
|
1010
1024
|
if (bundleOption) {
|
|
1025
|
+
explicitBundleInCall = true;
|
|
1011
1026
|
const bundleValue = bundleOption.value.value;
|
|
1012
1027
|
canBundle = bundleValue === true || bundleValue === "force" || String(bundleValue) === "true";
|
|
1013
1028
|
forceDownload = bundleValue === "force";
|
|
1014
1029
|
}
|
|
1030
|
+
if (!explicitBundleInCall && registryConfig?.scriptOptions?.bundle !== void 0) {
|
|
1031
|
+
const bundleValue = registryConfig.scriptOptions.bundle;
|
|
1032
|
+
canBundle = bundleValue === true || bundleValue === "force" || String(bundleValue) === "true";
|
|
1033
|
+
forceDownload = bundleValue === "force";
|
|
1034
|
+
}
|
|
1015
1035
|
const rpiOption = scriptOptions?.value.properties?.find((prop) => {
|
|
1016
1036
|
return prop.type === "Property" && prop.key?.name === "proxy" && prop.value.type === "Literal";
|
|
1017
1037
|
});
|
|
@@ -1214,14 +1234,15 @@ function templatePlugin(config, registry) {
|
|
|
1214
1234
|
for (const [k, c] of Object.entries(config.registry || {})) {
|
|
1215
1235
|
if (c === false)
|
|
1216
1236
|
continue;
|
|
1217
|
-
const
|
|
1237
|
+
const entry = c;
|
|
1238
|
+
const [, scriptOptions] = entry;
|
|
1218
1239
|
if (!scriptOptions?.trigger)
|
|
1219
1240
|
continue;
|
|
1220
1241
|
const importDefinition = registry.find((i) => i.import.name.toLowerCase() === `usescript${k.toLowerCase()}`);
|
|
1221
1242
|
if (importDefinition) {
|
|
1222
1243
|
resolvedRegistryKeys.push(k);
|
|
1223
1244
|
imports.unshift(`import { ${importDefinition.import.name} } from '${importDefinition.import.from}'`);
|
|
1224
|
-
const [input] =
|
|
1245
|
+
const [input] = entry;
|
|
1225
1246
|
const opts = { ...scriptOptions };
|
|
1226
1247
|
const triggerResolved = resolveTriggerForTemplate(opts.trigger);
|
|
1227
1248
|
if (triggerResolved) {
|
|
@@ -1356,6 +1377,42 @@ function fixSelfClosingScriptComponents(nuxt) {
|
|
|
1356
1377
|
}
|
|
1357
1378
|
const UPPER_RE = /([A-Z])/g;
|
|
1358
1379
|
const toScreamingSnake = (s) => s.replace(UPPER_RE, "_$1").toUpperCase();
|
|
1380
|
+
const PROXY_SECRET_ENV_KEY = "NUXT_SCRIPTS_PROXY_SECRET";
|
|
1381
|
+
const PROXY_SECRET_ENV_LINE_RE = /^NUXT_SCRIPTS_PROXY_SECRET=/m;
|
|
1382
|
+
const PROXY_SECRET_ENV_VALUE_RE = /^NUXT_SCRIPTS_PROXY_SECRET=(.+)$/m;
|
|
1383
|
+
function resolveProxySecret(rootDir, isDev, configSecret, autoGenerate = true) {
|
|
1384
|
+
if (configSecret)
|
|
1385
|
+
return { secret: configSecret, ephemeral: false, source: "config" };
|
|
1386
|
+
const envSecret = process.env[PROXY_SECRET_ENV_KEY];
|
|
1387
|
+
if (envSecret)
|
|
1388
|
+
return { secret: envSecret, ephemeral: false, source: "env" };
|
|
1389
|
+
if (!isDev || !autoGenerate)
|
|
1390
|
+
return void 0;
|
|
1391
|
+
const secret = randomBytes(32).toString("hex");
|
|
1392
|
+
const envPath = resolve(rootDir, ".env");
|
|
1393
|
+
const line = `${PROXY_SECRET_ENV_KEY}=${secret}
|
|
1394
|
+
`;
|
|
1395
|
+
try {
|
|
1396
|
+
if (existsSync(envPath)) {
|
|
1397
|
+
const contents = readFileSync(envPath, "utf-8");
|
|
1398
|
+
if (PROXY_SECRET_ENV_LINE_RE.test(contents)) {
|
|
1399
|
+
const match = contents.match(PROXY_SECRET_ENV_VALUE_RE);
|
|
1400
|
+
if (match?.[1])
|
|
1401
|
+
return { secret: match[1].trim(), ephemeral: false, source: "dotenv-generated" };
|
|
1402
|
+
}
|
|
1403
|
+
appendFileSync(envPath, contents.endsWith("\n") ? line : `
|
|
1404
|
+
${line}`);
|
|
1405
|
+
} else {
|
|
1406
|
+
writeFileSync(envPath, `# Generated by @nuxt/scripts
|
|
1407
|
+
${line}`);
|
|
1408
|
+
}
|
|
1409
|
+
process.env[PROXY_SECRET_ENV_KEY] = secret;
|
|
1410
|
+
return { secret, ephemeral: false, source: "dotenv-generated" };
|
|
1411
|
+
} catch {
|
|
1412
|
+
process.env[PROXY_SECRET_ENV_KEY] = secret;
|
|
1413
|
+
return { secret, ephemeral: true, source: "memory-generated" };
|
|
1414
|
+
}
|
|
1415
|
+
}
|
|
1359
1416
|
function isProxyDisabled(registryKey, registry2, runtimeConfig) {
|
|
1360
1417
|
const entry = registry2?.[registryKey];
|
|
1361
1418
|
if (!entry)
|
|
@@ -1443,25 +1500,32 @@ const module$1 = defineNuxtModule({
|
|
|
1443
1500
|
}
|
|
1444
1501
|
const scripts = await registry(resolvePath);
|
|
1445
1502
|
if (config.registry) {
|
|
1503
|
+
const componentOnlyKeys = new Set(scripts.filter((s) => !s.import).map((s) => s.registryKey));
|
|
1446
1504
|
migrateDeprecatedRegistryKeys(config.registry, (msg) => logger.warn(msg));
|
|
1447
|
-
normalizeRegistryConfig(config.registry, (msg) => logger.warn(msg));
|
|
1505
|
+
normalizeRegistryConfig(config.registry, (msg) => logger.warn(msg), componentOnlyKeys);
|
|
1448
1506
|
nuxt.options.runtimeConfig.public = nuxt.options.runtimeConfig.public || {};
|
|
1449
1507
|
const registryWithDefaults = {};
|
|
1450
1508
|
for (const [key, entry] of Object.entries(config.registry)) {
|
|
1451
1509
|
if (entry === false)
|
|
1452
1510
|
continue;
|
|
1453
1511
|
const input = entry[0];
|
|
1512
|
+
const scriptOptions = entry[1];
|
|
1454
1513
|
const envDefaults = scripts.find((s) => s.registryKey === key)?.envDefaults;
|
|
1514
|
+
const base = {};
|
|
1455
1515
|
if (!envDefaults || !Object.keys(envDefaults).length) {
|
|
1456
|
-
|
|
1457
|
-
|
|
1516
|
+
Object.assign(base, input);
|
|
1517
|
+
} else {
|
|
1518
|
+
const envResolved = {};
|
|
1519
|
+
for (const [field, defaultValue] of Object.entries(envDefaults)) {
|
|
1520
|
+
const envKey = `NUXT_PUBLIC_SCRIPTS_${toScreamingSnake(key)}_${toScreamingSnake(field)}`;
|
|
1521
|
+
envResolved[field] = process.env[envKey] || defaultValue;
|
|
1522
|
+
}
|
|
1523
|
+
Object.assign(base, defu(input, envResolved));
|
|
1458
1524
|
}
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
const envKey = `NUXT_PUBLIC_SCRIPTS_${toScreamingSnake(key)}_${toScreamingSnake(field)}`;
|
|
1462
|
-
envResolved[field] = process.env[envKey] || defaultValue;
|
|
1525
|
+
if (scriptOptions && Object.keys(scriptOptions).length > 0) {
|
|
1526
|
+
base.scriptOptions = scriptOptions;
|
|
1463
1527
|
}
|
|
1464
|
-
registryWithDefaults[key] =
|
|
1528
|
+
registryWithDefaults[key] = base;
|
|
1465
1529
|
}
|
|
1466
1530
|
nuxt.options.runtimeConfig.public.scripts = defu(
|
|
1467
1531
|
nuxt.options.runtimeConfig.public.scripts || {},
|
|
@@ -1491,6 +1555,8 @@ const module$1 = defineNuxtModule({
|
|
|
1491
1555
|
const composables = [
|
|
1492
1556
|
"useScript",
|
|
1493
1557
|
"useScriptEventPage",
|
|
1558
|
+
"useScriptProxyToken",
|
|
1559
|
+
"useScriptProxyUrl",
|
|
1494
1560
|
"useScriptTriggerConsent",
|
|
1495
1561
|
"useScriptTriggerElement",
|
|
1496
1562
|
"useScriptTriggerIdleTimeout",
|
|
@@ -1533,10 +1599,23 @@ const module$1 = defineNuxtModule({
|
|
|
1533
1599
|
const script = scripts.find((s) => s.registryKey === key);
|
|
1534
1600
|
if (!script?.schema)
|
|
1535
1601
|
continue;
|
|
1536
|
-
const
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1602
|
+
const isComponentOnly = !script.import;
|
|
1603
|
+
if (isComponentOnly) {
|
|
1604
|
+
if (scriptOptions && "trigger" in scriptOptions && scriptOptions.trigger !== false) {
|
|
1605
|
+
const pascal = key.charAt(0).toUpperCase() + key.slice(1);
|
|
1606
|
+
logger.warn(
|
|
1607
|
+
`[nuxt-scripts] registry.${key}: \`trigger\` has no effect on component-only scripts. Render <Script${pascal}> in your template to load the embed.`
|
|
1608
|
+
);
|
|
1609
|
+
}
|
|
1610
|
+
continue;
|
|
1611
|
+
}
|
|
1612
|
+
const willAutoLoad = scriptOptions && "trigger" in scriptOptions && scriptOptions.trigger !== false;
|
|
1613
|
+
if (willAutoLoad) {
|
|
1614
|
+
const requiredFields = extractRequiredFields(script.schema);
|
|
1615
|
+
const missing = requiredFields.filter((f) => !input[f]);
|
|
1616
|
+
if (missing.length) {
|
|
1617
|
+
logger.warn(`[nuxt-scripts] registry.${key}: missing required field${missing.length > 1 ? "s" : ""} ${missing.map((f) => `'${f}'`).join(", ")}. The script infrastructure is registered but will not function without ${missing.length > 1 ? "them" : "it"}.`);
|
|
1618
|
+
}
|
|
1540
1619
|
}
|
|
1541
1620
|
const envDefaultKeys = new Set(Object.keys(script.envDefaults || {}));
|
|
1542
1621
|
const userProvidedFields = Object.keys(input).filter((f) => !envDefaultKeys.has(f));
|
|
@@ -1649,7 +1728,7 @@ They will load directly from third-party servers.`
|
|
|
1649
1728
|
addPluginTemplate({
|
|
1650
1729
|
filename: "nuxt-scripts-intercept.client.mjs",
|
|
1651
1730
|
getContents() {
|
|
1652
|
-
return generateInterceptPluginContents(proxyPrefix);
|
|
1731
|
+
return generateInterceptPluginContents(proxyPrefix, { testMode: !!nuxt.options.test });
|
|
1653
1732
|
}
|
|
1654
1733
|
});
|
|
1655
1734
|
nuxt.options.runtimeConfig["nuxt-scripts-proxy"] = {
|
|
@@ -1661,12 +1740,12 @@ They will load directly from third-party servers.`
|
|
|
1661
1740
|
if (totalDomains > 0 && nuxt.options.dev) {
|
|
1662
1741
|
logger.success(`Proxy mode enabled for ${registryKeys.length} script(s), ${totalDomains} domain(s) proxied (privacy: ${privacyLabel})`);
|
|
1663
1742
|
}
|
|
1664
|
-
const
|
|
1665
|
-
const
|
|
1666
|
-
if (
|
|
1743
|
+
const proxyStaticPresets = ["static", "github-pages", "cloudflare-pages-static", "netlify-static", "azure-static", "firebase-static"];
|
|
1744
|
+
const proxyPreset = process.env.NITRO_PRESET || "";
|
|
1745
|
+
if (proxyStaticPresets.includes(proxyPreset)) {
|
|
1667
1746
|
logger.warn(
|
|
1668
|
-
`Proxy collection endpoints require a server runtime (detected: ${
|
|
1669
|
-
Scripts will be bundled, but collection requests will not be proxied.
|
|
1747
|
+
`Proxy collection endpoints require a server runtime (detected: ${proxyPreset || "static"}).
|
|
1748
|
+
Scripts will be bundled, but collection requests will not be proxied and URL signing will be unavailable.
|
|
1670
1749
|
Options: configure platform rewrites, switch to server-rendered mode, or disable with proxy: false.`
|
|
1671
1750
|
);
|
|
1672
1751
|
}
|
|
@@ -1713,6 +1792,7 @@ Options: configure platform rewrites, switch to server-rendered mode, or disable
|
|
|
1713
1792
|
});
|
|
1714
1793
|
const scriptsPrefix = config.prefix || "/_scripts";
|
|
1715
1794
|
const enabledEndpoints = {};
|
|
1795
|
+
let anyHandlerRequiresSigning = false;
|
|
1716
1796
|
for (const script of scripts) {
|
|
1717
1797
|
if (!script.serverHandlers?.length || !script.registryKey)
|
|
1718
1798
|
continue;
|
|
@@ -1721,11 +1801,14 @@ Options: configure platform rewrites, switch to server-rendered mode, or disable
|
|
|
1721
1801
|
continue;
|
|
1722
1802
|
enabledEndpoints[script.registryKey] = true;
|
|
1723
1803
|
for (const handler of script.serverHandlers) {
|
|
1804
|
+
const resolvedRoute = handler.route.replace("/_scripts", scriptsPrefix);
|
|
1724
1805
|
addServerHandler({
|
|
1725
|
-
route:
|
|
1806
|
+
route: resolvedRoute,
|
|
1726
1807
|
handler: handler.handler,
|
|
1727
1808
|
middleware: handler.middleware
|
|
1728
1809
|
});
|
|
1810
|
+
if (handler.requiresSigning)
|
|
1811
|
+
anyHandlerRequiresSigning = true;
|
|
1729
1812
|
}
|
|
1730
1813
|
if (script.registryKey === "gravatar") {
|
|
1731
1814
|
const gravatarConfig = config.registry?.gravatar?.[0] || {};
|
|
@@ -1745,7 +1828,45 @@ Options: configure platform rewrites, switch to server-rendered mode, or disable
|
|
|
1745
1828
|
{ endpoints: enabledEndpoints },
|
|
1746
1829
|
nuxt.options.runtimeConfig.public["nuxt-scripts"]
|
|
1747
1830
|
);
|
|
1831
|
+
const staticPresets = ["static", "github-pages", "cloudflare-pages-static", "netlify-static", "azure-static", "firebase-static"];
|
|
1832
|
+
const nitroPreset = process.env.NITRO_PRESET || "";
|
|
1833
|
+
const isStaticTarget = staticPresets.includes(nitroPreset);
|
|
1834
|
+
const isSpa = nuxt.options.ssr === false;
|
|
1835
|
+
if (anyHandlerRequiresSigning && (isSpa || isStaticTarget)) {
|
|
1836
|
+
logger.warn(
|
|
1837
|
+
`[security] URL signing requires a server runtime${isStaticTarget ? ` (detected preset: ${nitroPreset})` : " (ssr: false)"}.
|
|
1838
|
+
Proxy endpoints will work without signature verification.
|
|
1839
|
+
To enable signing, deploy with a server-rendered target or configure platform-level rewrites.`
|
|
1840
|
+
);
|
|
1841
|
+
} else if (anyHandlerRequiresSigning) {
|
|
1842
|
+
const proxySecretResolved = resolveProxySecret(
|
|
1843
|
+
nuxt.options.rootDir,
|
|
1844
|
+
!!nuxt.options.dev,
|
|
1845
|
+
config.security?.secret,
|
|
1846
|
+
config.security?.autoGenerateSecret !== false
|
|
1847
|
+
);
|
|
1848
|
+
if (proxySecretResolved?.source === "dotenv-generated")
|
|
1849
|
+
logger.info(`[security] Generated ${PROXY_SECRET_ENV_KEY} in .env for signed proxy URLs.`);
|
|
1850
|
+
else if (proxySecretResolved?.source === "memory-generated")
|
|
1851
|
+
logger.warn(`[security] Generated an in-memory ${PROXY_SECRET_ENV_KEY} (could not write .env). Signed URLs will break across restarts.`);
|
|
1852
|
+
if (proxySecretResolved?.secret) {
|
|
1853
|
+
const scriptsRuntime = nuxt.options.runtimeConfig["nuxt-scripts"];
|
|
1854
|
+
scriptsRuntime.proxySecret = proxySecretResolved.secret;
|
|
1855
|
+
if (config.security?.pageTokenMaxAge !== void 0)
|
|
1856
|
+
scriptsRuntime.pageTokenMaxAge = config.security.pageTokenMaxAge;
|
|
1857
|
+
addPlugin({
|
|
1858
|
+
src: await resolvePath("./runtime/plugins/proxy-token.server"),
|
|
1859
|
+
mode: "server"
|
|
1860
|
+
});
|
|
1861
|
+
} else if (!nuxt.options.dev) {
|
|
1862
|
+
logger.warn(
|
|
1863
|
+
`[security] ${PROXY_SECRET_ENV_KEY} is not set. Proxy endpoints will pass requests through without signature verification.
|
|
1864
|
+
Generate one with: npx @nuxt/scripts generate-secret
|
|
1865
|
+
Then set the env var: ${PROXY_SECRET_ENV_KEY}=<secret>`
|
|
1866
|
+
);
|
|
1867
|
+
}
|
|
1868
|
+
}
|
|
1748
1869
|
}
|
|
1749
1870
|
});
|
|
1750
1871
|
|
|
1751
|
-
export { applyAutoInject, module$1 as default, isProxyDisabled };
|
|
1872
|
+
export { applyAutoInject, module$1 as default, isProxyDisabled, resolveProxySecret };
|
package/dist/registry.d.mts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { ProxyPrivacyInput } from '../dist/runtime/server/utils/privacy.js';
|
|
2
2
|
import { ScriptCapabilities, RegistryScript, RegistryScriptKey, ProxyConfig, ProxyCapability, ProxyAutoInject, ResolvedProxyAutoInject } from '../dist/runtime/types.js';
|
|
3
|
+
export { ScriptCapabilities } from '../dist/runtime/types.js';
|
|
3
4
|
|
|
4
5
|
interface RegistryScriptMeta {
|
|
5
6
|
/** Registry key (e.g. 'plausibleAnalytics') */
|
package/dist/registry.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { ProxyPrivacyInput } from '../dist/runtime/server/utils/privacy.js';
|
|
2
2
|
import { ScriptCapabilities, RegistryScript, RegistryScriptKey, ProxyConfig, ProxyCapability, ProxyAutoInject, ResolvedProxyAutoInject } from '../dist/runtime/types.js';
|
|
3
|
+
export { ScriptCapabilities } from '../dist/runtime/types.js';
|
|
3
4
|
|
|
4
5
|
interface RegistryScriptMeta {
|
|
5
6
|
/** Registry key (e.g. 'plausibleAnalytics') */
|
package/dist/registry.mjs
CHANGED
|
@@ -126,7 +126,7 @@ const registryMeta = [
|
|
|
126
126
|
m("intercom", "Intercom", "support", "useScriptIntercom", { bundle: true, proxy: true }, PRIVACY_IP_ONLY),
|
|
127
127
|
m("crisp", "Crisp", "support", "useScriptCrisp", { bundle: true }, null),
|
|
128
128
|
// cdn
|
|
129
|
-
m("npm", "NPM", "cdn", "useScriptNpm", {}, null),
|
|
129
|
+
m("npm", "NPM", "cdn", "useScriptNpm", { bundle: true }, null),
|
|
130
130
|
// utility
|
|
131
131
|
m("googleRecaptcha", "Google reCAPTCHA", "utility", "useScriptGoogleRecaptcha", {}, null),
|
|
132
132
|
m("googleSignIn", "Google Sign-In", "utility", "useScriptGoogleSignIn", {}, null),
|
|
@@ -346,7 +346,7 @@ async function registry(resolve) {
|
|
|
346
346
|
return "https://cdn.mxpnl.com/libs/mixpanel-2-latest.min.js";
|
|
347
347
|
}
|
|
348
348
|
},
|
|
349
|
-
partytown: { forwards: ["mixpanel", "mixpanel.init", "mixpanel.track", "mixpanel.identify", "mixpanel.people.set", "mixpanel.reset", "mixpanel.register"] }
|
|
349
|
+
partytown: { forwards: ["mixpanel", "mixpanel.init", "mixpanel.track", "mixpanel.identify", "mixpanel.people.set", "mixpanel.reset", "mixpanel.register", "mixpanel.opt_in_tracking", "mixpanel.opt_out_tracking"] }
|
|
350
350
|
}),
|
|
351
351
|
// ad
|
|
352
352
|
def("bingUet", {
|
|
@@ -401,7 +401,7 @@ async function registry(resolve) {
|
|
|
401
401
|
domains: ["analytics.tiktok.com", "mon.tiktok.com", "mcs.tiktok.com"],
|
|
402
402
|
privacy: PRIVACY_FULL
|
|
403
403
|
},
|
|
404
|
-
partytown: { forwards: ["ttq.track", "ttq.page", "ttq.identify"] }
|
|
404
|
+
partytown: { forwards: ["ttq.track", "ttq.page", "ttq.identify", "ttq.grantConsent", "ttq.revokeConsent", "ttq.holdConsent"] }
|
|
405
405
|
}),
|
|
406
406
|
def("snapchatPixel", {
|
|
407
407
|
schema: SnapTrPixelOptions,
|
|
@@ -503,7 +503,7 @@ async function registry(resolve) {
|
|
|
503
503
|
domains: ["www.clarity.ms", "scripts.clarity.ms", "d.clarity.ms", "e.clarity.ms", "k.clarity.ms", "c.clarity.ms", "a.clarity.ms", "b.clarity.ms"],
|
|
504
504
|
privacy: PRIVACY_HEATMAP
|
|
505
505
|
},
|
|
506
|
-
partytown: { forwards: [] }
|
|
506
|
+
partytown: { forwards: ["clarity"] }
|
|
507
507
|
}),
|
|
508
508
|
// payments
|
|
509
509
|
def("stripe", {
|
|
@@ -554,8 +554,8 @@ async function registry(resolve) {
|
|
|
554
554
|
envDefaults: { apiKey: "" },
|
|
555
555
|
category: "content",
|
|
556
556
|
serverHandlers: [
|
|
557
|
-
{ route: "/_scripts/proxy/google-static-maps", handler: "./runtime/server/google-static-maps-proxy" },
|
|
558
|
-
{ route: "/_scripts/proxy/google-maps-geocode", handler: "./runtime/server/google-maps-geocode-proxy" }
|
|
557
|
+
{ route: "/_scripts/proxy/google-static-maps", handler: "./runtime/server/google-static-maps-proxy", requiresSigning: true },
|
|
558
|
+
{ route: "/_scripts/proxy/google-maps-geocode", handler: "./runtime/server/google-maps-geocode-proxy", requiresSigning: true }
|
|
559
559
|
]
|
|
560
560
|
}),
|
|
561
561
|
def("blueskyEmbed", {
|
|
@@ -564,8 +564,8 @@ async function registry(resolve) {
|
|
|
564
564
|
label: "Bluesky Embed",
|
|
565
565
|
category: "content",
|
|
566
566
|
serverHandlers: [
|
|
567
|
-
{ route: "/_scripts/embed/bluesky", handler: "./runtime/server/bluesky-embed" },
|
|
568
|
-
{ route: "/_scripts/embed/bluesky-image", handler: "./runtime/server/bluesky-embed-image" }
|
|
567
|
+
{ route: "/_scripts/embed/bluesky", handler: "./runtime/server/bluesky-embed", requiresSigning: true },
|
|
568
|
+
{ route: "/_scripts/embed/bluesky-image", handler: "./runtime/server/bluesky-embed-image", requiresSigning: true }
|
|
569
569
|
]
|
|
570
570
|
}),
|
|
571
571
|
def("instagramEmbed", {
|
|
@@ -574,9 +574,9 @@ async function registry(resolve) {
|
|
|
574
574
|
label: "Instagram Embed",
|
|
575
575
|
category: "content",
|
|
576
576
|
serverHandlers: [
|
|
577
|
-
{ route: "/_scripts/embed/instagram", handler: "./runtime/server/instagram-embed" },
|
|
578
|
-
{ route: "/_scripts/embed/instagram-image", handler: "./runtime/server/instagram-embed-image" },
|
|
579
|
-
{ route: "/_scripts/embed/instagram-asset", handler: "./runtime/server/instagram-embed-asset" }
|
|
577
|
+
{ route: "/_scripts/embed/instagram", handler: "./runtime/server/instagram-embed", requiresSigning: true },
|
|
578
|
+
{ route: "/_scripts/embed/instagram-image", handler: "./runtime/server/instagram-embed-image", requiresSigning: true },
|
|
579
|
+
{ route: "/_scripts/embed/instagram-asset", handler: "./runtime/server/instagram-embed-asset", requiresSigning: true }
|
|
580
580
|
]
|
|
581
581
|
}),
|
|
582
582
|
def("xEmbed", {
|
|
@@ -585,8 +585,8 @@ async function registry(resolve) {
|
|
|
585
585
|
label: "X Embed",
|
|
586
586
|
category: "content",
|
|
587
587
|
serverHandlers: [
|
|
588
|
-
{ route: "/_scripts/embed/x", handler: "./runtime/server/x-embed" },
|
|
589
|
-
{ route: "/_scripts/embed/x-image", handler: "./runtime/server/x-embed-image" }
|
|
588
|
+
{ route: "/_scripts/embed/x", handler: "./runtime/server/x-embed", requiresSigning: true },
|
|
589
|
+
{ route: "/_scripts/embed/x-image", handler: "./runtime/server/x-embed-image", requiresSigning: true }
|
|
590
590
|
]
|
|
591
591
|
}),
|
|
592
592
|
// support
|
|
@@ -690,7 +690,7 @@ async function registry(resolve) {
|
|
|
690
690
|
privacy: PRIVACY_IP_ONLY
|
|
691
691
|
},
|
|
692
692
|
serverHandlers: [
|
|
693
|
-
{ route: "/_scripts/proxy/gravatar", handler: "./runtime/server/gravatar-proxy" }
|
|
693
|
+
{ route: "/_scripts/proxy/gravatar", handler: "./runtime/server/gravatar-proxy", requiresSigning: true }
|
|
694
694
|
]
|
|
695
695
|
})
|
|
696
696
|
]);
|