@nuxt/scripts 1.0.0-beta.1 → 1.0.0-beta.2
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 +6 -0
- package/dist/client/200.html +1 -1
- package/dist/client/404.html +1 -1
- package/dist/client/_nuxt/B66N9HCo.js +1 -0
- package/dist/client/_nuxt/B8XOar-X.js +162 -0
- package/dist/client/_nuxt/{DTDyDxvR.js → DfLgoB--.js} +1 -1
- package/dist/client/_nuxt/DvH517bE.js +1 -0
- package/dist/client/_nuxt/builds/latest.json +1 -1
- package/dist/client/_nuxt/builds/meta/133a46c5-a5c1-4a63-87d1-037947a5bcdb.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 +80 -2
- package/dist/module.json +1 -1
- package/dist/module.mjs +630 -142
- package/dist/registry.mjs +10 -0
- 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/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/composables/useScript.js +24 -3
- package/dist/runtime/composables/useScriptTriggerServiceWorker.d.ts +7 -0
- package/dist/runtime/composables/useScriptTriggerServiceWorker.js +39 -0
- package/dist/runtime/plugins/sw-register.client.d.ts +2 -0
- package/dist/runtime/plugins/sw-register.client.js +12 -0
- package/dist/runtime/registry/instagram-embed.d.ts +23 -0
- package/dist/runtime/registry/instagram-embed.js +22 -0
- package/dist/runtime/registry/lemon-squeezy.d.ts +0 -1
- package/dist/runtime/registry/plausible-analytics.js +2 -2
- package/dist/runtime/registry/tiktok-pixel.d.ts +1 -0
- package/dist/runtime/registry/tiktok-pixel.js +1 -0
- package/dist/runtime/registry/x-embed.d.ts +77 -0
- package/dist/runtime/registry/x-embed.js +41 -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 +230 -0
- package/dist/runtime/server/sw-handler.d.ts +2 -0
- package/dist/runtime/server/sw-handler.js +25 -0
- package/dist/runtime/server/utils/privacy.d.ts +97 -0
- package/dist/runtime/server/utils/privacy.js +268 -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/sw/proxy-sw.template.d.ts +1 -0
- package/dist/runtime/sw/proxy-sw.template.js +54 -0
- package/dist/runtime/types.d.ts +29 -0
- package/dist/runtime/utils/pure.d.ts +13 -0
- package/dist/runtime/utils/pure.js +67 -0
- package/dist/runtime/utils.d.ts +1 -1
- package/dist/runtime/utils.js +2 -1
- package/dist/types.d.mts +1 -1
- package/package.json +27 -26
- package/dist/client/_nuxt/Bdf7Qtwg.js +0 -1
- package/dist/client/_nuxt/CoyZWCgl.js +0 -162
- package/dist/client/_nuxt/Ds1k3yKJ.js +0 -1
- package/dist/client/_nuxt/builds/meta/62574f80-71d4-4f9e-8b96-145c85230d99.json +0 -1
- package/dist/client/_nuxt/entry.BjfcJo5q.css +0 -1
- package/dist/client/_nuxt/error-404.D45Vtjcx.css +0 -1
- package/dist/client/_nuxt/error-500.BOm1rWQf.css +0 -1
package/dist/module.mjs
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
import { useNuxt, extendViteConfig, useLogger, addDevServerHandler, tryUseNuxt, logger as logger$1, addTypeTemplate, defineNuxtModule, createResolver, addImports, addComponentsDir, addTemplate, addPluginTemplate, addBuildPlugin
|
|
1
|
+
import { useNuxt, extendViteConfig, useLogger, addDevServerHandler, extendRouteRules, tryUseNuxt, logger as logger$1, addTypeTemplate, defineNuxtModule, createResolver, hasNuxtModule, addImports, addComponentsDir, addTemplate, addServerHandler, addPluginTemplate, addBuildPlugin } from '@nuxt/kit';
|
|
2
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
2
3
|
import { defu } from 'defu';
|
|
3
4
|
import { resolvePackageJSON, readPackageJSON } from 'pkg-types';
|
|
4
|
-
import {
|
|
5
|
+
import { addCustomTab } from '@nuxt/devtools-kit';
|
|
5
6
|
import { createHash } from 'node:crypto';
|
|
6
7
|
import fsp from 'node:fs/promises';
|
|
7
8
|
import { createUnplugin } from 'unplugin';
|
|
8
9
|
import MagicString from 'magic-string';
|
|
9
|
-
import {
|
|
10
|
+
import { parseAndWalk } from 'oxc-walker';
|
|
10
11
|
import { joinURL, parseURL, parseQuery, hasProtocol } from 'ufo';
|
|
11
12
|
import { hash } from 'ohash';
|
|
12
13
|
import { join, resolve, relative } from 'pathe';
|
|
@@ -15,6 +16,7 @@ import { fetch, $fetch } from 'ofetch';
|
|
|
15
16
|
import { lazyEventHandler, eventHandler, createError } from 'h3';
|
|
16
17
|
import { createStorage } from 'unstorage';
|
|
17
18
|
import fsDriver from 'unstorage/drivers/fs-lite';
|
|
19
|
+
import { rewriteScriptUrls } from '../dist/runtime/utils/pure.js';
|
|
18
20
|
import { pathToFileURL } from 'node:url';
|
|
19
21
|
import { isCI, provider } from 'std-env';
|
|
20
22
|
import { registry } from './registry.mjs';
|
|
@@ -45,20 +47,18 @@ async function setupDevToolsUI(options, resolve, nuxt = useNuxt()) {
|
|
|
45
47
|
};
|
|
46
48
|
});
|
|
47
49
|
}
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
}
|
|
61
|
-
});
|
|
50
|
+
addCustomTab({
|
|
51
|
+
// unique identifier
|
|
52
|
+
name: "nuxt-scripts",
|
|
53
|
+
// title to display in the tab
|
|
54
|
+
title: "Scripts",
|
|
55
|
+
// any icon from Iconify, or a URL to an image
|
|
56
|
+
icon: "carbon:script",
|
|
57
|
+
// iframe view
|
|
58
|
+
view: {
|
|
59
|
+
type: "iframe",
|
|
60
|
+
src: DEVTOOLS_UI_ROUTE
|
|
61
|
+
}
|
|
62
62
|
});
|
|
63
63
|
}
|
|
64
64
|
|
|
@@ -86,6 +86,9 @@ function setupPublicAssetStrategy(options = {}) {
|
|
|
86
86
|
const scriptDescriptor = renderedScript.get(join(assetsBaseURL, event.path.slice(1)));
|
|
87
87
|
if (!scriptDescriptor || scriptDescriptor instanceof Error)
|
|
88
88
|
throw createError({ statusCode: 404 });
|
|
89
|
+
if (scriptDescriptor.content) {
|
|
90
|
+
return scriptDescriptor.content;
|
|
91
|
+
}
|
|
89
92
|
const key = `bundle:${filename}`;
|
|
90
93
|
let res = await storage.getItemRaw(key);
|
|
91
94
|
if (!res) {
|
|
@@ -97,31 +100,204 @@ function setupPublicAssetStrategy(options = {}) {
|
|
|
97
100
|
})
|
|
98
101
|
});
|
|
99
102
|
if (nuxt.options.dev) {
|
|
100
|
-
|
|
101
|
-
nuxt.options.routeRules[joinURL(assetsBaseURL, "**")] = {
|
|
103
|
+
extendRouteRules(joinURL(assetsBaseURL, "**"), {
|
|
102
104
|
cache: {
|
|
103
105
|
maxAge: ONE_YEAR_IN_SECONDS
|
|
104
106
|
}
|
|
105
|
-
};
|
|
107
|
+
});
|
|
106
108
|
}
|
|
107
|
-
nuxt.options.nitro.publicAssets ||= [];
|
|
108
109
|
const cacheDir = join(nuxt.options.buildDir, "cache", "scripts");
|
|
109
|
-
nuxt.
|
|
110
|
-
|
|
111
|
-
publicAssets
|
|
110
|
+
nuxt.hook("nitro:config", (nitroConfig) => {
|
|
111
|
+
nitroConfig.publicAssets ||= [];
|
|
112
|
+
nitroConfig.publicAssets.push({
|
|
112
113
|
dir: cacheDir,
|
|
113
114
|
maxAge: ONE_YEAR_IN_SECONDS,
|
|
114
115
|
baseURL: assetsBaseURL
|
|
115
|
-
}
|
|
116
|
-
prerender
|
|
117
|
-
|
|
118
|
-
|
|
116
|
+
});
|
|
117
|
+
nitroConfig.prerender ||= {};
|
|
118
|
+
nitroConfig.prerender.ignore ||= [];
|
|
119
|
+
nitroConfig.prerender.ignore.push(assetsBaseURL);
|
|
119
120
|
});
|
|
120
121
|
return {
|
|
121
122
|
renderedScript
|
|
122
123
|
};
|
|
123
124
|
}
|
|
124
125
|
|
|
126
|
+
function buildProxyConfig(collectPrefix) {
|
|
127
|
+
return {
|
|
128
|
+
googleAnalytics: {
|
|
129
|
+
rewrite: [
|
|
130
|
+
// Modern gtag.js uses www.google.com/g/collect
|
|
131
|
+
{ from: "www.google.com/g/collect", to: `${collectPrefix}/ga/g/collect` },
|
|
132
|
+
// Older gtag.js constructs URLs dynamically: "https://"+(subdomain)+".google-analytics.com/g/collect"
|
|
133
|
+
// We need to catch the suffix pattern with leading dot
|
|
134
|
+
{ from: ".google-analytics.com/g/collect", to: `${collectPrefix}/ga/g/collect` },
|
|
135
|
+
{ from: ".analytics.google.com/g/collect", to: `${collectPrefix}/ga/g/collect` },
|
|
136
|
+
// Full domain patterns for static URLs
|
|
137
|
+
{ from: "www.google-analytics.com/g/collect", to: `${collectPrefix}/ga/g/collect` },
|
|
138
|
+
{ from: "analytics.google.com/g/collect", to: `${collectPrefix}/ga/g/collect` },
|
|
139
|
+
// Legacy endpoints still used by some scripts
|
|
140
|
+
{ from: "www.google-analytics.com", to: `${collectPrefix}/ga` },
|
|
141
|
+
{ from: "analytics.google.com", to: `${collectPrefix}/ga` },
|
|
142
|
+
// DoubleClick tracking (used by GA4 for ads/conversions)
|
|
143
|
+
{ from: "stats.g.doubleclick.net/g/collect", to: `${collectPrefix}/ga/g/collect` },
|
|
144
|
+
{ from: "stats.g.doubleclick.net", to: `${collectPrefix}/ga-dc` },
|
|
145
|
+
// Google Ads/Syndication tracking
|
|
146
|
+
{ from: "pagead2.googlesyndication.com", to: `${collectPrefix}/ga-syn` },
|
|
147
|
+
{ from: "www.googleadservices.com", to: `${collectPrefix}/ga-ads` },
|
|
148
|
+
{ from: "googleads.g.doubleclick.net", to: `${collectPrefix}/ga-gads` }
|
|
149
|
+
],
|
|
150
|
+
routes: {
|
|
151
|
+
[`${collectPrefix}/ga/**`]: { proxy: "https://www.google-analytics.com/**" },
|
|
152
|
+
[`${collectPrefix}/ga-dc/**`]: { proxy: "https://stats.g.doubleclick.net/**" },
|
|
153
|
+
[`${collectPrefix}/ga-syn/**`]: { proxy: "https://pagead2.googlesyndication.com/**" },
|
|
154
|
+
[`${collectPrefix}/ga-ads/**`]: { proxy: "https://www.googleadservices.com/**" },
|
|
155
|
+
[`${collectPrefix}/ga-gads/**`]: { proxy: "https://googleads.g.doubleclick.net/**" }
|
|
156
|
+
}
|
|
157
|
+
},
|
|
158
|
+
googleTagManager: {
|
|
159
|
+
rewrite: [
|
|
160
|
+
{ from: "www.googletagmanager.com", to: `${collectPrefix}/gtm` }
|
|
161
|
+
],
|
|
162
|
+
routes: {
|
|
163
|
+
[`${collectPrefix}/gtm/**`]: { proxy: "https://www.googletagmanager.com/**" }
|
|
164
|
+
}
|
|
165
|
+
},
|
|
166
|
+
metaPixel: {
|
|
167
|
+
rewrite: [
|
|
168
|
+
// SDK script loading
|
|
169
|
+
{ from: "connect.facebook.net", to: `${collectPrefix}/meta` },
|
|
170
|
+
// Tracking pixel endpoint (www and non-www)
|
|
171
|
+
{ from: "www.facebook.com/tr", to: `${collectPrefix}/meta-tr` },
|
|
172
|
+
{ from: "facebook.com/tr", to: `${collectPrefix}/meta-tr` },
|
|
173
|
+
// Additional Meta tracking domains
|
|
174
|
+
{ from: "pixel.facebook.com", to: `${collectPrefix}/meta-px` },
|
|
175
|
+
{ from: "www.facebook.com/plugins", to: `${collectPrefix}/meta-plugins` }
|
|
176
|
+
],
|
|
177
|
+
routes: {
|
|
178
|
+
[`${collectPrefix}/meta/**`]: { proxy: "https://connect.facebook.net/**" },
|
|
179
|
+
[`${collectPrefix}/meta-tr/**`]: { proxy: "https://www.facebook.com/tr/**" },
|
|
180
|
+
[`${collectPrefix}/meta-px/**`]: { proxy: "https://pixel.facebook.com/**" },
|
|
181
|
+
[`${collectPrefix}/meta-plugins/**`]: { proxy: "https://www.facebook.com/plugins/**" }
|
|
182
|
+
}
|
|
183
|
+
},
|
|
184
|
+
tiktokPixel: {
|
|
185
|
+
rewrite: [
|
|
186
|
+
{ from: "analytics.tiktok.com", to: `${collectPrefix}/tiktok` }
|
|
187
|
+
],
|
|
188
|
+
routes: {
|
|
189
|
+
[`${collectPrefix}/tiktok/**`]: { proxy: "https://analytics.tiktok.com/**" }
|
|
190
|
+
}
|
|
191
|
+
},
|
|
192
|
+
segment: {
|
|
193
|
+
rewrite: [
|
|
194
|
+
{ from: "api.segment.io", to: `${collectPrefix}/segment` },
|
|
195
|
+
{ from: "cdn.segment.com", to: `${collectPrefix}/segment-cdn` }
|
|
196
|
+
],
|
|
197
|
+
routes: {
|
|
198
|
+
[`${collectPrefix}/segment/**`]: { proxy: "https://api.segment.io/**" },
|
|
199
|
+
[`${collectPrefix}/segment-cdn/**`]: { proxy: "https://cdn.segment.com/**" }
|
|
200
|
+
}
|
|
201
|
+
},
|
|
202
|
+
xPixel: {
|
|
203
|
+
rewrite: [
|
|
204
|
+
{ from: "analytics.twitter.com", to: `${collectPrefix}/x` },
|
|
205
|
+
{ from: "t.co", to: `${collectPrefix}/x-t` }
|
|
206
|
+
],
|
|
207
|
+
routes: {
|
|
208
|
+
[`${collectPrefix}/x/**`]: { proxy: "https://analytics.twitter.com/**" },
|
|
209
|
+
[`${collectPrefix}/x-t/**`]: { proxy: "https://t.co/**" }
|
|
210
|
+
}
|
|
211
|
+
},
|
|
212
|
+
snapchatPixel: {
|
|
213
|
+
rewrite: [
|
|
214
|
+
{ from: "tr.snapchat.com", to: `${collectPrefix}/snap` }
|
|
215
|
+
],
|
|
216
|
+
routes: {
|
|
217
|
+
[`${collectPrefix}/snap/**`]: { proxy: "https://tr.snapchat.com/**" }
|
|
218
|
+
}
|
|
219
|
+
},
|
|
220
|
+
redditPixel: {
|
|
221
|
+
rewrite: [
|
|
222
|
+
{ from: "alb.reddit.com", to: `${collectPrefix}/reddit` }
|
|
223
|
+
],
|
|
224
|
+
routes: {
|
|
225
|
+
[`${collectPrefix}/reddit/**`]: { proxy: "https://alb.reddit.com/**" }
|
|
226
|
+
}
|
|
227
|
+
},
|
|
228
|
+
clarity: {
|
|
229
|
+
rewrite: [
|
|
230
|
+
// Main clarity domain
|
|
231
|
+
{ from: "www.clarity.ms", to: `${collectPrefix}/clarity` },
|
|
232
|
+
// Script loader (the actual SDK is loaded from here)
|
|
233
|
+
{ from: "scripts.clarity.ms", to: `${collectPrefix}/clarity-scripts` },
|
|
234
|
+
// Data collection endpoint
|
|
235
|
+
{ from: "d.clarity.ms", to: `${collectPrefix}/clarity-data` },
|
|
236
|
+
// Event collection endpoint
|
|
237
|
+
{ from: "e.clarity.ms", to: `${collectPrefix}/clarity-events` }
|
|
238
|
+
],
|
|
239
|
+
routes: {
|
|
240
|
+
[`${collectPrefix}/clarity/**`]: { proxy: "https://www.clarity.ms/**" },
|
|
241
|
+
[`${collectPrefix}/clarity-scripts/**`]: { proxy: "https://scripts.clarity.ms/**" },
|
|
242
|
+
[`${collectPrefix}/clarity-data/**`]: { proxy: "https://d.clarity.ms/**" },
|
|
243
|
+
[`${collectPrefix}/clarity-events/**`]: { proxy: "https://e.clarity.ms/**" }
|
|
244
|
+
}
|
|
245
|
+
},
|
|
246
|
+
hotjar: {
|
|
247
|
+
rewrite: [
|
|
248
|
+
// Static assets
|
|
249
|
+
{ from: "static.hotjar.com", to: `${collectPrefix}/hotjar` },
|
|
250
|
+
// Script loader (bootstrap script loads the main SDK from here)
|
|
251
|
+
{ from: "script.hotjar.com", to: `${collectPrefix}/hotjar-script` },
|
|
252
|
+
// Configuration/variables
|
|
253
|
+
{ from: "vars.hotjar.com", to: `${collectPrefix}/hotjar-vars` },
|
|
254
|
+
// Data ingestion endpoint
|
|
255
|
+
{ from: "in.hotjar.com", to: `${collectPrefix}/hotjar-in` },
|
|
256
|
+
// Video capture
|
|
257
|
+
{ from: "vc.hotjar.com", to: `${collectPrefix}/hotjar-vc` },
|
|
258
|
+
// Metrics/telemetry
|
|
259
|
+
{ from: "metrics.hotjar.io", to: `${collectPrefix}/hotjar-metrics` },
|
|
260
|
+
// Insights (ContentSquare integration)
|
|
261
|
+
{ from: "insights.hotjar.com", to: `${collectPrefix}/hotjar-insights` }
|
|
262
|
+
],
|
|
263
|
+
routes: {
|
|
264
|
+
[`${collectPrefix}/hotjar/**`]: { proxy: "https://static.hotjar.com/**" },
|
|
265
|
+
[`${collectPrefix}/hotjar-script/**`]: { proxy: "https://script.hotjar.com/**" },
|
|
266
|
+
[`${collectPrefix}/hotjar-vars/**`]: { proxy: "https://vars.hotjar.com/**" },
|
|
267
|
+
[`${collectPrefix}/hotjar-in/**`]: { proxy: "https://in.hotjar.com/**" },
|
|
268
|
+
[`${collectPrefix}/hotjar-vc/**`]: { proxy: "https://vc.hotjar.com/**" },
|
|
269
|
+
[`${collectPrefix}/hotjar-metrics/**`]: { proxy: "https://metrics.hotjar.io/**" },
|
|
270
|
+
[`${collectPrefix}/hotjar-insights/**`]: { proxy: "https://insights.hotjar.com/**" }
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
function getProxyConfig(key, collectPrefix) {
|
|
276
|
+
const configs = buildProxyConfig(collectPrefix);
|
|
277
|
+
return configs[key];
|
|
278
|
+
}
|
|
279
|
+
function getAllProxyConfigs(collectPrefix) {
|
|
280
|
+
return buildProxyConfig(collectPrefix);
|
|
281
|
+
}
|
|
282
|
+
function getSWInterceptRules(collectPrefix) {
|
|
283
|
+
const configs = buildProxyConfig(collectPrefix);
|
|
284
|
+
const rules = [];
|
|
285
|
+
for (const config of Object.values(configs)) {
|
|
286
|
+
if (!config.routes)
|
|
287
|
+
continue;
|
|
288
|
+
for (const [localPath, { proxy }] of Object.entries(config.routes)) {
|
|
289
|
+
const match = proxy.match(/^https?:\/\/([^/]+)(\/.*)?\/\*\*$/);
|
|
290
|
+
if (match?.[1]) {
|
|
291
|
+
const domain = match[1];
|
|
292
|
+
const pathPrefix = match[2] || "";
|
|
293
|
+
const target = localPath.replace(/\/\*\*$/, "");
|
|
294
|
+
rules.push({ pattern: domain, pathPrefix, target });
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
return rules;
|
|
299
|
+
}
|
|
300
|
+
|
|
125
301
|
function isVue(id, opts = {}) {
|
|
126
302
|
const { search } = parseURL(decodeURIComponent(pathToFileURL(id).href));
|
|
127
303
|
if (id.endsWith(".vue") && !search) {
|
|
@@ -178,7 +354,7 @@ function normalizeScriptData(src, assetsBaseURL = "/_scripts") {
|
|
|
178
354
|
return { url: src };
|
|
179
355
|
}
|
|
180
356
|
async function downloadScript(opts, renderedScript, fetchOptions, cacheMaxAge) {
|
|
181
|
-
const { src, url, filename, forceDownload, integrity } = opts;
|
|
357
|
+
const { src, url, filename, forceDownload, integrity, proxyRewrites } = opts;
|
|
182
358
|
if (src === url || !filename) {
|
|
183
359
|
return;
|
|
184
360
|
}
|
|
@@ -186,7 +362,8 @@ async function downloadScript(opts, renderedScript, fetchOptions, cacheMaxAge) {
|
|
|
186
362
|
const scriptContent = renderedScript.get(src);
|
|
187
363
|
let res = scriptContent instanceof Error ? void 0 : scriptContent?.content;
|
|
188
364
|
if (!res) {
|
|
189
|
-
const
|
|
365
|
+
const proxyRewritesHash = proxyRewrites?.length ? `-${hash(proxyRewrites)}` : "";
|
|
366
|
+
const cacheKey = proxyRewrites?.length ? `bundle-proxy:${filename.replace(".js", `${proxyRewritesHash}.js`)}` : `bundle:${filename}`;
|
|
190
367
|
const shouldUseCache = !forceDownload && await storage.hasItem(cacheKey) && !await isCacheExpired(storage, filename, cacheMaxAge);
|
|
191
368
|
if (shouldUseCache) {
|
|
192
369
|
const cachedContent = await storage.getItemRaw(cacheKey);
|
|
@@ -212,8 +389,15 @@ async function downloadScript(opts, renderedScript, fetchOptions, cacheMaxAge) {
|
|
|
212
389
|
size = contentLength ? Number(contentLength) / 1024 : 0;
|
|
213
390
|
return Buffer.from(r._data || await r.arrayBuffer());
|
|
214
391
|
});
|
|
215
|
-
const integrityHash = integrity && res ? calculateIntegrity(res, integrity === true ? "sha384" : integrity) : void 0;
|
|
216
392
|
await storage.setItemRaw(`bundle:${filename}`, res);
|
|
393
|
+
if (proxyRewrites?.length && res) {
|
|
394
|
+
const content = res.toString("utf-8");
|
|
395
|
+
const rewritten = rewriteScriptUrls(content, proxyRewrites);
|
|
396
|
+
res = Buffer.from(rewritten, "utf-8");
|
|
397
|
+
logger.debug(`Rewrote ${proxyRewrites.length} URL patterns in ${filename}`);
|
|
398
|
+
}
|
|
399
|
+
const integrityHash = integrity && res ? calculateIntegrity(res, integrity === true ? "sha384" : integrity) : void 0;
|
|
400
|
+
await storage.setItemRaw(cacheKey, res);
|
|
217
401
|
await storage.setItem(`bundle-meta:${filename}`, {
|
|
218
402
|
timestamp: Date.now(),
|
|
219
403
|
src,
|
|
@@ -262,16 +446,21 @@ function NuxtScriptBundleTransformer(options = {
|
|
|
262
446
|
return createUnplugin(() => {
|
|
263
447
|
return {
|
|
264
448
|
name: "nuxt:scripts:bundler-transformer",
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
449
|
+
transform: {
|
|
450
|
+
filter: {
|
|
451
|
+
id: {
|
|
452
|
+
include: [/\.vue/, /\.[cm]?[jt]sx?$/],
|
|
453
|
+
exclude: [/\.(?:test|spec)\./]
|
|
454
|
+
}
|
|
455
|
+
},
|
|
456
|
+
async handler(code, id) {
|
|
457
|
+
if (!isVue(id, { type: ["template", "script"] }) && !isJS(id))
|
|
458
|
+
return;
|
|
459
|
+
if (!code.includes("useScript"))
|
|
460
|
+
return;
|
|
461
|
+
const s = new MagicString(code);
|
|
462
|
+
const deferredOps = [];
|
|
463
|
+
parseAndWalk(code, id, function(_node) {
|
|
275
464
|
const calleeName = _node.callee?.name;
|
|
276
465
|
if (!calleeName)
|
|
277
466
|
return;
|
|
@@ -281,6 +470,11 @@ function NuxtScriptBundleTransformer(options = {
|
|
|
281
470
|
const node = _node;
|
|
282
471
|
let scriptSrcNode;
|
|
283
472
|
let src;
|
|
473
|
+
let registryKey;
|
|
474
|
+
if (fnName !== "useScript") {
|
|
475
|
+
const baseName = fnName.replace(/^useScript/, "");
|
|
476
|
+
registryKey = baseName.length > 0 ? baseName.charAt(0).toLowerCase() + baseName.slice(1) : void 0;
|
|
477
|
+
}
|
|
284
478
|
if (fnName === "useScript") {
|
|
285
479
|
if (node.arguments[0]?.type === "Literal") {
|
|
286
480
|
scriptSrcNode = node.arguments[0];
|
|
@@ -297,9 +491,7 @@ function NuxtScriptBundleTransformer(options = {
|
|
|
297
491
|
}
|
|
298
492
|
if (!registryNode.scriptBundling && !registryNode.src)
|
|
299
493
|
return;
|
|
300
|
-
const
|
|
301
|
-
const registryKey = baseName.length > 0 ? baseName.charAt(0).toLowerCase() + baseName.slice(1) : "";
|
|
302
|
-
const registryConfig = options.registryConfig?.[registryKey] || {};
|
|
494
|
+
const registryConfig = options.registryConfig?.[registryKey || ""] || {};
|
|
303
495
|
const fnArg0 = {};
|
|
304
496
|
if (node.arguments[0]?.type === "ObjectExpression") {
|
|
305
497
|
const optionsNode = node.arguments[0];
|
|
@@ -319,6 +511,8 @@ function NuxtScriptBundleTransformer(options = {
|
|
|
319
511
|
src = registryNode.scriptBundling && registryNode.scriptBundling(mergedOptions);
|
|
320
512
|
if (src === false)
|
|
321
513
|
return;
|
|
514
|
+
if (!src && registryNode.src)
|
|
515
|
+
src = registryNode.src;
|
|
322
516
|
}
|
|
323
517
|
}
|
|
324
518
|
if (!scriptSrcNode && !src) {
|
|
@@ -333,8 +527,7 @@ function NuxtScriptBundleTransformer(options = {
|
|
|
333
527
|
if (bundleProperty && bundleProperty.value.type === "Literal") {
|
|
334
528
|
const bundleValue = bundleProperty.value.value;
|
|
335
529
|
if (bundleValue === true || bundleValue === "force" || String(bundleValue) === "true") {
|
|
336
|
-
|
|
337
|
-
s.overwrite(valueNode.start, valueNode.end, `'unsupported'`);
|
|
530
|
+
s.overwrite(bundleProperty.value.start, bundleProperty.value.end, `'unsupported'`);
|
|
338
531
|
}
|
|
339
532
|
}
|
|
340
533
|
}
|
|
@@ -351,8 +544,7 @@ function NuxtScriptBundleTransformer(options = {
|
|
|
351
544
|
(p) => (p.key?.name === "bundle" || p.key?.value === "bundle") && p.type === "Property"
|
|
352
545
|
);
|
|
353
546
|
if (bundleProperty && bundleProperty.value.type === "Literal") {
|
|
354
|
-
const
|
|
355
|
-
const bundleValue = value.value;
|
|
547
|
+
const bundleValue = bundleProperty.value.value;
|
|
356
548
|
if (bundleValue !== true && bundleValue !== "force" && String(bundleValue) !== "true") {
|
|
357
549
|
canBundle = false;
|
|
358
550
|
return;
|
|
@@ -380,81 +572,104 @@ function NuxtScriptBundleTransformer(options = {
|
|
|
380
572
|
canBundle = bundleValue === true || bundleValue === "force" || String(bundleValue) === "true";
|
|
381
573
|
forceDownload = bundleValue === "force";
|
|
382
574
|
}
|
|
575
|
+
const firstPartyOption = scriptOptions?.value.properties?.find((prop) => {
|
|
576
|
+
return prop.type === "Property" && prop.key?.name === "firstParty" && prop.value.type === "Literal";
|
|
577
|
+
});
|
|
578
|
+
let firstPartyOptOut = firstPartyOption?.value.value === false;
|
|
579
|
+
if (!firstPartyOptOut && node.arguments[1]?.type === "ObjectExpression") {
|
|
580
|
+
const secondArgFirstPartyProp = node.arguments[1].properties.find(
|
|
581
|
+
(p) => p.type === "Property" && p.key?.name === "firstParty" && p.value.type === "Literal"
|
|
582
|
+
);
|
|
583
|
+
firstPartyOptOut = secondArgFirstPartyProp?.value.value === false;
|
|
584
|
+
}
|
|
585
|
+
if (!firstPartyOptOut && node.arguments[0]?.type === "ObjectExpression") {
|
|
586
|
+
const firstArgFirstPartyProp = node.arguments[0].properties.find(
|
|
587
|
+
(p) => p.type === "Property" && p.key?.name === "firstParty" && p.value.type === "Literal"
|
|
588
|
+
);
|
|
589
|
+
firstPartyOptOut = firstArgFirstPartyProp?.value.value === false;
|
|
590
|
+
}
|
|
383
591
|
if (canBundle) {
|
|
384
592
|
const { url: _url, filename } = normalizeScriptData(src, options.assetsBaseURL);
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
url
|
|
392
|
-
}
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
593
|
+
const script = options.scripts?.find((s2) => s2.import.name === fnName);
|
|
594
|
+
const proxyConfigKey = script?.proxy !== false ? script?.proxy || registryKey : void 0;
|
|
595
|
+
const proxyRewrites = options.firstPartyEnabled && !firstPartyOptOut && proxyConfigKey && options.firstPartyCollectPrefix ? getProxyConfig(proxyConfigKey, options.firstPartyCollectPrefix)?.rewrite : void 0;
|
|
596
|
+
deferredOps.push(async () => {
|
|
597
|
+
let url = _url;
|
|
598
|
+
try {
|
|
599
|
+
await downloadScript({ src, url, filename, forceDownload, proxyRewrites, integrity: options.integrity }, renderedScript, options.fetchOptions, options.cacheMaxAge);
|
|
600
|
+
} catch (e) {
|
|
601
|
+
if (options.fallbackOnSrcOnBundleFail) {
|
|
602
|
+
logger.warn(`[Nuxt Scripts: Bundle Transformer] Failed to bundle ${src}. Fallback to remote loading.`);
|
|
603
|
+
url = src;
|
|
604
|
+
} else {
|
|
605
|
+
const errorMessage = e?.message || "Unknown error";
|
|
606
|
+
if (errorMessage.includes("timeout") || errorMessage.includes("network") || errorMessage.includes("ENOTFOUND") || errorMessage.includes("certificate")) {
|
|
607
|
+
logger.error(`[Nuxt Scripts: Bundle Transformer] Network issue while bundling ${src}: ${errorMessage}`);
|
|
608
|
+
logger.error(`[Nuxt Scripts: Bundle Transformer] Tip: Set 'fallbackOnSrcOnBundleFail: true' in module options or disable bundling in Docker environments`);
|
|
609
|
+
}
|
|
610
|
+
throw e;
|
|
397
611
|
}
|
|
398
|
-
throw e;
|
|
399
612
|
}
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
logger.warn(`[Nuxt Scripts: Bundle Transformer] Failed to bundle ${src}.`);
|
|
406
|
-
}
|
|
407
|
-
const scriptMeta = renderedScript.get(url);
|
|
408
|
-
const integrityHash = scriptMeta instanceof Error ? void 0 : scriptMeta?.integrity;
|
|
409
|
-
if (scriptSrcNode) {
|
|
410
|
-
if (integrityHash && fnName === "useScript" && node.arguments[0]?.type === "Literal") {
|
|
411
|
-
s.overwrite(scriptSrcNode.start, scriptSrcNode.end, `{ src: '${url}', integrity: '${integrityHash}', crossorigin: 'anonymous' }`);
|
|
412
|
-
} else if (integrityHash && fnName === "useScript" && node.arguments[0]?.type === "ObjectExpression") {
|
|
413
|
-
s.overwrite(scriptSrcNode.start, scriptSrcNode.end, `'${url}'`);
|
|
414
|
-
const objArg = node.arguments[0];
|
|
415
|
-
s.appendLeft(objArg.end - 1, `, integrity: '${integrityHash}', crossorigin: 'anonymous'`);
|
|
416
|
-
} else {
|
|
417
|
-
s.overwrite(scriptSrcNode.start, scriptSrcNode.end, `'${url}'`);
|
|
613
|
+
if (src === url) {
|
|
614
|
+
if (src && src.startsWith("/"))
|
|
615
|
+
logger.warn(`[Nuxt Scripts: Bundle Transformer] Relative scripts are already bundled. Skipping bundling for \`${src}\`.`);
|
|
616
|
+
else
|
|
617
|
+
logger.warn(`[Nuxt Scripts: Bundle Transformer] Failed to bundle ${src}.`);
|
|
418
618
|
}
|
|
419
|
-
|
|
420
|
-
const
|
|
421
|
-
if (
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
619
|
+
const scriptMeta = renderedScript.get(url);
|
|
620
|
+
const integrityHash = scriptMeta instanceof Error ? void 0 : scriptMeta?.integrity;
|
|
621
|
+
if (scriptSrcNode) {
|
|
622
|
+
if (integrityHash && fnName === "useScript" && node.arguments[0]?.type === "Literal") {
|
|
623
|
+
s.overwrite(scriptSrcNode.start, scriptSrcNode.end, `{ src: '${url}', integrity: '${integrityHash}', crossorigin: 'anonymous' }`);
|
|
624
|
+
} else if (integrityHash && fnName === "useScript" && node.arguments[0]?.type === "ObjectExpression") {
|
|
625
|
+
s.overwrite(scriptSrcNode.start, scriptSrcNode.end, `'${url}'`);
|
|
626
|
+
s.appendLeft(node.arguments[0].end - 1, `, integrity: '${integrityHash}', crossorigin: 'anonymous'`);
|
|
627
|
+
} else {
|
|
628
|
+
s.overwrite(scriptSrcNode.start, scriptSrcNode.end, `'${url}'`);
|
|
629
|
+
}
|
|
630
|
+
} else {
|
|
631
|
+
const integrityProps = integrityHash ? `, integrity: '${integrityHash}', crossorigin: 'anonymous'` : "";
|
|
632
|
+
if (node.arguments[0]) {
|
|
633
|
+
const optionsNode = node.arguments[0];
|
|
634
|
+
const scriptInputProperty = optionsNode.properties.find(
|
|
635
|
+
(p) => p.key?.name === "scriptInput" || p.key?.value === "scriptInput"
|
|
636
|
+
);
|
|
637
|
+
if (scriptInputProperty) {
|
|
638
|
+
const scriptInput = scriptInputProperty.value;
|
|
639
|
+
if (scriptInput.type === "ObjectExpression") {
|
|
640
|
+
const srcProperty = scriptInput.properties.find(
|
|
641
|
+
(p) => p.key?.name === "src" || p.key?.value === "src"
|
|
642
|
+
);
|
|
643
|
+
if (srcProperty) {
|
|
644
|
+
s.overwrite(srcProperty.value.start, srcProperty.value.end, `'${url}'`);
|
|
645
|
+
if (integrityHash)
|
|
646
|
+
s.appendLeft(scriptInput.end - 1, integrityProps);
|
|
647
|
+
} else {
|
|
648
|
+
s.appendRight(scriptInput.end - 1, `, src: '${url}'${integrityProps}`);
|
|
649
|
+
}
|
|
438
650
|
}
|
|
651
|
+
} else {
|
|
652
|
+
s.appendRight(node.arguments[0].start + 1, ` scriptInput: { src: '${url}'${integrityProps} }, `);
|
|
439
653
|
}
|
|
440
654
|
} else {
|
|
441
|
-
s.appendRight(node.
|
|
655
|
+
s.appendRight(node.callee.end, `({ scriptInput: { src: '${url}'${integrityProps} } })`);
|
|
442
656
|
}
|
|
443
|
-
} else {
|
|
444
|
-
s.appendRight(node.callee.end, `({ scriptInput: { src: '${url}'${integrityProps} } })`);
|
|
445
657
|
}
|
|
446
|
-
}
|
|
658
|
+
});
|
|
447
659
|
}
|
|
448
660
|
}
|
|
449
661
|
}
|
|
450
662
|
}
|
|
663
|
+
});
|
|
664
|
+
for (const op of deferredOps) {
|
|
665
|
+
await op();
|
|
666
|
+
}
|
|
667
|
+
if (s.hasChanged()) {
|
|
668
|
+
return {
|
|
669
|
+
code: s.toString(),
|
|
670
|
+
map: s.generateMap({ includeContent: true, source: id })
|
|
671
|
+
};
|
|
451
672
|
}
|
|
452
|
-
});
|
|
453
|
-
if (s.hasChanged()) {
|
|
454
|
-
return {
|
|
455
|
-
code: s.toString(),
|
|
456
|
-
map: s.generateMap({ includeContent: true, source: id })
|
|
457
|
-
};
|
|
458
673
|
}
|
|
459
674
|
}
|
|
460
675
|
};
|
|
@@ -505,17 +720,18 @@ function NuxtScriptsCheckScripts() {
|
|
|
505
720
|
return createUnplugin(() => {
|
|
506
721
|
return {
|
|
507
722
|
name: "nuxt-scripts:check-scripts",
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
723
|
+
transform: {
|
|
724
|
+
filter: {
|
|
725
|
+
id: /\.vue/
|
|
726
|
+
},
|
|
727
|
+
handler(code, id) {
|
|
728
|
+
if (!isVue(id, { type: ["script"] }))
|
|
729
|
+
return;
|
|
730
|
+
if (!code.includes("useScript"))
|
|
731
|
+
return;
|
|
732
|
+
let nameNode;
|
|
733
|
+
let errorNode;
|
|
734
|
+
parseAndWalk(code, id, function(_node) {
|
|
519
735
|
if (_node.type === "VariableDeclaration" && _node.declarations?.[0]?.id?.type === "ObjectPattern") {
|
|
520
736
|
const objPattern = _node.declarations[0]?.id;
|
|
521
737
|
for (const property of objPattern.properties) {
|
|
@@ -545,10 +761,10 @@ function NuxtScriptsCheckScripts() {
|
|
|
545
761
|
}
|
|
546
762
|
}
|
|
547
763
|
}
|
|
764
|
+
});
|
|
765
|
+
if (errorNode) {
|
|
766
|
+
return this.error(new Error("You can't use a top-level await on $script as it will never resolve."));
|
|
548
767
|
}
|
|
549
|
-
});
|
|
550
|
-
if (errorNode) {
|
|
551
|
-
return this.error(new Error("You can't use a top-level await on $script as it will never resolve."));
|
|
552
768
|
}
|
|
553
769
|
}
|
|
554
770
|
};
|
|
@@ -596,6 +812,7 @@ export {}`;
|
|
|
596
812
|
function templateTriggerResolver(defaultScriptOptions) {
|
|
597
813
|
const needsIdleTimeout = defaultScriptOptions?.trigger && typeof defaultScriptOptions.trigger === "object" && "idleTimeout" in defaultScriptOptions.trigger;
|
|
598
814
|
const needsInteraction = defaultScriptOptions?.trigger && typeof defaultScriptOptions.trigger === "object" && "interaction" in defaultScriptOptions.trigger;
|
|
815
|
+
const needsServiceWorker = defaultScriptOptions?.trigger && typeof defaultScriptOptions.trigger === "object" && "serviceWorker" in defaultScriptOptions.trigger;
|
|
599
816
|
const imports = [];
|
|
600
817
|
if (needsIdleTimeout) {
|
|
601
818
|
imports.push(`import { useScriptTriggerIdleTimeout } from '#nuxt-scripts/composables/useScriptTriggerIdleTimeout'`);
|
|
@@ -603,11 +820,15 @@ function templateTriggerResolver(defaultScriptOptions) {
|
|
|
603
820
|
if (needsInteraction) {
|
|
604
821
|
imports.push(`import { useScriptTriggerInteraction } from '#nuxt-scripts/composables/useScriptTriggerInteraction'`);
|
|
605
822
|
}
|
|
823
|
+
if (needsServiceWorker) {
|
|
824
|
+
imports.push(`import { useScriptTriggerServiceWorker } from '#nuxt-scripts/composables/useScriptTriggerServiceWorker'`);
|
|
825
|
+
}
|
|
606
826
|
return [
|
|
607
827
|
...imports,
|
|
608
828
|
`export function resolveTrigger(trigger) {`,
|
|
609
829
|
needsIdleTimeout ? ` if ('idleTimeout' in trigger) return useScriptTriggerIdleTimeout({ timeout: trigger.idleTimeout })` : "",
|
|
610
830
|
needsInteraction ? ` if ('interaction' in trigger) return useScriptTriggerInteraction({ events: trigger.interaction })` : "",
|
|
831
|
+
needsServiceWorker ? ` if ('serviceWorker' in trigger) return useScriptTriggerServiceWorker()` : "",
|
|
611
832
|
` return null`,
|
|
612
833
|
`}`
|
|
613
834
|
].filter(Boolean).join("\n");
|
|
@@ -624,6 +845,9 @@ function resolveTriggerForTemplate(trigger) {
|
|
|
624
845
|
if ("interaction" in trigger) {
|
|
625
846
|
return `useScriptTriggerInteraction({ events: ${JSON.stringify(trigger.interaction)} })`;
|
|
626
847
|
}
|
|
848
|
+
if ("serviceWorker" in trigger) {
|
|
849
|
+
return `useScriptTriggerServiceWorker()`;
|
|
850
|
+
}
|
|
627
851
|
}
|
|
628
852
|
return null;
|
|
629
853
|
}
|
|
@@ -634,27 +858,34 @@ function templatePlugin(config, registry) {
|
|
|
634
858
|
}
|
|
635
859
|
const imports = [];
|
|
636
860
|
const inits = [];
|
|
861
|
+
const resolvedRegistryKeys = [];
|
|
637
862
|
let needsIdleTimeoutImport = false;
|
|
638
863
|
let needsInteractionImport = false;
|
|
864
|
+
let needsServiceWorkerImport = false;
|
|
639
865
|
for (const [k, c] of Object.entries(config.registry || {})) {
|
|
640
|
-
const importDefinition = registry.find((i) => i.import.name === `useScript${k.substring(0, 1).toUpperCase() + k.substring(1)}`);
|
|
866
|
+
const importDefinition = registry.find((i) => i.proxy === k || i.import.name === `useScript${k.substring(0, 1).toUpperCase() + k.substring(1)}`);
|
|
641
867
|
if (importDefinition) {
|
|
868
|
+
resolvedRegistryKeys.push(k);
|
|
642
869
|
imports.unshift(`import { ${importDefinition.import.name} } from '${importDefinition.import.from}'`);
|
|
643
|
-
const args = (typeof c !== "object" ? {} : c) || {};
|
|
644
870
|
if (c === "mock") {
|
|
645
|
-
|
|
646
|
-
} else if (Array.isArray(c) && c.length === 2
|
|
647
|
-
const
|
|
871
|
+
inits.push(`const ${k} = ${importDefinition.import.name}({ scriptOptions: { trigger: 'manual', skipValidation: true } })`);
|
|
872
|
+
} else if (Array.isArray(c) && c.length === 2) {
|
|
873
|
+
const input = c[0] || {};
|
|
874
|
+
const scriptOptions = { ...c[1] };
|
|
875
|
+
const triggerResolved = resolveTriggerForTemplate(scriptOptions?.trigger);
|
|
648
876
|
if (triggerResolved) {
|
|
649
|
-
|
|
650
|
-
if (args.scriptOptions) {
|
|
651
|
-
args.scriptOptions.trigger = `__TRIGGER_${triggerResolved}__`;
|
|
652
|
-
}
|
|
877
|
+
scriptOptions.trigger = "__TRIGGER_PLACEHOLDER__";
|
|
653
878
|
if (triggerResolved.includes("useScriptTriggerIdleTimeout")) needsIdleTimeoutImport = true;
|
|
654
879
|
if (triggerResolved.includes("useScriptTriggerInteraction")) needsInteractionImport = true;
|
|
880
|
+
if (triggerResolved.includes("useScriptTriggerServiceWorker")) needsServiceWorkerImport = true;
|
|
655
881
|
}
|
|
882
|
+
const args = { ...input, scriptOptions };
|
|
883
|
+
const argsJson = triggerResolved ? JSON.stringify(args).replace(/"__TRIGGER_PLACEHOLDER__"/g, triggerResolved) : JSON.stringify(args);
|
|
884
|
+
inits.push(`const ${k} = ${importDefinition.import.name}(${argsJson})`);
|
|
885
|
+
} else {
|
|
886
|
+
const args = (typeof c !== "object" ? {} : c) || {};
|
|
887
|
+
inits.push(`const ${k} = ${importDefinition.import.name}(${JSON.stringify(args)})`);
|
|
656
888
|
}
|
|
657
|
-
inits.push(`const ${k} = ${importDefinition.import.name}(${JSON.stringify(args).replace(/"__TRIGGER_(.*?)__"/g, "$1")})`);
|
|
658
889
|
}
|
|
659
890
|
}
|
|
660
891
|
for (const [k, c] of Object.entries(config.globals || {})) {
|
|
@@ -666,8 +897,10 @@ function templatePlugin(config, registry) {
|
|
|
666
897
|
if (triggerResolved) {
|
|
667
898
|
if (triggerResolved.includes("useScriptTriggerIdleTimeout")) needsIdleTimeoutImport = true;
|
|
668
899
|
if (triggerResolved.includes("useScriptTriggerInteraction")) needsInteractionImport = true;
|
|
669
|
-
|
|
670
|
-
|
|
900
|
+
if (triggerResolved.includes("useScriptTriggerServiceWorker")) needsServiceWorkerImport = true;
|
|
901
|
+
const resolvedOptions = { ...options, trigger: "__TRIGGER_PLACEHOLDER__" };
|
|
902
|
+
const optionsJson = JSON.stringify(resolvedOptions).replace(/"__TRIGGER_PLACEHOLDER__"/g, triggerResolved);
|
|
903
|
+
inits.push(`const ${k} = useScript(${JSON.stringify({ key: k, ...typeof c[0] === "string" ? { src: c[0] } : c[0] })}, { ...${optionsJson}, use: () => ({ ${k}: window.${k} }) })`);
|
|
671
904
|
} else {
|
|
672
905
|
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} }) })`);
|
|
673
906
|
}
|
|
@@ -676,8 +909,10 @@ function templatePlugin(config, registry) {
|
|
|
676
909
|
if (triggerResolved) {
|
|
677
910
|
if (triggerResolved.includes("useScriptTriggerIdleTimeout")) needsIdleTimeoutImport = true;
|
|
678
911
|
if (triggerResolved.includes("useScriptTriggerInteraction")) needsInteractionImport = true;
|
|
679
|
-
|
|
680
|
-
|
|
912
|
+
if (triggerResolved.includes("useScriptTriggerServiceWorker")) needsServiceWorkerImport = true;
|
|
913
|
+
const resolvedOptions = { ...c, trigger: "__TRIGGER_PLACEHOLDER__" };
|
|
914
|
+
const argsJson = JSON.stringify({ key: k, ...resolvedOptions }).replace(/"__TRIGGER_PLACEHOLDER__"/g, triggerResolved);
|
|
915
|
+
inits.push(`const ${k} = useScript(${argsJson}, { use: () => ({ ${k}: window.${k} }) })`);
|
|
681
916
|
} else {
|
|
682
917
|
inits.push(`const ${k} = useScript(${JSON.stringify({ key: k, ...c })}, { use: () => ({ ${k}: window.${k} }) })`);
|
|
683
918
|
}
|
|
@@ -690,6 +925,9 @@ function templatePlugin(config, registry) {
|
|
|
690
925
|
if (needsInteractionImport) {
|
|
691
926
|
triggerImports.push(`import { useScriptTriggerInteraction } from '#nuxt-scripts/composables/useScriptTriggerInteraction'`);
|
|
692
927
|
}
|
|
928
|
+
if (needsServiceWorkerImport) {
|
|
929
|
+
triggerImports.push(`import { useScriptTriggerServiceWorker } from '#nuxt-scripts/composables/useScriptTriggerServiceWorker'`);
|
|
930
|
+
}
|
|
693
931
|
return [
|
|
694
932
|
`import { useScript } from '#nuxt-scripts/composables/useScript'`,
|
|
695
933
|
`import { defineNuxtPlugin } from 'nuxt/app'`,
|
|
@@ -702,12 +940,26 @@ function templatePlugin(config, registry) {
|
|
|
702
940
|
` parallel: true,`,
|
|
703
941
|
` setup() {`,
|
|
704
942
|
...inits.map((i) => ` ${i}`),
|
|
705
|
-
` return { provide: { $scripts: { ${[...Object.keys(config.globals || {}), ...
|
|
943
|
+
` return { provide: { $scripts: { ${[...Object.keys(config.globals || {}), ...resolvedRegistryKeys].join(", ")} } } }`,
|
|
706
944
|
` }`,
|
|
707
945
|
`})`
|
|
708
946
|
].join("\n");
|
|
709
947
|
}
|
|
710
948
|
|
|
949
|
+
const PARTYTOWN_FORWARDS = {
|
|
950
|
+
googleAnalytics: ["dataLayer.push", "gtag"],
|
|
951
|
+
plausible: ["plausible"],
|
|
952
|
+
fathom: ["fathom", "fathom.trackEvent", "fathom.trackPageview"],
|
|
953
|
+
umami: ["umami", "umami.track"],
|
|
954
|
+
matomo: ["_paq.push"],
|
|
955
|
+
segment: ["analytics", "analytics.track", "analytics.page", "analytics.identify"],
|
|
956
|
+
metaPixel: ["fbq"],
|
|
957
|
+
xPixel: ["twq"],
|
|
958
|
+
tiktokPixel: ["ttq.track", "ttq.page", "ttq.identify"],
|
|
959
|
+
snapchatPixel: ["snaptr"],
|
|
960
|
+
redditPixel: ["rdt"],
|
|
961
|
+
cloudflareWebAnalytics: ["__cfBeacon"]
|
|
962
|
+
};
|
|
711
963
|
const module$1 = defineNuxtModule({
|
|
712
964
|
meta: {
|
|
713
965
|
name: "@nuxt/scripts",
|
|
@@ -717,6 +969,7 @@ const module$1 = defineNuxtModule({
|
|
|
717
969
|
}
|
|
718
970
|
},
|
|
719
971
|
defaults: {
|
|
972
|
+
firstParty: true,
|
|
720
973
|
defaultScriptOptions: {
|
|
721
974
|
trigger: "onNuxtReady"
|
|
722
975
|
},
|
|
@@ -756,7 +1009,8 @@ const module$1 = defineNuxtModule({
|
|
|
756
1009
|
nuxt.options.runtimeConfig["nuxt-scripts"] = {
|
|
757
1010
|
version,
|
|
758
1011
|
// Private proxy config with API key (server-side only)
|
|
759
|
-
googleStaticMapsProxy: config.googleStaticMapsProxy?.enabled ? { apiKey: nuxt.options.runtimeConfig.public.scripts?.googleMaps?.apiKey } : void 0
|
|
1012
|
+
googleStaticMapsProxy: config.googleStaticMapsProxy?.enabled ? { apiKey: nuxt.options.runtimeConfig.public.scripts?.googleMaps?.apiKey } : void 0,
|
|
1013
|
+
swTemplate: readFileSync(await resolvePath("./runtime/sw/proxy-sw.template.js"), "utf-8")
|
|
760
1014
|
};
|
|
761
1015
|
nuxt.options.runtimeConfig.public["nuxt-scripts"] = {
|
|
762
1016
|
// expose for devtools
|
|
@@ -772,13 +1026,57 @@ const module$1 = defineNuxtModule({
|
|
|
772
1026
|
config.registry
|
|
773
1027
|
);
|
|
774
1028
|
}
|
|
1029
|
+
if (config.defaultScriptOptions?.bundle !== void 0) {
|
|
1030
|
+
logger.warn(
|
|
1031
|
+
"`scripts.defaultScriptOptions.bundle` is deprecated. Use `scripts.firstParty: true` instead. First-party mode is now enabled by default."
|
|
1032
|
+
);
|
|
1033
|
+
}
|
|
1034
|
+
const staticPresets = ["static", "github-pages", "cloudflare-pages-static"];
|
|
1035
|
+
const preset = process.env.NITRO_PRESET || "";
|
|
1036
|
+
const isStaticPreset = staticPresets.includes(preset);
|
|
1037
|
+
const firstPartyEnabled = !!config.firstParty;
|
|
1038
|
+
const firstPartyPrefix = typeof config.firstParty === "object" ? config.firstParty.prefix : void 0;
|
|
1039
|
+
const firstPartyCollectPrefix = typeof config.firstParty === "object" ? config.firstParty.collectPrefix || "/_proxy" : "/_proxy";
|
|
1040
|
+
const firstPartyPrivacy = typeof config.firstParty === "object" ? config.firstParty.privacy ?? "anonymize" : "anonymize";
|
|
1041
|
+
const assetsPrefix = firstPartyPrefix || config.assets?.prefix || "/_scripts";
|
|
1042
|
+
if (config.partytown?.length) {
|
|
1043
|
+
config.registry = config.registry || {};
|
|
1044
|
+
const requiredForwards = [];
|
|
1045
|
+
for (const scriptKey of config.partytown) {
|
|
1046
|
+
const forwards = PARTYTOWN_FORWARDS[scriptKey];
|
|
1047
|
+
if (forwards) {
|
|
1048
|
+
requiredForwards.push(...forwards);
|
|
1049
|
+
} else if (import.meta.dev) {
|
|
1050
|
+
logger.warn(`[partytown] "${scriptKey}" has no known Partytown forwards configured. It may not work correctly or may require manual forward configuration.`);
|
|
1051
|
+
}
|
|
1052
|
+
const reg = config.registry;
|
|
1053
|
+
const existing = reg[scriptKey];
|
|
1054
|
+
if (Array.isArray(existing)) {
|
|
1055
|
+
existing[1] = { ...existing[1], partytown: true };
|
|
1056
|
+
} else if (existing && typeof existing === "object" && existing !== true && existing !== "mock") {
|
|
1057
|
+
reg[scriptKey] = [existing, { partytown: true }];
|
|
1058
|
+
} else if (existing === true || existing === "mock") {
|
|
1059
|
+
reg[scriptKey] = [{}, { partytown: true }];
|
|
1060
|
+
} else {
|
|
1061
|
+
reg[scriptKey] = [{}, { partytown: true }];
|
|
1062
|
+
}
|
|
1063
|
+
}
|
|
1064
|
+
if (requiredForwards.length && hasNuxtModule("@nuxtjs/partytown")) {
|
|
1065
|
+
const partytownConfig = nuxt.options.partytown || {};
|
|
1066
|
+
const existingForwards = partytownConfig.forward || [];
|
|
1067
|
+
const newForwards = [.../* @__PURE__ */ new Set([...existingForwards, ...requiredForwards])];
|
|
1068
|
+
nuxt.options.partytown = { ...partytownConfig, forward: newForwards };
|
|
1069
|
+
logger.info(`[partytown] Auto-configured forwards: ${requiredForwards.join(", ")}`);
|
|
1070
|
+
}
|
|
1071
|
+
}
|
|
775
1072
|
const composables = [
|
|
776
1073
|
"useScript",
|
|
777
1074
|
"useScriptEventPage",
|
|
778
1075
|
"useScriptTriggerConsent",
|
|
779
1076
|
"useScriptTriggerElement",
|
|
780
1077
|
"useScriptTriggerIdleTimeout",
|
|
781
|
-
"useScriptTriggerInteraction"
|
|
1078
|
+
"useScriptTriggerInteraction",
|
|
1079
|
+
"useScriptTriggerServiceWorker"
|
|
782
1080
|
];
|
|
783
1081
|
for (const composable of composables) {
|
|
784
1082
|
addImports({
|
|
@@ -798,6 +1096,104 @@ const module$1 = defineNuxtModule({
|
|
|
798
1096
|
return templateTriggerResolver(config.defaultScriptOptions);
|
|
799
1097
|
}
|
|
800
1098
|
});
|
|
1099
|
+
const swHandlerPath = await resolvePath("./runtime/server/sw-handler");
|
|
1100
|
+
logger.debug("[nuxt-scripts] First-party config:", { firstPartyEnabled, firstPartyPrivacy, firstPartyCollectPrefix });
|
|
1101
|
+
if (firstPartyEnabled && !nuxt.options.dev) {
|
|
1102
|
+
const swPath = "/_nuxt-scripts-sw.js";
|
|
1103
|
+
const swRules = getSWInterceptRules(firstPartyCollectPrefix);
|
|
1104
|
+
addServerHandler({
|
|
1105
|
+
route: swPath,
|
|
1106
|
+
handler: swHandlerPath
|
|
1107
|
+
});
|
|
1108
|
+
addPluginTemplate({
|
|
1109
|
+
filename: "nuxt-scripts-sw-register.client.mjs",
|
|
1110
|
+
getContents() {
|
|
1111
|
+
return `import { defineNuxtPlugin } from 'nuxt/app'
|
|
1112
|
+
|
|
1113
|
+
export default defineNuxtPlugin({
|
|
1114
|
+
name: 'nuxt-scripts:sw-register',
|
|
1115
|
+
enforce: 'pre',
|
|
1116
|
+
async setup() {
|
|
1117
|
+
if (!('serviceWorker' in navigator)) return;
|
|
1118
|
+
|
|
1119
|
+
try {
|
|
1120
|
+
const reg = await navigator.serviceWorker.register('${swPath}', { scope: '/' });
|
|
1121
|
+
|
|
1122
|
+
// Wait for SW to be active and controlling this page
|
|
1123
|
+
if (!navigator.serviceWorker.controller) {
|
|
1124
|
+
await new Promise((resolve) => {
|
|
1125
|
+
const onControllerChange = () => {
|
|
1126
|
+
navigator.serviceWorker.removeEventListener('controllerchange', onControllerChange);
|
|
1127
|
+
resolve();
|
|
1128
|
+
};
|
|
1129
|
+
navigator.serviceWorker.addEventListener('controllerchange', onControllerChange);
|
|
1130
|
+
|
|
1131
|
+
// Fallback timeout
|
|
1132
|
+
setTimeout(resolve, 2000);
|
|
1133
|
+
});
|
|
1134
|
+
}
|
|
1135
|
+
} catch (err) {
|
|
1136
|
+
console.warn('[nuxt-scripts] SW registration failed:', err);
|
|
1137
|
+
}
|
|
1138
|
+
},
|
|
1139
|
+
})
|
|
1140
|
+
`;
|
|
1141
|
+
}
|
|
1142
|
+
});
|
|
1143
|
+
addPluginTemplate({
|
|
1144
|
+
filename: "nuxt-scripts-beacon-intercept.client.mjs",
|
|
1145
|
+
getContents() {
|
|
1146
|
+
const rulesJson = JSON.stringify(swRules);
|
|
1147
|
+
return `export default defineNuxtPlugin({
|
|
1148
|
+
name: 'nuxt-scripts:beacon-intercept',
|
|
1149
|
+
enforce: 'pre',
|
|
1150
|
+
setup() {
|
|
1151
|
+
if (typeof navigator === 'undefined' || !navigator.sendBeacon) return;
|
|
1152
|
+
|
|
1153
|
+
const rules = ${rulesJson};
|
|
1154
|
+
const originalBeacon = navigator.sendBeacon.bind(navigator);
|
|
1155
|
+
|
|
1156
|
+
navigator.sendBeacon = (url, data) => {
|
|
1157
|
+
try {
|
|
1158
|
+
const parsed = new URL(url, window.location.origin);
|
|
1159
|
+
|
|
1160
|
+
// Check if this URL matches any of our proxy rules
|
|
1161
|
+
for (const rule of rules) {
|
|
1162
|
+
if (parsed.hostname === rule.pattern || parsed.hostname.endsWith('.' + rule.pattern)) {
|
|
1163
|
+
// Check path prefix if specified
|
|
1164
|
+
if (rule.pathPrefix && !parsed.pathname.startsWith(rule.pathPrefix)) {
|
|
1165
|
+
continue;
|
|
1166
|
+
}
|
|
1167
|
+
|
|
1168
|
+
// Rewrite to proxy: strip pathPrefix from original, prepend target
|
|
1169
|
+
const pathWithoutPrefix = rule.pathPrefix
|
|
1170
|
+
? parsed.pathname.slice(rule.pathPrefix.length)
|
|
1171
|
+
: parsed.pathname;
|
|
1172
|
+
const separator = pathWithoutPrefix.startsWith('/') ? '' : '/';
|
|
1173
|
+
const proxyUrl = rule.target + separator + pathWithoutPrefix + parsed.search;
|
|
1174
|
+
|
|
1175
|
+
return originalBeacon(proxyUrl, data);
|
|
1176
|
+
}
|
|
1177
|
+
}
|
|
1178
|
+
} catch (e) {
|
|
1179
|
+
// URL parsing failed, pass through
|
|
1180
|
+
}
|
|
1181
|
+
|
|
1182
|
+
return originalBeacon(url, data);
|
|
1183
|
+
};
|
|
1184
|
+
},
|
|
1185
|
+
})
|
|
1186
|
+
`;
|
|
1187
|
+
}
|
|
1188
|
+
});
|
|
1189
|
+
nuxt.options.runtimeConfig.public["nuxt-scripts-sw"] = { path: swPath };
|
|
1190
|
+
const proxyHandlerPath = await resolvePath("./runtime/server/proxy-handler");
|
|
1191
|
+
logger.debug("[nuxt-scripts] Registering proxy handler:", `${firstPartyCollectPrefix}/**`, "->", proxyHandlerPath);
|
|
1192
|
+
addServerHandler({
|
|
1193
|
+
route: `${firstPartyCollectPrefix}/**`,
|
|
1194
|
+
handler: proxyHandlerPath
|
|
1195
|
+
});
|
|
1196
|
+
}
|
|
801
1197
|
const scripts = await registry(resolvePath);
|
|
802
1198
|
for (const script of scripts) {
|
|
803
1199
|
if (script.import?.name) {
|
|
@@ -825,6 +1221,75 @@ const module$1 = defineNuxtModule({
|
|
|
825
1221
|
});
|
|
826
1222
|
}
|
|
827
1223
|
const { renderedScript } = setupPublicAssetStrategy(config.assets);
|
|
1224
|
+
if (firstPartyEnabled) {
|
|
1225
|
+
const proxyConfigs = getAllProxyConfigs(firstPartyCollectPrefix);
|
|
1226
|
+
const registryKeys = Object.keys(config.registry || {});
|
|
1227
|
+
const neededRoutes = {};
|
|
1228
|
+
const unsupportedScripts = [];
|
|
1229
|
+
for (const key of registryKeys) {
|
|
1230
|
+
const script = registryScriptsWithImport.find((s) => s.import.name.toLowerCase() === `usescript${key.toLowerCase()}`);
|
|
1231
|
+
const proxyKey = script?.proxy || void 0;
|
|
1232
|
+
if (proxyKey) {
|
|
1233
|
+
const proxyConfig = proxyConfigs[proxyKey];
|
|
1234
|
+
if (proxyConfig?.routes) {
|
|
1235
|
+
Object.assign(neededRoutes, proxyConfig.routes);
|
|
1236
|
+
} else {
|
|
1237
|
+
unsupportedScripts.push(key);
|
|
1238
|
+
}
|
|
1239
|
+
}
|
|
1240
|
+
}
|
|
1241
|
+
if (unsupportedScripts.length && nuxt.options.dev) {
|
|
1242
|
+
logger.warn(
|
|
1243
|
+
`First-party mode is enabled but these scripts don't support it yet: ${unsupportedScripts.join(", ")}.
|
|
1244
|
+
They will load directly from third-party servers. Request support at https://github.com/nuxt/scripts/issues`
|
|
1245
|
+
);
|
|
1246
|
+
}
|
|
1247
|
+
const flatRoutes = {};
|
|
1248
|
+
for (const [path, config2] of Object.entries(neededRoutes)) {
|
|
1249
|
+
flatRoutes[path] = config2.proxy;
|
|
1250
|
+
}
|
|
1251
|
+
const allRewrites = [];
|
|
1252
|
+
for (const key of registryKeys) {
|
|
1253
|
+
const script = registryScriptsWithImport.find((s) => s.import.name.toLowerCase() === `usescript${key.toLowerCase()}`);
|
|
1254
|
+
const proxyKey = script?.proxy !== false ? script?.proxy || key : void 0;
|
|
1255
|
+
if (proxyKey) {
|
|
1256
|
+
const proxyConfig = proxyConfigs[proxyKey];
|
|
1257
|
+
if (proxyConfig?.rewrite) {
|
|
1258
|
+
allRewrites.push(...proxyConfig.rewrite);
|
|
1259
|
+
}
|
|
1260
|
+
}
|
|
1261
|
+
}
|
|
1262
|
+
nuxt.options.runtimeConfig["nuxt-scripts-proxy"] = {
|
|
1263
|
+
routes: flatRoutes,
|
|
1264
|
+
privacy: firstPartyPrivacy,
|
|
1265
|
+
rewrites: allRewrites
|
|
1266
|
+
};
|
|
1267
|
+
if (Object.keys(neededRoutes).length) {
|
|
1268
|
+
if (nuxt.options.dev) {
|
|
1269
|
+
const routeCount = Object.keys(neededRoutes).length;
|
|
1270
|
+
const scriptsCount = registryKeys.length;
|
|
1271
|
+
logger.success(`First-party mode enabled for ${scriptsCount} script(s), ${routeCount} proxy route(s) configured (privacy: ${firstPartyPrivacy})`);
|
|
1272
|
+
if (logger.level >= 4) {
|
|
1273
|
+
for (const [path, config2] of Object.entries(neededRoutes)) {
|
|
1274
|
+
logger.debug(` ${path} \u2192 ${config2.proxy}`);
|
|
1275
|
+
}
|
|
1276
|
+
}
|
|
1277
|
+
}
|
|
1278
|
+
}
|
|
1279
|
+
if (isStaticPreset) {
|
|
1280
|
+
logger.warn(
|
|
1281
|
+
`First-party collection endpoints require a server runtime (detected: ${preset || "static"}).
|
|
1282
|
+
Scripts will be bundled, but collection requests will not be proxied.
|
|
1283
|
+
|
|
1284
|
+
Options:
|
|
1285
|
+
1. Configure platform rewrites (Vercel, Netlify, Cloudflare)
|
|
1286
|
+
2. Switch to server-rendered mode (ssr: true)
|
|
1287
|
+
3. Disable with firstParty: false
|
|
1288
|
+
|
|
1289
|
+
See: https://scripts.nuxt.com/docs/guides/first-party#static-hosting`
|
|
1290
|
+
);
|
|
1291
|
+
}
|
|
1292
|
+
}
|
|
828
1293
|
const moduleInstallPromises = /* @__PURE__ */ new Map();
|
|
829
1294
|
addBuildPlugin(NuxtScriptsCheckScripts(), {
|
|
830
1295
|
dev: true
|
|
@@ -832,12 +1297,14 @@ const module$1 = defineNuxtModule({
|
|
|
832
1297
|
addBuildPlugin(NuxtScriptBundleTransformer({
|
|
833
1298
|
scripts: registryScriptsWithImport,
|
|
834
1299
|
registryConfig: nuxt.options.runtimeConfig.public.scripts,
|
|
835
|
-
defaultBundle: config.defaultScriptOptions?.bundle,
|
|
1300
|
+
defaultBundle: firstPartyEnabled || config.defaultScriptOptions?.bundle,
|
|
1301
|
+
firstPartyEnabled,
|
|
1302
|
+
firstPartyCollectPrefix,
|
|
836
1303
|
moduleDetected(module) {
|
|
837
1304
|
if (nuxt.options.dev && module !== "@nuxt/scripts" && !moduleInstallPromises.has(module) && !hasNuxtModule(module))
|
|
838
1305
|
moduleInstallPromises.set(module, () => installNuxtModule(module));
|
|
839
1306
|
},
|
|
840
|
-
assetsBaseURL:
|
|
1307
|
+
assetsBaseURL: assetsPrefix,
|
|
841
1308
|
fallbackOnSrcOnBundleFail: config.assets?.fallbackOnSrcOnBundleFail,
|
|
842
1309
|
fetchOptions: config.assets?.fetchOptions,
|
|
843
1310
|
cacheMaxAge: config.assets?.cacheMaxAge,
|
|
@@ -856,8 +1323,29 @@ const module$1 = defineNuxtModule({
|
|
|
856
1323
|
handler: await resolvePath("./runtime/server/google-static-maps-proxy")
|
|
857
1324
|
});
|
|
858
1325
|
}
|
|
859
|
-
|
|
1326
|
+
addServerHandler({
|
|
1327
|
+
route: "/api/_scripts/x-embed",
|
|
1328
|
+
handler: await resolvePath("./runtime/server/x-embed")
|
|
1329
|
+
});
|
|
1330
|
+
addServerHandler({
|
|
1331
|
+
route: "/api/_scripts/x-embed-image",
|
|
1332
|
+
handler: await resolvePath("./runtime/server/x-embed-image")
|
|
1333
|
+
});
|
|
1334
|
+
addServerHandler({
|
|
1335
|
+
route: "/api/_scripts/instagram-embed",
|
|
1336
|
+
handler: await resolvePath("./runtime/server/instagram-embed")
|
|
1337
|
+
});
|
|
1338
|
+
addServerHandler({
|
|
1339
|
+
route: "/api/_scripts/instagram-embed-image",
|
|
1340
|
+
handler: await resolvePath("./runtime/server/instagram-embed-image")
|
|
1341
|
+
});
|
|
1342
|
+
addServerHandler({
|
|
1343
|
+
route: "/api/_scripts/instagram-embed-asset",
|
|
1344
|
+
handler: await resolvePath("./runtime/server/instagram-embed-asset")
|
|
1345
|
+
});
|
|
1346
|
+
if (nuxt.options.dev) {
|
|
860
1347
|
setupDevToolsUI(config, resolvePath);
|
|
1348
|
+
}
|
|
861
1349
|
}
|
|
862
1350
|
});
|
|
863
1351
|
|