@nuxt/scripts 0.13.2 → 1.0.0-beta.12
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 +15 -0
- package/dist/client/200.html +1 -1
- package/dist/client/404.html +1 -1
- package/dist/client/_nuxt/48AF9EJD.js +1 -0
- package/dist/client/_nuxt/Bk6ed9rg.js +1 -0
- package/dist/client/_nuxt/C4Cj8gBr.js +162 -0
- package/dist/client/_nuxt/{Bje-0OHL.js → DP0kj6Xn.js} +1 -1
- package/dist/client/_nuxt/builds/latest.json +1 -1
- package/dist/client/_nuxt/builds/meta/919b81d8-ed3a-4222-8a40-df0031cc3b99.json +1 -0
- package/dist/client/_nuxt/entry.D45OuV0w.css +1 -0
- package/dist/client/_nuxt/error-404.B57D-jUQ.css +1 -0
- package/dist/client/_nuxt/error-500.DTHUW7BI.css +1 -0
- package/dist/client/index.html +1 -1
- package/dist/module.d.mts +113 -4
- package/dist/module.d.ts +176 -0
- package/dist/module.json +1 -1
- package/dist/module.mjs +780 -299
- package/dist/registry.d.ts +6 -0
- package/dist/registry.mjs +94 -18
- package/dist/runtime/components/GoogleMaps/ScriptGoogleMaps.d.vue.ts +30 -2
- package/dist/runtime/components/GoogleMaps/ScriptGoogleMaps.vue +40 -15
- package/dist/runtime/components/GoogleMaps/ScriptGoogleMaps.vue.d.ts +30 -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 +21 -9
- package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsMarkerClusterer.vue +8 -8
- package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsMarkerClusterer.vue.d.ts +21 -9
- package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsPinElement.vue +11 -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.d.vue.ts +1 -1
- package/dist/runtime/components/ScriptCrisp.vue +1 -1
- package/dist/runtime/components/ScriptCrisp.vue.d.ts +1 -1
- package/dist/runtime/components/ScriptGoogleAdsense.vue +1 -1
- package/dist/runtime/components/ScriptInstagramEmbed.d.vue.ts +53 -0
- package/dist/runtime/components/ScriptInstagramEmbed.vue +38 -0
- package/dist/runtime/components/ScriptInstagramEmbed.vue.d.ts +53 -0
- package/dist/runtime/components/ScriptIntercom.d.vue.ts +1 -1
- package/dist/runtime/components/ScriptIntercom.vue +4 -3
- package/dist/runtime/components/ScriptIntercom.vue.d.ts +1 -1
- package/dist/runtime/components/ScriptPayPalButtons.d.vue.ts +2 -2
- package/dist/runtime/components/ScriptPayPalButtons.vue +13 -11
- package/dist/runtime/components/ScriptPayPalButtons.vue.d.ts +2 -2
- package/dist/runtime/components/ScriptPayPalMarks.d.vue.ts +2 -2
- package/dist/runtime/components/ScriptPayPalMarks.vue +10 -8
- package/dist/runtime/components/ScriptPayPalMarks.vue.d.ts +2 -2
- package/dist/runtime/components/ScriptPayPalMessages.d.vue.ts +2 -2
- package/dist/runtime/components/ScriptPayPalMessages.vue +11 -9
- package/dist/runtime/components/ScriptPayPalMessages.vue.d.ts +2 -2
- package/dist/runtime/components/ScriptStripePricingTable.vue +2 -2
- package/dist/runtime/components/ScriptVimeoPlayer.d.vue.ts +2 -2
- package/dist/runtime/components/ScriptVimeoPlayer.vue +1 -1
- package/dist/runtime/components/ScriptVimeoPlayer.vue.d.ts +2 -2
- package/dist/runtime/components/ScriptXEmbed.d.vue.ts +82 -0
- package/dist/runtime/components/ScriptXEmbed.vue +76 -0
- package/dist/runtime/components/ScriptXEmbed.vue.d.ts +82 -0
- package/dist/runtime/components/ScriptYouTubePlayer.d.vue.ts +12 -1
- package/dist/runtime/components/ScriptYouTubePlayer.vue +44 -16
- package/dist/runtime/components/ScriptYouTubePlayer.vue.d.ts +12 -1
- package/dist/runtime/composables/useScript.js +36 -5
- 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/composables/useScriptTriggerServiceWorker.d.ts +7 -0
- package/dist/runtime/composables/useScriptTriggerServiceWorker.js +39 -0
- package/dist/runtime/npm-script-stub.d.ts +20 -0
- package/dist/runtime/npm-script-stub.js +73 -0
- package/dist/runtime/registry/clarity.js +21 -25
- package/dist/runtime/registry/cloudflare-web-analytics.js +1 -1
- package/dist/runtime/registry/crisp.js +1 -1
- package/dist/runtime/registry/databuddy-analytics.js +1 -1
- package/dist/runtime/registry/fathom-analytics.js +1 -1
- package/dist/runtime/registry/google-adsense.js +1 -1
- package/dist/runtime/registry/google-analytics.js +2 -2
- package/dist/runtime/registry/google-maps.d.ts +1 -1
- package/dist/runtime/registry/google-maps.js +1 -1
- package/dist/runtime/registry/google-recaptcha.d.ts +27 -0
- package/dist/runtime/registry/google-recaptcha.js +45 -0
- package/dist/runtime/registry/google-sign-in.d.ts +84 -0
- package/dist/runtime/registry/google-sign-in.js +50 -0
- package/dist/runtime/registry/google-tag-manager.d.ts +4 -2
- package/dist/runtime/registry/google-tag-manager.js +16 -6
- package/dist/runtime/registry/hotjar.js +1 -1
- package/dist/runtime/registry/instagram-embed.d.ts +23 -0
- package/dist/runtime/registry/instagram-embed.js +22 -0
- package/dist/runtime/registry/intercom.js +1 -1
- package/dist/runtime/registry/lemon-squeezy.d.ts +0 -1
- package/dist/runtime/registry/matomo-analytics.js +3 -3
- package/dist/runtime/registry/meta-pixel.js +1 -1
- package/dist/runtime/registry/npm.js +1 -1
- package/dist/runtime/registry/paypal.d.ts +1 -1
- package/dist/runtime/registry/paypal.js +2 -2
- package/dist/runtime/registry/plausible-analytics.js +21 -13
- package/dist/runtime/registry/posthog.d.ts +27 -0
- package/dist/runtime/registry/posthog.js +88 -0
- package/dist/runtime/registry/reddit-pixel.js +1 -1
- package/dist/runtime/registry/rybbit-analytics.js +41 -9
- package/dist/runtime/registry/segment.js +1 -1
- package/dist/runtime/registry/snapchat-pixel.js +1 -1
- package/dist/runtime/registry/stripe.d.ts +1 -1
- package/dist/runtime/registry/stripe.js +1 -1
- package/dist/runtime/registry/tiktok-pixel.d.ts +44 -0
- package/dist/runtime/registry/tiktok-pixel.js +44 -0
- package/dist/runtime/registry/umami-analytics.js +1 -1
- 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 +77 -0
- package/dist/runtime/registry/x-embed.js +41 -0
- package/dist/runtime/registry/x-pixel.js +1 -1
- 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.d.ts +2 -0
- package/dist/runtime/server/google-static-maps-proxy.js +54 -0
- package/dist/runtime/server/instagram-embed-asset.d.ts +2 -0
- package/dist/runtime/server/instagram-embed-asset.js +42 -0
- package/dist/runtime/server/instagram-embed-image.d.ts +2 -0
- package/dist/runtime/server/instagram-embed-image.js +54 -0
- package/dist/runtime/server/instagram-embed.d.ts +2 -0
- package/dist/runtime/server/instagram-embed.js +91 -0
- package/dist/runtime/server/proxy-handler.d.ts +6 -0
- package/dist/runtime/server/proxy-handler.js +264 -0
- package/dist/runtime/server/utils/privacy.d.ts +141 -0
- package/dist/runtime/server/utils/privacy.js +324 -0
- package/dist/runtime/server/x-embed-image.d.ts +2 -0
- package/dist/runtime/server/x-embed-image.js +53 -0
- package/dist/runtime/server/x-embed.d.ts +49 -0
- package/dist/runtime/server/x-embed.js +31 -0
- package/dist/runtime/types.d.ts +61 -20
- package/dist/runtime/utils/pure.d.ts +9 -0
- package/dist/runtime/utils/pure.js +0 -0
- package/dist/runtime/utils.d.ts +5 -4
- package/dist/runtime/utils.js +12 -2
- package/dist/shared/scripts.DLRgvHQg.mjs +288 -0
- package/dist/stats.d.mts +39 -0
- package/dist/stats.d.ts +39 -0
- package/dist/stats.mjs +711 -0
- package/dist/types.d.mts +1 -1
- package/package.json +59 -46
- package/dist/client/_nuxt/DMut0W-e.js +0 -162
- package/dist/client/_nuxt/builds/meta/5e0206fe-a683-423c-8d59-2596d0b16fee.json +0 -1
- package/dist/client/_nuxt/entry.BjfcJo5q.css +0 -1
- package/dist/client/_nuxt/error-404.B0ZhSNwd.css +0 -1
- package/dist/client/_nuxt/error-500.D4MdgPaC.css +0 -1
- package/dist/client/_nuxt/iNmKC7TZ.js +0 -1
- package/dist/client/_nuxt/rttsH3SL.js +0 -1
package/dist/module.mjs
CHANGED
|
@@ -1,78 +1,36 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { existsSync, readdirSync, readFileSync } from 'node:fs';
|
|
2
|
+
import { useNuxt, addDevServerHandler, extendRouteRules, tryUseNuxt, extendViteConfig, logger as logger$1, useLogger, addTypeTemplate, defineNuxtModule, createResolver, hasNuxtModule, addImports, addComponentsDir, addTemplate, addPluginTemplate, addServerHandler, addBuildPlugin } from '@nuxt/kit';
|
|
2
3
|
import { defu } from 'defu';
|
|
3
|
-
import { resolvePackageJSON, readPackageJSON } from 'pkg-types';
|
|
4
|
-
import { existsSync } from 'node:fs';
|
|
5
|
-
import fsp from 'node:fs/promises';
|
|
6
|
-
import { createUnplugin } from 'unplugin';
|
|
7
|
-
import MagicString from 'magic-string';
|
|
8
|
-
import { asyncWalk, walk } from 'estree-walker';
|
|
9
|
-
import { joinURL, parseURL, parseQuery, hasProtocol } from 'ufo';
|
|
10
|
-
import { hash } from 'ohash';
|
|
11
4
|
import { join, resolve, relative } from 'pathe';
|
|
12
|
-
import {
|
|
13
|
-
import { fetch, $fetch } from 'ofetch';
|
|
5
|
+
import { resolvePackageJSON, readPackageJSON } from 'pkg-types';
|
|
14
6
|
import { lazyEventHandler, eventHandler, createError } from 'h3';
|
|
7
|
+
import { fetch, $fetch } from 'ofetch';
|
|
8
|
+
import { joinURL, parseURL, parseQuery, hasProtocol } from 'ufo';
|
|
15
9
|
import { createStorage } from 'unstorage';
|
|
16
10
|
import fsDriver from 'unstorage/drivers/fs-lite';
|
|
17
|
-
import {
|
|
11
|
+
import { addCustomTab } from '@nuxt/devtools-kit';
|
|
18
12
|
import { isCI, provider } from 'std-env';
|
|
13
|
+
import { parseAndWalk } from 'oxc-walker';
|
|
14
|
+
import { createUnplugin } from 'unplugin';
|
|
15
|
+
import { pathToFileURL } from 'node:url';
|
|
16
|
+
import { createHash } from 'node:crypto';
|
|
17
|
+
import fsp from 'node:fs/promises';
|
|
18
|
+
import { colors } from 'consola/utils';
|
|
19
|
+
import MagicString from 'magic-string';
|
|
20
|
+
import { hash } from 'ohash';
|
|
21
|
+
import { a as getProxyConfig, g as getAllProxyConfigs, r as routesToInterceptRules } from './shared/scripts.DLRgvHQg.mjs';
|
|
19
22
|
import { registry } from './registry.mjs';
|
|
20
23
|
|
|
21
|
-
const DEVTOOLS_UI_ROUTE = "/__nuxt-scripts";
|
|
22
|
-
const DEVTOOLS_UI_LOCAL_PORT = 3300;
|
|
23
|
-
|
|
24
|
-
async function setupDevToolsUI(options, resolve, nuxt = useNuxt()) {
|
|
25
|
-
const clientPath = await resolve("./client");
|
|
26
|
-
const isProductionBuild = existsSync(clientPath);
|
|
27
|
-
if (isProductionBuild) {
|
|
28
|
-
nuxt.hook("vite:serverCreated", async (server) => {
|
|
29
|
-
const sirv = await import('sirv').then((r) => r.default || r);
|
|
30
|
-
server.middlewares.use(
|
|
31
|
-
DEVTOOLS_UI_ROUTE,
|
|
32
|
-
sirv(clientPath, { dev: true, single: true })
|
|
33
|
-
);
|
|
34
|
-
});
|
|
35
|
-
} else {
|
|
36
|
-
extendViteConfig((config) => {
|
|
37
|
-
config.server = config.server || {};
|
|
38
|
-
config.server.proxy = config.server.proxy || {};
|
|
39
|
-
config.server.proxy[DEVTOOLS_UI_ROUTE] = {
|
|
40
|
-
target: `http://localhost:${DEVTOOLS_UI_LOCAL_PORT}${DEVTOOLS_UI_ROUTE}`,
|
|
41
|
-
changeOrigin: true,
|
|
42
|
-
followRedirects: true,
|
|
43
|
-
rewrite: (path) => path.replace(DEVTOOLS_UI_ROUTE, "")
|
|
44
|
-
};
|
|
45
|
-
});
|
|
46
|
-
}
|
|
47
|
-
nuxt.hook("devtools:customTabs", (tabs) => {
|
|
48
|
-
tabs.push({
|
|
49
|
-
// unique identifier
|
|
50
|
-
name: "nuxt-scripts",
|
|
51
|
-
// title to display in the tab
|
|
52
|
-
title: "Scripts",
|
|
53
|
-
// any icon from Iconify, or a URL to an image
|
|
54
|
-
icon: "carbon:script",
|
|
55
|
-
// iframe view
|
|
56
|
-
view: {
|
|
57
|
-
type: "iframe",
|
|
58
|
-
src: DEVTOOLS_UI_ROUTE
|
|
59
|
-
}
|
|
60
|
-
});
|
|
61
|
-
});
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
const logger = useLogger("@nuxt/scripts");
|
|
65
|
-
|
|
66
24
|
const renderedScript = /* @__PURE__ */ new Map();
|
|
67
25
|
const ONE_YEAR_IN_SECONDS = 60 * 60 * 24 * 365;
|
|
68
|
-
|
|
26
|
+
function bundleStorage() {
|
|
69
27
|
const nuxt = tryUseNuxt();
|
|
70
28
|
return createStorage({
|
|
71
29
|
driver: fsDriver({
|
|
72
30
|
base: resolve(nuxt?.options.rootDir || "", "node_modules/.cache/nuxt/scripts")
|
|
73
31
|
})
|
|
74
32
|
});
|
|
75
|
-
}
|
|
33
|
+
}
|
|
76
34
|
function setupPublicAssetStrategy(options = {}) {
|
|
77
35
|
const assetsBaseURL = options.prefix || "/_scripts";
|
|
78
36
|
const nuxt = useNuxt();
|
|
@@ -85,6 +43,9 @@ function setupPublicAssetStrategy(options = {}) {
|
|
|
85
43
|
const scriptDescriptor = renderedScript.get(join(assetsBaseURL, event.path.slice(1)));
|
|
86
44
|
if (!scriptDescriptor || scriptDescriptor instanceof Error)
|
|
87
45
|
throw createError({ statusCode: 404 });
|
|
46
|
+
if (scriptDescriptor.content) {
|
|
47
|
+
return scriptDescriptor.content;
|
|
48
|
+
}
|
|
88
49
|
const key = `bundle:${filename}`;
|
|
89
50
|
let res = await storage.getItemRaw(key);
|
|
90
51
|
if (!res) {
|
|
@@ -96,31 +57,112 @@ function setupPublicAssetStrategy(options = {}) {
|
|
|
96
57
|
})
|
|
97
58
|
});
|
|
98
59
|
if (nuxt.options.dev) {
|
|
99
|
-
|
|
100
|
-
nuxt.options.routeRules[joinURL(assetsBaseURL, "**")] = {
|
|
60
|
+
extendRouteRules(joinURL(assetsBaseURL, "**"), {
|
|
101
61
|
cache: {
|
|
102
62
|
maxAge: ONE_YEAR_IN_SECONDS
|
|
103
63
|
}
|
|
104
|
-
};
|
|
64
|
+
});
|
|
105
65
|
}
|
|
106
|
-
nuxt.options.nitro.publicAssets ||= [];
|
|
107
66
|
const cacheDir = join(nuxt.options.buildDir, "cache", "scripts");
|
|
108
|
-
nuxt.
|
|
109
|
-
|
|
110
|
-
publicAssets
|
|
67
|
+
nuxt.hook("nitro:config", (nitroConfig) => {
|
|
68
|
+
nitroConfig.publicAssets ||= [];
|
|
69
|
+
nitroConfig.publicAssets.push({
|
|
111
70
|
dir: cacheDir,
|
|
112
71
|
maxAge: ONE_YEAR_IN_SECONDS,
|
|
113
72
|
baseURL: assetsBaseURL
|
|
114
|
-
}
|
|
115
|
-
prerender
|
|
116
|
-
|
|
117
|
-
|
|
73
|
+
});
|
|
74
|
+
nitroConfig.prerender ||= {};
|
|
75
|
+
nitroConfig.prerender.ignore ||= [];
|
|
76
|
+
nitroConfig.prerender.ignore.push(assetsBaseURL);
|
|
118
77
|
});
|
|
119
78
|
return {
|
|
120
79
|
renderedScript
|
|
121
80
|
};
|
|
122
81
|
}
|
|
123
82
|
|
|
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 isStackblitz = provider === "stackblitz";
|
|
125
|
+
async function promptToInstall(name, installCommand, options) {
|
|
126
|
+
if (await resolvePackageJSON(name).catch(() => null))
|
|
127
|
+
return true;
|
|
128
|
+
logger$1.info(`Package ${name} is missing`);
|
|
129
|
+
if (isCI)
|
|
130
|
+
return false;
|
|
131
|
+
if (options.prompt === true || options.prompt !== false && !isStackblitz) {
|
|
132
|
+
const confirm = await logger$1.prompt(`Do you want to install ${name} package?`, {
|
|
133
|
+
type: "confirm",
|
|
134
|
+
name: "confirm",
|
|
135
|
+
initial: true
|
|
136
|
+
});
|
|
137
|
+
if (!confirm)
|
|
138
|
+
return false;
|
|
139
|
+
}
|
|
140
|
+
logger$1.info(`Installing ${name}...`);
|
|
141
|
+
try {
|
|
142
|
+
await installCommand();
|
|
143
|
+
logger$1.success(`Installed ${name}`);
|
|
144
|
+
return true;
|
|
145
|
+
} catch (err) {
|
|
146
|
+
logger$1.error(err);
|
|
147
|
+
return false;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
const installPrompts = /* @__PURE__ */ new Set();
|
|
151
|
+
function installNuxtModule(name, options) {
|
|
152
|
+
if (installPrompts.has(name))
|
|
153
|
+
return;
|
|
154
|
+
installPrompts.add(name);
|
|
155
|
+
const nuxt = tryUseNuxt();
|
|
156
|
+
if (!nuxt)
|
|
157
|
+
return;
|
|
158
|
+
return promptToInstall(name, async () => {
|
|
159
|
+
const { runCommand } = await import(String("nuxi"));
|
|
160
|
+
await runCommand("module", ["add", name, "--cwd", nuxt.options.rootDir]);
|
|
161
|
+
}, { rootDir: nuxt.options.rootDir, searchPaths: nuxt.options.modulesDir, ...options });
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
const logger = useLogger("@nuxt/scripts");
|
|
165
|
+
|
|
124
166
|
function isVue(id, opts = {}) {
|
|
125
167
|
const { search } = parseURL(decodeURIComponent(pathToFileURL(id).href));
|
|
126
168
|
if (id.endsWith(".vue") && !search) {
|
|
@@ -148,7 +190,178 @@ function isJS(id) {
|
|
|
148
190
|
return JS_RE.test(pathname);
|
|
149
191
|
}
|
|
150
192
|
|
|
193
|
+
function NuxtScriptsCheckScripts() {
|
|
194
|
+
return createUnplugin(() => {
|
|
195
|
+
return {
|
|
196
|
+
name: "nuxt-scripts:check-scripts",
|
|
197
|
+
transform: {
|
|
198
|
+
filter: {
|
|
199
|
+
id: /\.vue/
|
|
200
|
+
},
|
|
201
|
+
handler(code, id) {
|
|
202
|
+
if (!isVue(id, { type: ["script"] }))
|
|
203
|
+
return;
|
|
204
|
+
if (!code.includes("useScript"))
|
|
205
|
+
return;
|
|
206
|
+
let nameNode;
|
|
207
|
+
let errorNode;
|
|
208
|
+
parseAndWalk(code, id, (_node) => {
|
|
209
|
+
if (_node.type === "VariableDeclaration" && _node.declarations?.[0]?.id?.type === "ObjectPattern") {
|
|
210
|
+
const objPattern = _node.declarations[0]?.id;
|
|
211
|
+
for (const property of objPattern.properties) {
|
|
212
|
+
if (property.type === "Property" && property.key.type === "Identifier" && property.key.name === "$script" && property.value.type === "Identifier") {
|
|
213
|
+
nameNode = _node;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
if (nameNode) {
|
|
218
|
+
let sequence = _node.type === "SequenceExpression" ? _node : null;
|
|
219
|
+
let assignmentExpression;
|
|
220
|
+
if (_node.type === "VariableDeclaration") {
|
|
221
|
+
if (_node.declarations[0]?.init?.type === "SequenceExpression") {
|
|
222
|
+
sequence = _node.declarations[0]?.init;
|
|
223
|
+
assignmentExpression = _node.declarations[0]?.init?.expressions?.[0];
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
if (sequence && !assignmentExpression) {
|
|
227
|
+
assignmentExpression = sequence.expressions[0]?.type === "AssignmentExpression" ? sequence.expressions[0] : null;
|
|
228
|
+
}
|
|
229
|
+
if (assignmentExpression) {
|
|
230
|
+
const right = assignmentExpression?.right;
|
|
231
|
+
if (right.callee?.name === "_withAsyncContext") {
|
|
232
|
+
if (right.arguments[0]?.body?.name === "$script" || right.arguments[0]?.body?.callee?.object?.name === "$script") {
|
|
233
|
+
errorNode = nameNode;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
});
|
|
239
|
+
if (errorNode) {
|
|
240
|
+
return this.error(new Error("You can't use a top-level await on $script as it will never resolve."));
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
};
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
function isPropertyKeyAST(parent, ctx) {
|
|
249
|
+
return parent?.type === "Property" && ctx.key === "key" || parent?.type === "SwitchCase" && ctx.key === "test";
|
|
250
|
+
}
|
|
251
|
+
function matchAndRewrite(value, rewrites) {
|
|
252
|
+
for (const { from, to } of rewrites) {
|
|
253
|
+
const isSuffixMatch = from.startsWith(".");
|
|
254
|
+
const fromSlashIdx = from.indexOf("/");
|
|
255
|
+
const fromHost = fromSlashIdx > 0 ? from.slice(0, fromSlashIdx) : from;
|
|
256
|
+
const fromPath = fromSlashIdx > 0 ? from.slice(fromSlashIdx) : "";
|
|
257
|
+
if (!value.includes(fromHost))
|
|
258
|
+
continue;
|
|
259
|
+
const url = parseURL(value);
|
|
260
|
+
let shouldRewrite = false;
|
|
261
|
+
let rewriteSuffix = "";
|
|
262
|
+
if (url.host) {
|
|
263
|
+
const hostMatches = isSuffixMatch ? url.host.endsWith(fromHost) : url.host === fromHost;
|
|
264
|
+
if (hostMatches) {
|
|
265
|
+
const fullPath = url.pathname + (url.search || "") + (url.hash || "");
|
|
266
|
+
if (fromPath && fullPath.startsWith(fromPath)) {
|
|
267
|
+
shouldRewrite = true;
|
|
268
|
+
rewriteSuffix = fullPath.slice(fromPath.length);
|
|
269
|
+
} else if (!fromPath) {
|
|
270
|
+
shouldRewrite = true;
|
|
271
|
+
rewriteSuffix = fullPath;
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
} else if (value.startsWith("//")) {
|
|
275
|
+
const hostPart = value.slice(2).split("/")[0];
|
|
276
|
+
const hostMatches = isSuffixMatch ? hostPart?.endsWith(fromHost) ?? false : hostPart === fromHost;
|
|
277
|
+
if (hostMatches) {
|
|
278
|
+
const remainder = value.slice(2 + (hostPart?.length ?? 0));
|
|
279
|
+
if (fromPath && remainder.startsWith(fromPath)) {
|
|
280
|
+
shouldRewrite = true;
|
|
281
|
+
rewriteSuffix = remainder.slice(fromPath.length);
|
|
282
|
+
} else if (!fromPath) {
|
|
283
|
+
shouldRewrite = true;
|
|
284
|
+
rewriteSuffix = remainder;
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
} else if (fromPath && (value.startsWith(from) || isSuffixMatch && value.includes(from))) {
|
|
288
|
+
const domainEnd = value.indexOf(from) + from.length;
|
|
289
|
+
const nextChar = value[domainEnd];
|
|
290
|
+
if (!nextChar || nextChar === "/" || nextChar === "?" || nextChar === "#") {
|
|
291
|
+
shouldRewrite = true;
|
|
292
|
+
rewriteSuffix = value.slice(domainEnd);
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
if (shouldRewrite) {
|
|
296
|
+
return rewriteSuffix === "/" || rewriteSuffix.startsWith("?") || rewriteSuffix.startsWith("#") ? to + rewriteSuffix : joinURL(to, rewriteSuffix);
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
return null;
|
|
300
|
+
}
|
|
301
|
+
function rewriteScriptUrlsAST(content, filename, rewrites) {
|
|
302
|
+
const s = new MagicString(content);
|
|
303
|
+
parseAndWalk(content, filename, (node, parent, ctx) => {
|
|
304
|
+
if (node.type === "Literal" && typeof node.value === "string") {
|
|
305
|
+
const value = node.value;
|
|
306
|
+
const rewritten = matchAndRewrite(value, rewrites);
|
|
307
|
+
if (rewritten === null)
|
|
308
|
+
return;
|
|
309
|
+
const quote = content[node.start];
|
|
310
|
+
if (isPropertyKeyAST(parent, ctx)) {
|
|
311
|
+
s.overwrite(node.start, node.end, quote + rewritten + quote);
|
|
312
|
+
} else {
|
|
313
|
+
s.overwrite(node.start, node.end, `self.location.origin+${quote}${rewritten}${quote}`);
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
if (node.type === "TemplateLiteral" && node.expressions?.length === 0) {
|
|
317
|
+
const quasis = node.quasis;
|
|
318
|
+
if (quasis?.length === 1) {
|
|
319
|
+
const value = quasis[0].value?.cooked ?? quasis[0].value?.raw;
|
|
320
|
+
if (typeof value !== "string")
|
|
321
|
+
return;
|
|
322
|
+
const rewritten = matchAndRewrite(value, rewrites);
|
|
323
|
+
if (rewritten === null)
|
|
324
|
+
return;
|
|
325
|
+
if (isPropertyKeyAST(parent, ctx)) {
|
|
326
|
+
s.overwrite(node.start, node.end, `\`${rewritten}\``);
|
|
327
|
+
} else {
|
|
328
|
+
s.overwrite(node.start, node.end, `self.location.origin+\`${rewritten}\``);
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
if (node.type === "CallExpression") {
|
|
333
|
+
const callee = node.callee;
|
|
334
|
+
if (callee?.type === "MemberExpression" && !callee.computed && callee.object?.type === "Identifier" && callee.object.name === "navigator" && callee.property?.name === "sendBeacon") {
|
|
335
|
+
s.overwrite(callee.start, callee.end, "__nuxtScripts.sendBeacon");
|
|
336
|
+
}
|
|
337
|
+
if (callee?.type === "Identifier" && callee.name === "fetch") {
|
|
338
|
+
s.overwrite(callee.start, callee.end, "__nuxtScripts.fetch");
|
|
339
|
+
}
|
|
340
|
+
if (callee?.type === "MemberExpression" && !callee.computed && callee.object?.type === "Identifier" && (callee.object.name === "window" || callee.object.name === "self" || callee.object.name === "globalThis") && callee.property?.name === "fetch") {
|
|
341
|
+
s.overwrite(callee.start, callee.end, "__nuxtScripts.fetch");
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
});
|
|
345
|
+
let output = s.toString();
|
|
346
|
+
const gaRewrite = rewrites.find((r) => r.from.includes("google-analytics.com/g/collect"));
|
|
347
|
+
if (gaRewrite) {
|
|
348
|
+
output = output.replace(
|
|
349
|
+
/"https:\/\/"\+\(.*?\)\+"\.google-analytics\.com\/g\/collect"/g,
|
|
350
|
+
`self.location.origin+"${gaRewrite.to}"`
|
|
351
|
+
);
|
|
352
|
+
output = output.replace(
|
|
353
|
+
/"https:\/\/"\+\(.*?\)\+"\.analytics\.google\.com\/g\/collect"/g,
|
|
354
|
+
`self.location.origin+"${gaRewrite.to}"`
|
|
355
|
+
);
|
|
356
|
+
}
|
|
357
|
+
return output;
|
|
358
|
+
}
|
|
359
|
+
|
|
151
360
|
const SEVEN_DAYS_IN_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
361
|
+
function calculateIntegrity(content, algorithm = "sha384") {
|
|
362
|
+
const hash = createHash(algorithm).update(content).digest("base64");
|
|
363
|
+
return `${algorithm}-${hash}`;
|
|
364
|
+
}
|
|
152
365
|
async function isCacheExpired(storage, filename, cacheMaxAge = SEVEN_DAYS_IN_MS) {
|
|
153
366
|
const metaKey = `bundle-meta:${filename}`;
|
|
154
367
|
const meta = await storage.getItem(metaKey);
|
|
@@ -161,10 +374,8 @@ function normalizeScriptData(src, assetsBaseURL = "/_scripts") {
|
|
|
161
374
|
if (hasProtocol(src, { acceptRelative: true })) {
|
|
162
375
|
src = src.replace(/^\/\//, "https://");
|
|
163
376
|
const url = parseURL(src);
|
|
164
|
-
const
|
|
165
|
-
|
|
166
|
-
// force an extension
|
|
167
|
-
].filter(Boolean).join("-");
|
|
377
|
+
const h = hash(url);
|
|
378
|
+
const file = `${h.startsWith("-") ? `_${h.slice(1)}` : h}.js`;
|
|
168
379
|
const nuxt = tryUseNuxt();
|
|
169
380
|
const cdnURL = nuxt?.options.runtimeConfig?.app?.cdnURL || nuxt?.options.app?.cdnURL || "";
|
|
170
381
|
const baseURL = cdnURL || nuxt?.options.app.baseURL || "";
|
|
@@ -173,7 +384,7 @@ function normalizeScriptData(src, assetsBaseURL = "/_scripts") {
|
|
|
173
384
|
return { url: src };
|
|
174
385
|
}
|
|
175
386
|
async function downloadScript(opts, renderedScript, fetchOptions, cacheMaxAge) {
|
|
176
|
-
const { src, url, filename, forceDownload } = opts;
|
|
387
|
+
const { src, url, filename, forceDownload, integrity, proxyRewrites } = opts;
|
|
177
388
|
if (src === url || !filename) {
|
|
178
389
|
return;
|
|
179
390
|
}
|
|
@@ -181,16 +392,19 @@ async function downloadScript(opts, renderedScript, fetchOptions, cacheMaxAge) {
|
|
|
181
392
|
const scriptContent = renderedScript.get(src);
|
|
182
393
|
let res = scriptContent instanceof Error ? void 0 : scriptContent?.content;
|
|
183
394
|
if (!res) {
|
|
184
|
-
const
|
|
395
|
+
const proxyRewritesHash = proxyRewrites?.length ? `-${hash(proxyRewrites)}` : "";
|
|
396
|
+
const cacheKey = proxyRewrites?.length ? `bundle-proxy:${filename.replace(".js", `${proxyRewritesHash}.js`)}` : `bundle:${filename}`;
|
|
185
397
|
const shouldUseCache = !forceDownload && await storage.hasItem(cacheKey) && !await isCacheExpired(storage, filename, cacheMaxAge);
|
|
186
398
|
if (shouldUseCache) {
|
|
187
|
-
const
|
|
399
|
+
const cachedContent = await storage.getItemRaw(cacheKey);
|
|
400
|
+
const meta = await storage.getItem(`bundle-meta:${filename}`);
|
|
188
401
|
renderedScript.set(url, {
|
|
189
|
-
content:
|
|
190
|
-
size:
|
|
402
|
+
content: cachedContent,
|
|
403
|
+
size: cachedContent.length / 1024,
|
|
191
404
|
encoding: "utf-8",
|
|
192
405
|
src,
|
|
193
|
-
filename
|
|
406
|
+
filename,
|
|
407
|
+
integrity: meta?.integrity
|
|
194
408
|
});
|
|
195
409
|
return;
|
|
196
410
|
}
|
|
@@ -206,19 +420,29 @@ async function downloadScript(opts, renderedScript, fetchOptions, cacheMaxAge) {
|
|
|
206
420
|
return Buffer.from(r._data || await r.arrayBuffer());
|
|
207
421
|
});
|
|
208
422
|
await storage.setItemRaw(`bundle:${filename}`, res);
|
|
423
|
+
if (proxyRewrites?.length && res) {
|
|
424
|
+
const content = res.toString("utf-8");
|
|
425
|
+
const rewritten = rewriteScriptUrlsAST(content, filename || "script.js", proxyRewrites);
|
|
426
|
+
res = Buffer.from(rewritten, "utf-8");
|
|
427
|
+
logger.debug(`Rewrote ${proxyRewrites.length} URL patterns in ${filename}`);
|
|
428
|
+
}
|
|
429
|
+
const integrityHash = integrity && res ? calculateIntegrity(res, integrity === true ? "sha384" : integrity) : void 0;
|
|
430
|
+
await storage.setItemRaw(cacheKey, res);
|
|
209
431
|
await storage.setItem(`bundle-meta:${filename}`, {
|
|
210
432
|
timestamp: Date.now(),
|
|
211
433
|
src,
|
|
212
|
-
filename
|
|
434
|
+
filename,
|
|
435
|
+
integrity: integrityHash
|
|
213
436
|
});
|
|
214
437
|
size = size || res.length / 1024;
|
|
215
|
-
logger.info(`Downloading script ${colors.gray(`${src} \u2192 ${filename} (${size.toFixed(2)} kB ${encoding})`)}`);
|
|
438
|
+
logger.info(`Downloading script ${colors.gray(`${src} \u2192 ${filename} (${size.toFixed(2)} kB ${encoding})${integrityHash ? ` [${integrityHash.slice(0, 15)}...]` : ""}`)}`);
|
|
216
439
|
renderedScript.set(url, {
|
|
217
440
|
content: res,
|
|
218
441
|
size,
|
|
219
442
|
encoding,
|
|
220
443
|
src,
|
|
221
|
-
filename
|
|
444
|
+
filename,
|
|
445
|
+
integrity: integrityHash
|
|
222
446
|
});
|
|
223
447
|
}
|
|
224
448
|
}
|
|
@@ -252,16 +476,21 @@ function NuxtScriptBundleTransformer(options = {
|
|
|
252
476
|
return createUnplugin(() => {
|
|
253
477
|
return {
|
|
254
478
|
name: "nuxt:scripts:bundler-transformer",
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
479
|
+
transform: {
|
|
480
|
+
filter: {
|
|
481
|
+
id: {
|
|
482
|
+
include: [/\.vue/, /\.[cm]?[jt]sx?$/],
|
|
483
|
+
exclude: [/\.(?:test|spec)\./]
|
|
484
|
+
}
|
|
485
|
+
},
|
|
486
|
+
async handler(code, id) {
|
|
487
|
+
if (!isVue(id, { type: ["template", "script"] }) && !isJS(id))
|
|
488
|
+
return;
|
|
489
|
+
if (!code.includes("useScript"))
|
|
490
|
+
return;
|
|
491
|
+
const s = new MagicString(code);
|
|
492
|
+
const deferredOps = [];
|
|
493
|
+
parseAndWalk(code, id, (_node) => {
|
|
265
494
|
const calleeName = _node.callee?.name;
|
|
266
495
|
if (!calleeName)
|
|
267
496
|
return;
|
|
@@ -271,6 +500,11 @@ function NuxtScriptBundleTransformer(options = {
|
|
|
271
500
|
const node = _node;
|
|
272
501
|
let scriptSrcNode;
|
|
273
502
|
let src;
|
|
503
|
+
let registryKey;
|
|
504
|
+
if (fnName !== "useScript") {
|
|
505
|
+
const baseName = fnName.replace(/^useScript/, "");
|
|
506
|
+
registryKey = baseName.length > 0 ? baseName.charAt(0).toLowerCase() + baseName.slice(1) : void 0;
|
|
507
|
+
}
|
|
274
508
|
if (fnName === "useScript") {
|
|
275
509
|
if (node.arguments[0]?.type === "Literal") {
|
|
276
510
|
scriptSrcNode = node.arguments[0];
|
|
@@ -287,9 +521,7 @@ function NuxtScriptBundleTransformer(options = {
|
|
|
287
521
|
}
|
|
288
522
|
if (!registryNode.scriptBundling && !registryNode.src)
|
|
289
523
|
return;
|
|
290
|
-
const
|
|
291
|
-
const registryKey = baseName.length > 0 ? baseName.charAt(0).toLowerCase() + baseName.slice(1) : "";
|
|
292
|
-
const registryConfig = options.registryConfig?.[registryKey] || {};
|
|
524
|
+
const registryConfig = options.registryConfig?.[registryKey || ""] || {};
|
|
293
525
|
const fnArg0 = {};
|
|
294
526
|
if (node.arguments[0]?.type === "ObjectExpression") {
|
|
295
527
|
const optionsNode = node.arguments[0];
|
|
@@ -309,6 +541,8 @@ function NuxtScriptBundleTransformer(options = {
|
|
|
309
541
|
src = registryNode.scriptBundling && registryNode.scriptBundling(mergedOptions);
|
|
310
542
|
if (src === false)
|
|
311
543
|
return;
|
|
544
|
+
if (!src && registryNode.src)
|
|
545
|
+
src = registryNode.src;
|
|
312
546
|
}
|
|
313
547
|
}
|
|
314
548
|
if (!scriptSrcNode && !src) {
|
|
@@ -323,8 +557,7 @@ function NuxtScriptBundleTransformer(options = {
|
|
|
323
557
|
if (bundleProperty && bundleProperty.value.type === "Literal") {
|
|
324
558
|
const bundleValue = bundleProperty.value.value;
|
|
325
559
|
if (bundleValue === true || bundleValue === "force" || String(bundleValue) === "true") {
|
|
326
|
-
|
|
327
|
-
s.overwrite(valueNode.start, valueNode.end, `'unsupported'`);
|
|
560
|
+
s.overwrite(bundleProperty.value.start, bundleProperty.value.end, `'unsupported'`);
|
|
328
561
|
}
|
|
329
562
|
}
|
|
330
563
|
}
|
|
@@ -341,8 +574,7 @@ function NuxtScriptBundleTransformer(options = {
|
|
|
341
574
|
(p) => (p.key?.name === "bundle" || p.key?.value === "bundle") && p.type === "Property"
|
|
342
575
|
);
|
|
343
576
|
if (bundleProperty && bundleProperty.value.type === "Literal") {
|
|
344
|
-
const
|
|
345
|
-
const bundleValue = value.value;
|
|
577
|
+
const bundleValue = bundleProperty.value.value;
|
|
346
578
|
if (bundleValue !== true && bundleValue !== "force" && String(bundleValue) !== "true") {
|
|
347
579
|
canBundle = false;
|
|
348
580
|
return;
|
|
@@ -370,170 +602,152 @@ function NuxtScriptBundleTransformer(options = {
|
|
|
370
602
|
canBundle = bundleValue === true || bundleValue === "force" || String(bundleValue) === "true";
|
|
371
603
|
forceDownload = bundleValue === "force";
|
|
372
604
|
}
|
|
605
|
+
const firstPartyOption = scriptOptions?.value.properties?.find((prop) => {
|
|
606
|
+
return prop.type === "Property" && prop.key?.name === "firstParty" && prop.value.type === "Literal";
|
|
607
|
+
});
|
|
608
|
+
let firstPartyOptOut = firstPartyOption?.value.value === false;
|
|
609
|
+
if (!firstPartyOptOut && node.arguments[1]?.type === "ObjectExpression") {
|
|
610
|
+
const secondArgFirstPartyProp = node.arguments[1].properties.find(
|
|
611
|
+
(p) => p.type === "Property" && p.key?.name === "firstParty" && p.value.type === "Literal"
|
|
612
|
+
);
|
|
613
|
+
firstPartyOptOut = secondArgFirstPartyProp?.value.value === false;
|
|
614
|
+
}
|
|
615
|
+
if (!firstPartyOptOut && node.arguments[0]?.type === "ObjectExpression") {
|
|
616
|
+
const firstArgFirstPartyProp = node.arguments[0].properties.find(
|
|
617
|
+
(p) => p.type === "Property" && p.key?.name === "firstParty" && p.value.type === "Literal"
|
|
618
|
+
);
|
|
619
|
+
firstPartyOptOut = firstArgFirstPartyProp?.value.value === false;
|
|
620
|
+
}
|
|
373
621
|
if (canBundle) {
|
|
374
622
|
const { url: _url, filename } = normalizeScriptData(src, options.assetsBaseURL);
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
url
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
623
|
+
const script = options.scripts?.find((s2) => s2.import.name === fnName);
|
|
624
|
+
const proxyConfigKey = script?.proxy !== false ? script?.proxy || registryKey : void 0;
|
|
625
|
+
const proxyRewrites = options.firstPartyEnabled && !firstPartyOptOut && proxyConfigKey && options.firstPartyCollectPrefix ? getProxyConfig(proxyConfigKey, options.firstPartyCollectPrefix)?.rewrite : void 0;
|
|
626
|
+
deferredOps.push(async () => {
|
|
627
|
+
let url = _url;
|
|
628
|
+
try {
|
|
629
|
+
await downloadScript({ src, url, filename, forceDownload, proxyRewrites, integrity: options.integrity }, renderedScript, options.fetchOptions, options.cacheMaxAge);
|
|
630
|
+
} catch (e) {
|
|
631
|
+
if (options.fallbackOnSrcOnBundleFail) {
|
|
632
|
+
logger.warn(`[Nuxt Scripts: Bundle Transformer] Failed to bundle ${src}. Fallback to remote loading.`);
|
|
633
|
+
url = src;
|
|
634
|
+
} else {
|
|
635
|
+
const errorMessage = e?.message || "Unknown error";
|
|
636
|
+
if (errorMessage.includes("timeout") || errorMessage.includes("network") || errorMessage.includes("ENOTFOUND") || errorMessage.includes("certificate")) {
|
|
637
|
+
logger.error(`[Nuxt Scripts: Bundle Transformer] Network issue while bundling ${src}: ${errorMessage}`);
|
|
638
|
+
logger.error(`[Nuxt Scripts: Bundle Transformer] Tip: Set 'fallbackOnSrcOnBundleFail: true' in module options or disable bundling in Docker environments`);
|
|
639
|
+
}
|
|
640
|
+
throw e;
|
|
387
641
|
}
|
|
388
|
-
throw e;
|
|
389
642
|
}
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
(
|
|
404
|
-
);
|
|
405
|
-
if (scriptInputProperty) {
|
|
406
|
-
const scriptInput = scriptInputProperty.value;
|
|
407
|
-
if (scriptInput.type === "ObjectExpression") {
|
|
408
|
-
const srcProperty = scriptInput.properties.find(
|
|
409
|
-
(p) => p.key?.name === "src" || p.key?.value === "src"
|
|
410
|
-
);
|
|
411
|
-
if (srcProperty)
|
|
412
|
-
s.overwrite(srcProperty.value.start, srcProperty.value.end, `'${url}'`);
|
|
413
|
-
else
|
|
414
|
-
s.appendRight(scriptInput.end, `, src: '${url}'`);
|
|
415
|
-
}
|
|
643
|
+
if (src === url) {
|
|
644
|
+
if (src && src.startsWith("/"))
|
|
645
|
+
logger.warn(`[Nuxt Scripts: Bundle Transformer] Relative scripts are already bundled. Skipping bundling for \`${src}\`.`);
|
|
646
|
+
else
|
|
647
|
+
logger.warn(`[Nuxt Scripts: Bundle Transformer] Failed to bundle ${src}.`);
|
|
648
|
+
}
|
|
649
|
+
const scriptMeta = renderedScript.get(url);
|
|
650
|
+
const integrityHash = scriptMeta instanceof Error ? void 0 : scriptMeta?.integrity;
|
|
651
|
+
if (scriptSrcNode) {
|
|
652
|
+
if (integrityHash && fnName === "useScript" && node.arguments[0]?.type === "Literal") {
|
|
653
|
+
s.overwrite(scriptSrcNode.start, scriptSrcNode.end, `{ src: '${url}', integrity: '${integrityHash}', crossorigin: 'anonymous' }`);
|
|
654
|
+
} else if (integrityHash && fnName === "useScript" && node.arguments[0]?.type === "ObjectExpression") {
|
|
655
|
+
s.overwrite(scriptSrcNode.start, scriptSrcNode.end, `'${url}'`);
|
|
656
|
+
s.appendLeft(node.arguments[0].end - 1, `, integrity: '${integrityHash}', crossorigin: 'anonymous'`);
|
|
416
657
|
} else {
|
|
417
|
-
s.
|
|
658
|
+
s.overwrite(scriptSrcNode.start, scriptSrcNode.end, `'${url}'`);
|
|
418
659
|
}
|
|
419
660
|
} else {
|
|
420
|
-
|
|
661
|
+
const integrityProps = integrityHash ? `, integrity: '${integrityHash}', crossorigin: 'anonymous'` : "";
|
|
662
|
+
if (node.arguments[0]) {
|
|
663
|
+
const optionsNode = node.arguments[0];
|
|
664
|
+
const scriptInputProperty = optionsNode.properties.find(
|
|
665
|
+
(p) => p.key?.name === "scriptInput" || p.key?.value === "scriptInput"
|
|
666
|
+
);
|
|
667
|
+
if (scriptInputProperty) {
|
|
668
|
+
const scriptInput = scriptInputProperty.value;
|
|
669
|
+
if (scriptInput.type === "ObjectExpression") {
|
|
670
|
+
const srcProperty = scriptInput.properties.find(
|
|
671
|
+
(p) => p.key?.name === "src" || p.key?.value === "src"
|
|
672
|
+
);
|
|
673
|
+
if (srcProperty) {
|
|
674
|
+
s.overwrite(srcProperty.value.start, srcProperty.value.end, `'${url}'`);
|
|
675
|
+
if (integrityHash)
|
|
676
|
+
s.appendLeft(scriptInput.end - 1, integrityProps);
|
|
677
|
+
} else {
|
|
678
|
+
s.appendRight(scriptInput.end - 1, `, src: '${url}'${integrityProps}`);
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
} else {
|
|
682
|
+
s.appendRight(node.arguments[0].start + 1, ` scriptInput: { src: '${url}'${integrityProps} }, `);
|
|
683
|
+
}
|
|
684
|
+
} else {
|
|
685
|
+
s.overwrite(node.callee.end, node.end, `({ scriptInput: { src: '${url}'${integrityProps} } })`);
|
|
686
|
+
}
|
|
421
687
|
}
|
|
422
|
-
}
|
|
688
|
+
});
|
|
423
689
|
}
|
|
424
690
|
}
|
|
425
691
|
}
|
|
426
692
|
}
|
|
693
|
+
});
|
|
694
|
+
for (const op of deferredOps) {
|
|
695
|
+
await op();
|
|
696
|
+
}
|
|
697
|
+
if (s.hasChanged()) {
|
|
698
|
+
return {
|
|
699
|
+
code: s.toString(),
|
|
700
|
+
map: s.generateMap({ includeContent: true, source: id })
|
|
701
|
+
};
|
|
427
702
|
}
|
|
428
|
-
});
|
|
429
|
-
if (s.hasChanged()) {
|
|
430
|
-
return {
|
|
431
|
-
code: s.toString(),
|
|
432
|
-
map: s.generateMap({ includeContent: true, source: id })
|
|
433
|
-
};
|
|
434
703
|
}
|
|
435
704
|
}
|
|
436
705
|
};
|
|
437
706
|
});
|
|
438
707
|
}
|
|
439
708
|
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
if (!confirm)
|
|
454
|
-
return false;
|
|
709
|
+
function registerTypeTemplates({ nuxt, config, newScripts }) {
|
|
710
|
+
addTypeTemplate({
|
|
711
|
+
filename: "types/nuxt-scripts-augments.d.ts",
|
|
712
|
+
getContents: () => {
|
|
713
|
+
const typesPath = relative(
|
|
714
|
+
resolve(nuxt.options.rootDir, nuxt.options.buildDir, "types"),
|
|
715
|
+
resolve("runtime/types")
|
|
716
|
+
);
|
|
717
|
+
let augments = `// Generated by @nuxt/scripts
|
|
718
|
+
declare module '#app' {
|
|
719
|
+
interface NuxtApp {
|
|
720
|
+
$scripts: Record<${[...Object.keys(config.globals || {}), ...Object.keys(config.registry || {})].map((k) => `'${k}'`).concat(["string"]).join(" | ")}, import('#nuxt-scripts/types').UseScriptContext<any> | undefined>
|
|
721
|
+
_scripts: Record<string, import('#nuxt-scripts/types').NuxtDevToolsScriptInstance>
|
|
455
722
|
}
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
await installCommand();
|
|
459
|
-
logger$1.success(`Installed ${name}`);
|
|
460
|
-
return true;
|
|
461
|
-
} catch (err) {
|
|
462
|
-
logger$1.error(err);
|
|
463
|
-
return false;
|
|
723
|
+
interface RuntimeNuxtHooks {
|
|
724
|
+
'scripts:updated': (ctx: { scripts: Record<string, import('#nuxt-scripts/types').NuxtDevToolsScriptInstance> }) => void | Promise<void>
|
|
464
725
|
}
|
|
465
726
|
}
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
}
|
|
727
|
+
`;
|
|
728
|
+
if (newScripts.length) {
|
|
729
|
+
augments += `
|
|
730
|
+
declare module '#nuxt-scripts/types' {
|
|
731
|
+
type _NuxtScriptOptions = Omit<import('${typesPath}').NuxtUseScriptOptions, 'use' | 'beforeInit'>
|
|
732
|
+
interface ScriptRegistry {
|
|
733
|
+
${newScripts.map((i) => {
|
|
734
|
+
const key = i.import.name.replace("useScript", "");
|
|
735
|
+
const keyLcFirst = key.substring(0, 1).toLowerCase() + key.substring(1);
|
|
736
|
+
return ` ${keyLcFirst}?: import('${i.import.from}').${key}Input | [import('${i.import.from}').${key}Input, _NuxtScriptOptions]`;
|
|
737
|
+
}).join("\n")}
|
|
738
|
+
}
|
|
478
739
|
}
|
|
479
|
-
|
|
480
|
-
function NuxtScriptsCheckScripts() {
|
|
481
|
-
return createUnplugin(() => {
|
|
482
|
-
return {
|
|
483
|
-
name: "nuxt-scripts:check-scripts",
|
|
484
|
-
transformInclude(id) {
|
|
485
|
-
return isVue(id, { type: ["script"] });
|
|
486
|
-
},
|
|
487
|
-
async transform(code) {
|
|
488
|
-
if (!code.includes("useScript"))
|
|
489
|
-
return;
|
|
490
|
-
const ast = this.parse(code);
|
|
491
|
-
let nameNode;
|
|
492
|
-
let errorNode;
|
|
493
|
-
walk(ast, {
|
|
494
|
-
enter(_node) {
|
|
495
|
-
if (_node.type === "VariableDeclaration" && _node.declarations?.[0]?.id?.type === "ObjectPattern") {
|
|
496
|
-
const objPattern = _node.declarations[0]?.id;
|
|
497
|
-
for (const property of objPattern.properties) {
|
|
498
|
-
if (property.type === "Property" && property.key.type === "Identifier" && property.key.name === "$script" && property.value.type === "Identifier") {
|
|
499
|
-
nameNode = _node;
|
|
500
|
-
}
|
|
501
|
-
}
|
|
502
|
-
}
|
|
503
|
-
if (nameNode) {
|
|
504
|
-
let sequence = _node.type === "SequenceExpression" ? _node : null;
|
|
505
|
-
let assignmentExpression;
|
|
506
|
-
if (_node.type === "VariableDeclaration") {
|
|
507
|
-
if (_node.declarations[0]?.init?.type === "SequenceExpression") {
|
|
508
|
-
sequence = _node.declarations[0]?.init;
|
|
509
|
-
assignmentExpression = _node.declarations[0]?.init?.expressions?.[0];
|
|
510
|
-
}
|
|
511
|
-
}
|
|
512
|
-
if (sequence && !assignmentExpression) {
|
|
513
|
-
assignmentExpression = sequence.expressions[0]?.type === "AssignmentExpression" ? sequence.expressions[0] : null;
|
|
514
|
-
}
|
|
515
|
-
if (assignmentExpression) {
|
|
516
|
-
const right = assignmentExpression?.right;
|
|
517
|
-
if (right.callee?.name === "_withAsyncContext") {
|
|
518
|
-
if (right.arguments[0]?.body?.name === "$script" || right.arguments[0]?.body?.callee?.object?.name === "$script") {
|
|
519
|
-
errorNode = nameNode;
|
|
520
|
-
}
|
|
521
|
-
}
|
|
522
|
-
}
|
|
523
|
-
}
|
|
524
|
-
}
|
|
525
|
-
});
|
|
526
|
-
if (errorNode) {
|
|
527
|
-
return this.error(new Error("You can't use a top-level await on $script as it will never resolve."));
|
|
528
|
-
}
|
|
740
|
+
`;
|
|
529
741
|
}
|
|
530
|
-
|
|
531
|
-
|
|
742
|
+
return `${augments}
|
|
743
|
+
export {}`;
|
|
744
|
+
}
|
|
745
|
+
}, { nuxt: true });
|
|
532
746
|
}
|
|
533
|
-
|
|
534
747
|
function templateTriggerResolver(defaultScriptOptions) {
|
|
535
748
|
const needsIdleTimeout = defaultScriptOptions?.trigger && typeof defaultScriptOptions.trigger === "object" && "idleTimeout" in defaultScriptOptions.trigger;
|
|
536
749
|
const needsInteraction = defaultScriptOptions?.trigger && typeof defaultScriptOptions.trigger === "object" && "interaction" in defaultScriptOptions.trigger;
|
|
750
|
+
const needsServiceWorker = defaultScriptOptions?.trigger && typeof defaultScriptOptions.trigger === "object" && "serviceWorker" in defaultScriptOptions.trigger;
|
|
537
751
|
const imports = [];
|
|
538
752
|
if (needsIdleTimeout) {
|
|
539
753
|
imports.push(`import { useScriptTriggerIdleTimeout } from '#nuxt-scripts/composables/useScriptTriggerIdleTimeout'`);
|
|
@@ -541,11 +755,15 @@ function templateTriggerResolver(defaultScriptOptions) {
|
|
|
541
755
|
if (needsInteraction) {
|
|
542
756
|
imports.push(`import { useScriptTriggerInteraction } from '#nuxt-scripts/composables/useScriptTriggerInteraction'`);
|
|
543
757
|
}
|
|
758
|
+
if (needsServiceWorker) {
|
|
759
|
+
imports.push(`import { useScriptTriggerServiceWorker } from '#nuxt-scripts/composables/useScriptTriggerServiceWorker'`);
|
|
760
|
+
}
|
|
544
761
|
return [
|
|
545
762
|
...imports,
|
|
546
763
|
`export function resolveTrigger(trigger) {`,
|
|
547
764
|
needsIdleTimeout ? ` if ('idleTimeout' in trigger) return useScriptTriggerIdleTimeout({ timeout: trigger.idleTimeout })` : "",
|
|
548
765
|
needsInteraction ? ` if ('interaction' in trigger) return useScriptTriggerInteraction({ events: trigger.interaction })` : "",
|
|
766
|
+
needsServiceWorker ? ` if ('serviceWorker' in trigger) return useScriptTriggerServiceWorker()` : "",
|
|
549
767
|
` return null`,
|
|
550
768
|
`}`
|
|
551
769
|
].filter(Boolean).join("\n");
|
|
@@ -562,6 +780,9 @@ function resolveTriggerForTemplate(trigger) {
|
|
|
562
780
|
if ("interaction" in trigger) {
|
|
563
781
|
return `useScriptTriggerInteraction({ events: ${JSON.stringify(trigger.interaction)} })`;
|
|
564
782
|
}
|
|
783
|
+
if ("serviceWorker" in trigger) {
|
|
784
|
+
return `useScriptTriggerServiceWorker()`;
|
|
785
|
+
}
|
|
565
786
|
}
|
|
566
787
|
return null;
|
|
567
788
|
}
|
|
@@ -572,27 +793,37 @@ function templatePlugin(config, registry) {
|
|
|
572
793
|
}
|
|
573
794
|
const imports = [];
|
|
574
795
|
const inits = [];
|
|
796
|
+
const resolvedRegistryKeys = [];
|
|
575
797
|
let needsIdleTimeoutImport = false;
|
|
576
798
|
let needsInteractionImport = false;
|
|
799
|
+
let needsServiceWorkerImport = false;
|
|
577
800
|
for (const [k, c] of Object.entries(config.registry || {})) {
|
|
578
|
-
const importDefinition = registry.find((i) => i.import.name === `
|
|
801
|
+
const importDefinition = registry.find((i) => i.import.name.toLowerCase() === `usescript${k.toLowerCase()}`);
|
|
579
802
|
if (importDefinition) {
|
|
803
|
+
resolvedRegistryKeys.push(k);
|
|
580
804
|
imports.unshift(`import { ${importDefinition.import.name} } from '${importDefinition.import.from}'`);
|
|
581
|
-
const args = (typeof c !== "object" ? {} : c) || {};
|
|
582
805
|
if (c === "mock") {
|
|
583
|
-
|
|
584
|
-
} else if (Array.isArray(c) && c.length === 2
|
|
585
|
-
const
|
|
806
|
+
inits.push(`const ${k} = ${importDefinition.import.name}({ scriptOptions: { trigger: 'manual', skipValidation: true } })`);
|
|
807
|
+
} else if (Array.isArray(c) && c.length === 2) {
|
|
808
|
+
const input = c[0] || {};
|
|
809
|
+
const scriptOptions = { ...c[1] };
|
|
810
|
+
const triggerResolved = resolveTriggerForTemplate(scriptOptions?.trigger);
|
|
586
811
|
if (triggerResolved) {
|
|
587
|
-
|
|
588
|
-
if (
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
if (triggerResolved.includes("
|
|
812
|
+
scriptOptions.trigger = "__TRIGGER_PLACEHOLDER__";
|
|
813
|
+
if (triggerResolved.includes("useScriptTriggerIdleTimeout"))
|
|
814
|
+
needsIdleTimeoutImport = true;
|
|
815
|
+
if (triggerResolved.includes("useScriptTriggerInteraction"))
|
|
816
|
+
needsInteractionImport = true;
|
|
817
|
+
if (triggerResolved.includes("useScriptTriggerServiceWorker"))
|
|
818
|
+
needsServiceWorkerImport = true;
|
|
593
819
|
}
|
|
820
|
+
const args = { ...input, scriptOptions };
|
|
821
|
+
const argsJson = triggerResolved ? JSON.stringify(args).replace(/"__TRIGGER_PLACEHOLDER__"/g, triggerResolved) : JSON.stringify(args);
|
|
822
|
+
inits.push(`const ${k} = ${importDefinition.import.name}(${argsJson})`);
|
|
823
|
+
} else {
|
|
824
|
+
const args = (typeof c !== "object" ? {} : c) || {};
|
|
825
|
+
inits.push(`const ${k} = ${importDefinition.import.name}(${JSON.stringify(args)})`);
|
|
594
826
|
}
|
|
595
|
-
inits.push(`const ${k} = ${importDefinition.import.name}(${JSON.stringify(args).replace(/"__TRIGGER_(.*?)__"/g, "$1")})`);
|
|
596
827
|
}
|
|
597
828
|
}
|
|
598
829
|
for (const [k, c] of Object.entries(config.globals || {})) {
|
|
@@ -602,20 +833,30 @@ function templatePlugin(config, registry) {
|
|
|
602
833
|
const options = c[1];
|
|
603
834
|
const triggerResolved = resolveTriggerForTemplate(options?.trigger);
|
|
604
835
|
if (triggerResolved) {
|
|
605
|
-
if (triggerResolved.includes("useScriptTriggerIdleTimeout"))
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
836
|
+
if (triggerResolved.includes("useScriptTriggerIdleTimeout"))
|
|
837
|
+
needsIdleTimeoutImport = true;
|
|
838
|
+
if (triggerResolved.includes("useScriptTriggerInteraction"))
|
|
839
|
+
needsInteractionImport = true;
|
|
840
|
+
if (triggerResolved.includes("useScriptTriggerServiceWorker"))
|
|
841
|
+
needsServiceWorkerImport = true;
|
|
842
|
+
const resolvedOptions = { ...options, trigger: "__TRIGGER_PLACEHOLDER__" };
|
|
843
|
+
const optionsJson = JSON.stringify(resolvedOptions).replace(/"__TRIGGER_PLACEHOLDER__"/g, triggerResolved);
|
|
844
|
+
inits.push(`const ${k} = useScript(${JSON.stringify({ key: k, ...typeof c[0] === "string" ? { src: c[0] } : c[0] })}, { ...${optionsJson}, use: () => ({ ${k}: window.${k} }) })`);
|
|
609
845
|
} else {
|
|
610
846
|
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} }) })`);
|
|
611
847
|
}
|
|
612
848
|
} else if (typeof c === "object" && c !== null) {
|
|
613
849
|
const triggerResolved = resolveTriggerForTemplate(c.trigger);
|
|
614
850
|
if (triggerResolved) {
|
|
615
|
-
if (triggerResolved.includes("useScriptTriggerIdleTimeout"))
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
851
|
+
if (triggerResolved.includes("useScriptTriggerIdleTimeout"))
|
|
852
|
+
needsIdleTimeoutImport = true;
|
|
853
|
+
if (triggerResolved.includes("useScriptTriggerInteraction"))
|
|
854
|
+
needsInteractionImport = true;
|
|
855
|
+
if (triggerResolved.includes("useScriptTriggerServiceWorker"))
|
|
856
|
+
needsServiceWorkerImport = true;
|
|
857
|
+
const resolvedOptions = { ...c, trigger: "__TRIGGER_PLACEHOLDER__" };
|
|
858
|
+
const argsJson = JSON.stringify({ key: k, ...resolvedOptions }).replace(/"__TRIGGER_PLACEHOLDER__"/g, triggerResolved);
|
|
859
|
+
inits.push(`const ${k} = useScript(${argsJson}, { use: () => ({ ${k}: window.${k} }) })`);
|
|
619
860
|
} else {
|
|
620
861
|
inits.push(`const ${k} = useScript(${JSON.stringify({ key: k, ...c })}, { use: () => ({ ${k}: window.${k} }) })`);
|
|
621
862
|
}
|
|
@@ -628,6 +869,9 @@ function templatePlugin(config, registry) {
|
|
|
628
869
|
if (needsInteractionImport) {
|
|
629
870
|
triggerImports.push(`import { useScriptTriggerInteraction } from '#nuxt-scripts/composables/useScriptTriggerInteraction'`);
|
|
630
871
|
}
|
|
872
|
+
if (needsServiceWorkerImport) {
|
|
873
|
+
triggerImports.push(`import { useScriptTriggerServiceWorker } from '#nuxt-scripts/composables/useScriptTriggerServiceWorker'`);
|
|
874
|
+
}
|
|
631
875
|
return [
|
|
632
876
|
`import { useScript } from '#nuxt-scripts/composables/useScript'`,
|
|
633
877
|
`import { defineNuxtPlugin } from 'nuxt/app'`,
|
|
@@ -640,12 +884,78 @@ function templatePlugin(config, registry) {
|
|
|
640
884
|
` parallel: true,`,
|
|
641
885
|
` setup() {`,
|
|
642
886
|
...inits.map((i) => ` ${i}`),
|
|
643
|
-
` return { provide: {
|
|
887
|
+
` return { provide: { scripts: { ${[...Object.keys(config.globals || {}), ...resolvedRegistryKeys].join(", ")} } } }`,
|
|
644
888
|
` }`,
|
|
645
889
|
`})`
|
|
646
890
|
].join("\n");
|
|
647
891
|
}
|
|
648
892
|
|
|
893
|
+
const SELF_CLOSING_SCRIPT_RE = /<((?:Script[A-Z]|script-)\w[\w-]*)\b([^>]*?)\/\s*>/g;
|
|
894
|
+
function fixSelfClosingScriptComponents(nuxt) {
|
|
895
|
+
function expandTags(content) {
|
|
896
|
+
SELF_CLOSING_SCRIPT_RE.lastIndex = 0;
|
|
897
|
+
if (!SELF_CLOSING_SCRIPT_RE.test(content))
|
|
898
|
+
return null;
|
|
899
|
+
SELF_CLOSING_SCRIPT_RE.lastIndex = 0;
|
|
900
|
+
return content.replace(SELF_CLOSING_SCRIPT_RE, (_, tag, attrs) => `<${tag}${attrs.trimEnd()}></${tag}>`);
|
|
901
|
+
}
|
|
902
|
+
function fixFile(filePath) {
|
|
903
|
+
if (!existsSync(filePath))
|
|
904
|
+
return;
|
|
905
|
+
const content = readFileSync(filePath, "utf-8");
|
|
906
|
+
const fixed = expandTags(content);
|
|
907
|
+
if (fixed)
|
|
908
|
+
nuxt.vfs[filePath] = fixed;
|
|
909
|
+
}
|
|
910
|
+
function scanDir(dir) {
|
|
911
|
+
if (!existsSync(dir))
|
|
912
|
+
return;
|
|
913
|
+
for (const entry of readdirSync(dir, { withFileTypes: true })) {
|
|
914
|
+
const fullPath = resolve(dir, entry.name);
|
|
915
|
+
if (entry.isDirectory())
|
|
916
|
+
scanDir(fullPath);
|
|
917
|
+
else if (entry.name.endsWith(".vue"))
|
|
918
|
+
fixFile(fullPath);
|
|
919
|
+
}
|
|
920
|
+
}
|
|
921
|
+
const pagesDirs = /* @__PURE__ */ new Set();
|
|
922
|
+
for (const layer of nuxt.options._layers) {
|
|
923
|
+
pagesDirs.add(resolve(
|
|
924
|
+
layer.config.srcDir,
|
|
925
|
+
layer.config.dir?.pages || "pages"
|
|
926
|
+
));
|
|
927
|
+
}
|
|
928
|
+
for (const dir of pagesDirs) scanDir(dir);
|
|
929
|
+
if (nuxt.options.dev) {
|
|
930
|
+
nuxt.hook("builder:watch", (_event, relativePath) => {
|
|
931
|
+
if (!relativePath.endsWith(".vue"))
|
|
932
|
+
return;
|
|
933
|
+
for (const layer of nuxt.options._layers) {
|
|
934
|
+
const fullPath = resolve(layer.config.srcDir, relativePath);
|
|
935
|
+
for (const dir of pagesDirs) {
|
|
936
|
+
if (fullPath.startsWith(`${dir}/`)) {
|
|
937
|
+
fixFile(fullPath);
|
|
938
|
+
return;
|
|
939
|
+
}
|
|
940
|
+
}
|
|
941
|
+
}
|
|
942
|
+
});
|
|
943
|
+
}
|
|
944
|
+
}
|
|
945
|
+
const PARTYTOWN_FORWARDS = {
|
|
946
|
+
googleAnalytics: ["dataLayer.push", "gtag"],
|
|
947
|
+
plausible: ["plausible"],
|
|
948
|
+
fathom: ["fathom", "fathom.trackEvent", "fathom.trackPageview"],
|
|
949
|
+
umami: ["umami", "umami.track"],
|
|
950
|
+
matomo: ["_paq.push"],
|
|
951
|
+
segment: ["analytics", "analytics.track", "analytics.page", "analytics.identify"],
|
|
952
|
+
metaPixel: ["fbq"],
|
|
953
|
+
xPixel: ["twq"],
|
|
954
|
+
tiktokPixel: ["ttq.track", "ttq.page", "ttq.identify"],
|
|
955
|
+
snapchatPixel: ["snaptr"],
|
|
956
|
+
redditPixel: ["rdt"],
|
|
957
|
+
cloudflareWebAnalytics: ["__cfBeacon"]
|
|
958
|
+
};
|
|
649
959
|
const module$1 = defineNuxtModule({
|
|
650
960
|
meta: {
|
|
651
961
|
name: "@nuxt/scripts",
|
|
@@ -655,6 +965,7 @@ const module$1 = defineNuxtModule({
|
|
|
655
965
|
}
|
|
656
966
|
},
|
|
657
967
|
defaults: {
|
|
968
|
+
firstParty: true,
|
|
658
969
|
defaultScriptOptions: {
|
|
659
970
|
trigger: "onNuxtReady"
|
|
660
971
|
},
|
|
@@ -668,6 +979,10 @@ const module$1 = defineNuxtModule({
|
|
|
668
979
|
// Configures the maximum time (in milliseconds) allowed for each fetch attempt.
|
|
669
980
|
}
|
|
670
981
|
},
|
|
982
|
+
googleStaticMapsProxy: {
|
|
983
|
+
enabled: false,
|
|
984
|
+
cacheMaxAge: 3600
|
|
985
|
+
},
|
|
671
986
|
enabled: true,
|
|
672
987
|
debug: false
|
|
673
988
|
},
|
|
@@ -687,11 +1002,17 @@ const module$1 = defineNuxtModule({
|
|
|
687
1002
|
if (unheadVersion?.startsWith("1")) {
|
|
688
1003
|
logger.error(`Nuxt Scripts requires Unhead >= 2, you are using v${unheadVersion}. Please run \`nuxi upgrade --clean\` to upgrade...`);
|
|
689
1004
|
}
|
|
690
|
-
nuxt.options.runtimeConfig["nuxt-scripts"] = {
|
|
1005
|
+
nuxt.options.runtimeConfig["nuxt-scripts"] = {
|
|
1006
|
+
version,
|
|
1007
|
+
// Private proxy config with API key (server-side only)
|
|
1008
|
+
googleStaticMapsProxy: config.googleStaticMapsProxy?.enabled ? { apiKey: nuxt.options.runtimeConfig.public.scripts?.googleMaps?.apiKey } : void 0
|
|
1009
|
+
};
|
|
691
1010
|
nuxt.options.runtimeConfig.public["nuxt-scripts"] = {
|
|
692
1011
|
// expose for devtools
|
|
693
1012
|
version: nuxt.options.dev ? version : void 0,
|
|
694
|
-
defaultScriptOptions: config.defaultScriptOptions
|
|
1013
|
+
defaultScriptOptions: config.defaultScriptOptions,
|
|
1014
|
+
// Only expose enabled and cacheMaxAge to client, not apiKey
|
|
1015
|
+
googleStaticMapsProxy: config.googleStaticMapsProxy?.enabled ? { enabled: true, cacheMaxAge: config.googleStaticMapsProxy.cacheMaxAge } : void 0
|
|
695
1016
|
};
|
|
696
1017
|
if (config.registry) {
|
|
697
1018
|
nuxt.options.runtimeConfig.public = nuxt.options.runtimeConfig.public || {};
|
|
@@ -700,13 +1021,57 @@ const module$1 = defineNuxtModule({
|
|
|
700
1021
|
config.registry
|
|
701
1022
|
);
|
|
702
1023
|
}
|
|
1024
|
+
if (config.defaultScriptOptions?.bundle !== void 0) {
|
|
1025
|
+
logger.warn(
|
|
1026
|
+
"`scripts.defaultScriptOptions.bundle` is deprecated. Use `scripts.firstParty: true` instead. First-party mode is now enabled by default."
|
|
1027
|
+
);
|
|
1028
|
+
}
|
|
1029
|
+
const staticPresets = ["static", "github-pages", "cloudflare-pages-static"];
|
|
1030
|
+
const preset = process.env.NITRO_PRESET || "";
|
|
1031
|
+
const isStaticPreset = staticPresets.includes(preset);
|
|
1032
|
+
const firstPartyEnabled = !!config.firstParty;
|
|
1033
|
+
const firstPartyPrefix = typeof config.firstParty === "object" ? config.firstParty.prefix : void 0;
|
|
1034
|
+
const firstPartyCollectPrefix = typeof config.firstParty === "object" ? config.firstParty.collectPrefix || "/_proxy" : "/_proxy";
|
|
1035
|
+
const firstPartyPrivacy = typeof config.firstParty === "object" ? config.firstParty.privacy : void 0;
|
|
1036
|
+
const assetsPrefix = firstPartyPrefix || config.assets?.prefix || "/_scripts";
|
|
1037
|
+
if (config.partytown?.length) {
|
|
1038
|
+
config.registry = config.registry || {};
|
|
1039
|
+
const requiredForwards = [];
|
|
1040
|
+
for (const scriptKey of config.partytown) {
|
|
1041
|
+
const forwards = PARTYTOWN_FORWARDS[scriptKey];
|
|
1042
|
+
if (forwards) {
|
|
1043
|
+
requiredForwards.push(...forwards);
|
|
1044
|
+
} else if (import.meta.dev) {
|
|
1045
|
+
logger.warn(`[partytown] "${scriptKey}" has no known Partytown forwards configured. It may not work correctly or may require manual forward configuration.`);
|
|
1046
|
+
}
|
|
1047
|
+
const reg = config.registry;
|
|
1048
|
+
const existing = reg[scriptKey];
|
|
1049
|
+
if (Array.isArray(existing)) {
|
|
1050
|
+
existing[1] = { ...existing[1], partytown: true };
|
|
1051
|
+
} else if (existing && typeof existing === "object" && existing !== true && existing !== "mock") {
|
|
1052
|
+
reg[scriptKey] = [existing, { partytown: true }];
|
|
1053
|
+
} else if (existing === true || existing === "mock") {
|
|
1054
|
+
reg[scriptKey] = [{}, { partytown: true }];
|
|
1055
|
+
} else {
|
|
1056
|
+
reg[scriptKey] = [{}, { partytown: true }];
|
|
1057
|
+
}
|
|
1058
|
+
}
|
|
1059
|
+
if (requiredForwards.length && hasNuxtModule("@nuxtjs/partytown")) {
|
|
1060
|
+
const partytownConfig = nuxt.options.partytown || {};
|
|
1061
|
+
const existingForwards = partytownConfig.forward || [];
|
|
1062
|
+
const newForwards = [.../* @__PURE__ */ new Set([...existingForwards, ...requiredForwards])];
|
|
1063
|
+
nuxt.options.partytown = { ...partytownConfig, forward: newForwards };
|
|
1064
|
+
logger.info(`[partytown] Auto-configured forwards: ${requiredForwards.join(", ")}`);
|
|
1065
|
+
}
|
|
1066
|
+
}
|
|
703
1067
|
const composables = [
|
|
704
1068
|
"useScript",
|
|
705
1069
|
"useScriptEventPage",
|
|
706
1070
|
"useScriptTriggerConsent",
|
|
707
1071
|
"useScriptTriggerElement",
|
|
708
1072
|
"useScriptTriggerIdleTimeout",
|
|
709
|
-
"useScriptTriggerInteraction"
|
|
1073
|
+
"useScriptTriggerInteraction",
|
|
1074
|
+
"useScriptTriggerServiceWorker"
|
|
710
1075
|
];
|
|
711
1076
|
for (const composable of composables) {
|
|
712
1077
|
addImports({
|
|
@@ -720,12 +1085,60 @@ const module$1 = defineNuxtModule({
|
|
|
720
1085
|
path: await resolvePath("./runtime/components"),
|
|
721
1086
|
pathPrefix: false
|
|
722
1087
|
});
|
|
1088
|
+
fixSelfClosingScriptComponents(nuxt);
|
|
723
1089
|
addTemplate({
|
|
724
1090
|
filename: "nuxt-scripts-trigger-resolver.mjs",
|
|
725
1091
|
getContents() {
|
|
726
1092
|
return templateTriggerResolver(config.defaultScriptOptions);
|
|
727
1093
|
}
|
|
728
1094
|
});
|
|
1095
|
+
logger.debug("[nuxt-scripts] First-party config:", { firstPartyEnabled, firstPartyPrivacy, firstPartyCollectPrefix });
|
|
1096
|
+
let interceptRules = [];
|
|
1097
|
+
if (firstPartyEnabled) {
|
|
1098
|
+
addPluginTemplate({
|
|
1099
|
+
filename: "nuxt-scripts-intercept.client.mjs",
|
|
1100
|
+
getContents() {
|
|
1101
|
+
const rulesJson = JSON.stringify(interceptRules);
|
|
1102
|
+
return `export default defineNuxtPlugin({
|
|
1103
|
+
name: 'nuxt-scripts:intercept',
|
|
1104
|
+
enforce: 'pre',
|
|
1105
|
+
setup() {
|
|
1106
|
+
const rules = ${rulesJson};
|
|
1107
|
+
const origBeacon = typeof navigator !== 'undefined' && navigator.sendBeacon
|
|
1108
|
+
? navigator.sendBeacon.bind(navigator)
|
|
1109
|
+
: () => false;
|
|
1110
|
+
const origFetch = globalThis.fetch.bind(globalThis);
|
|
1111
|
+
|
|
1112
|
+
function rewriteUrl(url) {
|
|
1113
|
+
try {
|
|
1114
|
+
const parsed = new URL(url, location.origin);
|
|
1115
|
+
for (const rule of rules) {
|
|
1116
|
+
if (parsed.hostname === rule.pattern || parsed.hostname.endsWith('.' + rule.pattern)) {
|
|
1117
|
+
if (rule.pathPrefix && !parsed.pathname.startsWith(rule.pathPrefix)) continue;
|
|
1118
|
+
const path = rule.pathPrefix ? parsed.pathname.slice(rule.pathPrefix.length) : parsed.pathname;
|
|
1119
|
+
return location.origin + rule.target + (path.startsWith('/') ? '' : '/') + path + parsed.search;
|
|
1120
|
+
}
|
|
1121
|
+
}
|
|
1122
|
+
} catch {}
|
|
1123
|
+
return url;
|
|
1124
|
+
}
|
|
1125
|
+
|
|
1126
|
+
globalThis.__nuxtScripts = {
|
|
1127
|
+
sendBeacon: (url, data) => origBeacon(rewriteUrl(url), data),
|
|
1128
|
+
fetch: (url, opts) => origFetch(typeof url === 'string' ? rewriteUrl(url) : url, opts),
|
|
1129
|
+
};
|
|
1130
|
+
},
|
|
1131
|
+
})
|
|
1132
|
+
`;
|
|
1133
|
+
}
|
|
1134
|
+
});
|
|
1135
|
+
const proxyHandlerPath = await resolvePath("./runtime/server/proxy-handler");
|
|
1136
|
+
logger.debug("[nuxt-scripts] Registering proxy handler:", `${firstPartyCollectPrefix}/**`, "->", proxyHandlerPath);
|
|
1137
|
+
addServerHandler({
|
|
1138
|
+
route: `${firstPartyCollectPrefix}/**`,
|
|
1139
|
+
handler: proxyHandlerPath
|
|
1140
|
+
});
|
|
1141
|
+
}
|
|
729
1142
|
const scripts = await registry(resolvePath);
|
|
730
1143
|
for (const script of scripts) {
|
|
731
1144
|
if (script.import?.name) {
|
|
@@ -743,42 +1156,7 @@ const module$1 = defineNuxtModule({
|
|
|
743
1156
|
}
|
|
744
1157
|
const registryScriptsWithImport = registryScripts.filter((i) => !!i.import?.name);
|
|
745
1158
|
const newScripts = registryScriptsWithImport.filter((i) => !scripts.some((r) => r.import?.name === i.import.name));
|
|
746
|
-
|
|
747
|
-
filename: "module/nuxt-scripts.d.ts",
|
|
748
|
-
getContents: (data) => {
|
|
749
|
-
const typesPath = relative(resolve(data.nuxt.options.rootDir, data.nuxt.options.buildDir, "module"), resolve("runtime/types"));
|
|
750
|
-
let types = `
|
|
751
|
-
declare module '#app' {
|
|
752
|
-
interface NuxtApp {
|
|
753
|
-
$scripts: Record<${[...Object.keys(config.globals || {}), ...Object.keys(config.registry || {})].map((k) => `'${k}'`).concat(["string"]).join(" | ")}, (import('#nuxt-scripts/types').UseScriptContext<any>)>
|
|
754
|
-
_scripts: Record<string, (import('#nuxt-scripts/types').UseScriptContext<any>)>
|
|
755
|
-
}
|
|
756
|
-
interface RuntimeNuxtHooks {
|
|
757
|
-
'scripts:updated': (ctx: { scripts: Record<string, (import('#nuxt-scripts/types').UseScriptContext<any>)> }) => void | Promise<void>
|
|
758
|
-
}
|
|
759
|
-
}
|
|
760
|
-
`;
|
|
761
|
-
if (newScripts.length) {
|
|
762
|
-
types = `${types}
|
|
763
|
-
declare module '#nuxt-scripts/types' {
|
|
764
|
-
type NuxtUseScriptOptions = Omit<import('${typesPath}').NuxtUseScriptOptions, 'use' | 'beforeInit'>
|
|
765
|
-
interface ScriptRegistry {
|
|
766
|
-
${newScripts.map((i) => {
|
|
767
|
-
const key = i.import?.name.replace("useScript", "");
|
|
768
|
-
const keyLcFirst = key.substring(0, 1).toLowerCase() + key.substring(1);
|
|
769
|
-
return ` ${keyLcFirst}?: import('${i.import?.from}').${key}Input | [import('${i.import?.from}').${key}Input, NuxtUseScriptOptions]`;
|
|
770
|
-
}).join("\n")}
|
|
771
|
-
}
|
|
772
|
-
}`;
|
|
773
|
-
return types;
|
|
774
|
-
}
|
|
775
|
-
return `${types}
|
|
776
|
-
export {}`;
|
|
777
|
-
}
|
|
778
|
-
}, {
|
|
779
|
-
nuxt: true,
|
|
780
|
-
node: true
|
|
781
|
-
});
|
|
1159
|
+
registerTypeTemplates({ nuxt, config, newScripts });
|
|
782
1160
|
if (Object.keys(config.globals || {}).length || Object.keys(config.registry || {}).length) {
|
|
783
1161
|
addPluginTemplate({
|
|
784
1162
|
filename: `modules/${name.replace("/", "-")}/plugin.mjs`,
|
|
@@ -788,6 +1166,79 @@ export {}`;
|
|
|
788
1166
|
});
|
|
789
1167
|
}
|
|
790
1168
|
const { renderedScript } = setupPublicAssetStrategy(config.assets);
|
|
1169
|
+
if (firstPartyEnabled) {
|
|
1170
|
+
const proxyConfigs = getAllProxyConfigs(firstPartyCollectPrefix);
|
|
1171
|
+
const registryKeys = Object.keys(config.registry || {});
|
|
1172
|
+
const neededRoutes = {};
|
|
1173
|
+
const routePrivacyOverrides = {};
|
|
1174
|
+
const unsupportedScripts = [];
|
|
1175
|
+
for (const key of registryKeys) {
|
|
1176
|
+
const script = registryScriptsWithImport.find((s) => s.import.name.toLowerCase() === `usescript${key.toLowerCase()}`);
|
|
1177
|
+
const proxyKey = script?.proxy || void 0;
|
|
1178
|
+
if (proxyKey) {
|
|
1179
|
+
const proxyConfig = proxyConfigs[proxyKey];
|
|
1180
|
+
if (proxyConfig?.routes) {
|
|
1181
|
+
Object.assign(neededRoutes, proxyConfig.routes);
|
|
1182
|
+
for (const routePath of Object.keys(proxyConfig.routes)) {
|
|
1183
|
+
routePrivacyOverrides[routePath] = proxyConfig.privacy;
|
|
1184
|
+
}
|
|
1185
|
+
} else {
|
|
1186
|
+
unsupportedScripts.push(key);
|
|
1187
|
+
}
|
|
1188
|
+
}
|
|
1189
|
+
}
|
|
1190
|
+
if (config.registry?.posthog && typeof config.registry.posthog === "object") {
|
|
1191
|
+
const phConfig = config.registry.posthog;
|
|
1192
|
+
if (!phConfig.apiHost) {
|
|
1193
|
+
const region = phConfig.region || "us";
|
|
1194
|
+
phConfig.apiHost = region === "eu" ? `${firstPartyCollectPrefix}/ph-eu` : `${firstPartyCollectPrefix}/ph`;
|
|
1195
|
+
}
|
|
1196
|
+
}
|
|
1197
|
+
if (unsupportedScripts.length && nuxt.options.dev) {
|
|
1198
|
+
logger.warn(
|
|
1199
|
+
`First-party mode is enabled but these scripts don't support it yet: ${unsupportedScripts.join(", ")}.
|
|
1200
|
+
They will load directly from third-party servers. Request support at https://github.com/nuxt/scripts/issues`
|
|
1201
|
+
);
|
|
1202
|
+
}
|
|
1203
|
+
interceptRules = routesToInterceptRules(neededRoutes);
|
|
1204
|
+
const flatRoutes = {};
|
|
1205
|
+
for (const [path, config2] of Object.entries(neededRoutes)) {
|
|
1206
|
+
flatRoutes[path] = config2.proxy;
|
|
1207
|
+
}
|
|
1208
|
+
nuxt.options.runtimeConfig["nuxt-scripts-proxy"] = {
|
|
1209
|
+
routes: flatRoutes,
|
|
1210
|
+
privacy: firstPartyPrivacy,
|
|
1211
|
+
// undefined = use per-script defaults, set = global override
|
|
1212
|
+
routePrivacy: routePrivacyOverrides
|
|
1213
|
+
// per-script privacy from registry
|
|
1214
|
+
};
|
|
1215
|
+
if (Object.keys(neededRoutes).length) {
|
|
1216
|
+
if (nuxt.options.dev) {
|
|
1217
|
+
const routeCount = Object.keys(neededRoutes).length;
|
|
1218
|
+
const scriptsCount = registryKeys.length;
|
|
1219
|
+
const privacyLabel = firstPartyPrivacy === void 0 ? "per-script" : typeof firstPartyPrivacy === "boolean" ? firstPartyPrivacy ? "anonymize" : "passthrough" : "custom";
|
|
1220
|
+
logger.success(`First-party mode enabled for ${scriptsCount} script(s), ${routeCount} proxy route(s) configured (privacy: ${privacyLabel})`);
|
|
1221
|
+
if (logger.level >= 4) {
|
|
1222
|
+
for (const [path, config2] of Object.entries(neededRoutes)) {
|
|
1223
|
+
logger.debug(` ${path} \u2192 ${config2.proxy}`);
|
|
1224
|
+
}
|
|
1225
|
+
}
|
|
1226
|
+
}
|
|
1227
|
+
}
|
|
1228
|
+
if (isStaticPreset) {
|
|
1229
|
+
logger.warn(
|
|
1230
|
+
`First-party collection endpoints require a server runtime (detected: ${preset || "static"}).
|
|
1231
|
+
Scripts will be bundled, but collection requests will not be proxied.
|
|
1232
|
+
|
|
1233
|
+
Options:
|
|
1234
|
+
1. Configure platform rewrites (Vercel, Netlify, Cloudflare)
|
|
1235
|
+
2. Switch to server-rendered mode (ssr: true)
|
|
1236
|
+
3. Disable with firstParty: false
|
|
1237
|
+
|
|
1238
|
+
See: https://scripts.nuxt.com/docs/guides/first-party#static-hosting`
|
|
1239
|
+
);
|
|
1240
|
+
}
|
|
1241
|
+
}
|
|
791
1242
|
const moduleInstallPromises = /* @__PURE__ */ new Map();
|
|
792
1243
|
addBuildPlugin(NuxtScriptsCheckScripts(), {
|
|
793
1244
|
dev: true
|
|
@@ -795,15 +1246,18 @@ export {}`;
|
|
|
795
1246
|
addBuildPlugin(NuxtScriptBundleTransformer({
|
|
796
1247
|
scripts: registryScriptsWithImport,
|
|
797
1248
|
registryConfig: nuxt.options.runtimeConfig.public.scripts,
|
|
798
|
-
defaultBundle: config.defaultScriptOptions?.bundle,
|
|
1249
|
+
defaultBundle: firstPartyEnabled || config.defaultScriptOptions?.bundle,
|
|
1250
|
+
firstPartyEnabled,
|
|
1251
|
+
firstPartyCollectPrefix,
|
|
799
1252
|
moduleDetected(module) {
|
|
800
1253
|
if (nuxt.options.dev && module !== "@nuxt/scripts" && !moduleInstallPromises.has(module) && !hasNuxtModule(module))
|
|
801
1254
|
moduleInstallPromises.set(module, () => installNuxtModule(module));
|
|
802
1255
|
},
|
|
803
|
-
assetsBaseURL:
|
|
1256
|
+
assetsBaseURL: assetsPrefix,
|
|
804
1257
|
fallbackOnSrcOnBundleFail: config.assets?.fallbackOnSrcOnBundleFail,
|
|
805
1258
|
fetchOptions: config.assets?.fetchOptions,
|
|
806
1259
|
cacheMaxAge: config.assets?.cacheMaxAge,
|
|
1260
|
+
integrity: config.assets?.integrity,
|
|
807
1261
|
renderedScript
|
|
808
1262
|
}));
|
|
809
1263
|
nuxt.hooks.hook("build:done", async () => {
|
|
@@ -812,8 +1266,35 @@ export {}`;
|
|
|
812
1266
|
await p?.();
|
|
813
1267
|
});
|
|
814
1268
|
});
|
|
815
|
-
if (
|
|
1269
|
+
if (config.googleStaticMapsProxy?.enabled) {
|
|
1270
|
+
addServerHandler({
|
|
1271
|
+
route: "/_scripts/google-static-maps-proxy",
|
|
1272
|
+
handler: await resolvePath("./runtime/server/google-static-maps-proxy")
|
|
1273
|
+
});
|
|
1274
|
+
}
|
|
1275
|
+
addServerHandler({
|
|
1276
|
+
route: "/api/_scripts/x-embed",
|
|
1277
|
+
handler: await resolvePath("./runtime/server/x-embed")
|
|
1278
|
+
});
|
|
1279
|
+
addServerHandler({
|
|
1280
|
+
route: "/api/_scripts/x-embed-image",
|
|
1281
|
+
handler: await resolvePath("./runtime/server/x-embed-image")
|
|
1282
|
+
});
|
|
1283
|
+
addServerHandler({
|
|
1284
|
+
route: "/api/_scripts/instagram-embed",
|
|
1285
|
+
handler: await resolvePath("./runtime/server/instagram-embed")
|
|
1286
|
+
});
|
|
1287
|
+
addServerHandler({
|
|
1288
|
+
route: "/api/_scripts/instagram-embed-image",
|
|
1289
|
+
handler: await resolvePath("./runtime/server/instagram-embed-image")
|
|
1290
|
+
});
|
|
1291
|
+
addServerHandler({
|
|
1292
|
+
route: "/api/_scripts/instagram-embed-asset",
|
|
1293
|
+
handler: await resolvePath("./runtime/server/instagram-embed-asset")
|
|
1294
|
+
});
|
|
1295
|
+
if (nuxt.options.dev) {
|
|
816
1296
|
setupDevToolsUI(config, resolvePath);
|
|
1297
|
+
}
|
|
817
1298
|
}
|
|
818
1299
|
});
|
|
819
1300
|
|