@nuxt/scripts 1.3.3 → 1.3.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/devtools-client/200.html +1 -1
- package/dist/devtools-client/404.html +1 -1
- package/dist/devtools-client/_nuxt/{DAubxma0.js → 8ltZ0o6d.js} +1 -1
- package/dist/devtools-client/_nuxt/{CBuBrHyL.js → B8_EBdhg.js} +1 -1
- package/dist/devtools-client/_nuxt/CC0GKROJ.js +1 -0
- package/dist/devtools-client/_nuxt/{DvC3yV2P.js → CMXzQxJZ.js} +1 -1
- package/dist/devtools-client/_nuxt/{xAZ2vgo3.js → CP7c-Js6.js} +4 -4
- package/dist/devtools-client/_nuxt/{DzbSCA_w.js → DTP8MRtW.js} +1 -1
- package/dist/devtools-client/_nuxt/{DgAtAWdT.js → Dkc7iTdR.js} +1 -1
- package/dist/devtools-client/_nuxt/Dl7W1ViV.js +28 -0
- package/dist/devtools-client/_nuxt/{WOtyQdps.js → KxC4Q3ev.js} +1 -1
- package/dist/devtools-client/_nuxt/builds/latest.json +1 -1
- package/dist/devtools-client/_nuxt/builds/meta/c38edf4f-387c-4148-a34a-ca78a5b40869.json +1 -0
- package/dist/devtools-client/_nuxt/error-404.Bq2JQbJs.css +1 -0
- package/dist/devtools-client/_nuxt/error-500.5E_FOzlc.css +1 -0
- package/dist/devtools-client/_nuxt/{pages.BF1VnccH.css → pages.aU4WirOM.css} +1 -1
- package/dist/devtools-client/docs/index.html +1 -1
- package/dist/devtools-client/first-party/index.html +1 -1
- package/dist/devtools-client/index.html +1 -1
- package/dist/devtools-client/registry/index.html +1 -1
- package/dist/module.d.mts +1 -1
- package/dist/module.d.ts +1 -1
- package/dist/module.json +1 -1
- package/dist/module.mjs +263 -47
- package/dist/registry.mjs +2 -2
- package/dist/runtime/components/GoogleMaps/ScriptGoogleMaps.vue +71 -21
- package/dist/runtime/components/GoogleMaps/useGoogleMapsResource.d.ts +2 -1
- package/dist/runtime/components/GoogleMaps/useGoogleMapsResource.js +39 -25
- package/dist/runtime/components/ScriptCarbonAds.vue +11 -3
- package/dist/runtime/components/ScriptCrisp.vue +4 -1
- package/dist/runtime/components/ScriptIntercom.vue +4 -1
- package/dist/runtime/components/ScriptLemonSqueezy.d.vue.ts +13 -13
- package/dist/runtime/components/ScriptLemonSqueezy.vue +30 -6
- package/dist/runtime/components/ScriptLemonSqueezy.vue.d.ts +13 -13
- package/dist/runtime/components/ScriptPayPalButtons.vue +8 -1
- package/dist/runtime/components/ScriptPayPalMessages.vue +6 -0
- package/dist/runtime/components/ScriptStripePricingTable.vue +2 -0
- package/dist/runtime/components/ScriptVimeoPlayer.vue +8 -1
- package/dist/runtime/composables/useScript.js +121 -44
- package/dist/runtime/composables/useScriptEventPage.js +36 -20
- package/dist/runtime/composables/useScriptTriggerIdleTimeout.js +19 -5
- package/dist/runtime/composables/useScriptTriggerInteraction.js +23 -10
- package/dist/runtime/composables/useScriptTriggerServiceWorker.js +21 -18
- package/dist/runtime/devtools-standalone-bridge.client.js +28 -3
- package/dist/runtime/npm-script-proxy.d.ts +7 -0
- package/dist/runtime/npm-script-proxy.js +46 -0
- package/dist/runtime/npm-script-stub.js +4 -5
- package/dist/runtime/registry/posthog.js +11 -3
- package/dist/runtime/registry/speedcurve.js +33 -4
- package/dist/runtime/registry/usercentrics.js +4 -21
- package/dist/runtime/registry/youtube-player.js +16 -5
- package/dist/runtime/server/bluesky-embed.js +15 -6
- package/dist/runtime/server/google-maps-geocode-proxy.js +10 -5
- package/dist/runtime/server/google-static-maps-proxy.js +20 -13
- package/dist/runtime/server/gravatar-proxy.js +48 -11
- package/dist/runtime/server/instagram-embed-asset.js +1 -1
- package/dist/runtime/server/instagram-embed.js +44 -94
- package/dist/runtime/server/proxy-handler.d.ts +2 -1
- package/dist/runtime/server/proxy-handler.js +183 -23
- package/dist/runtime/server/utils/cache-config.d.ts +14 -0
- package/dist/runtime/server/utils/cache-config.js +13 -0
- package/dist/runtime/server/utils/cached-upstream.d.ts +23 -2
- package/dist/runtime/server/utils/cached-upstream.js +212 -15
- package/dist/runtime/server/utils/image-proxy.d.ts +3 -2
- package/dist/runtime/server/utils/image-proxy.js +26 -16
- package/dist/runtime/server/utils/instagram-embed.d.ts +8 -0
- package/dist/runtime/server/utils/instagram-embed.js +155 -0
- package/dist/runtime/server/utils/network-host.d.ts +21 -0
- package/dist/runtime/server/utils/network-host.js +112 -0
- package/dist/runtime/server/utils/privacy.js +55 -19
- package/dist/runtime/server/utils/proxy-query.d.ts +2 -0
- package/dist/runtime/server/utils/proxy-query.js +10 -0
- package/dist/runtime/server/utils/sign.d.ts +1 -1
- package/dist/runtime/server/utils/sign.js +1 -1
- package/dist/runtime/server/utils/withSigning.d.ts +1 -1
- package/dist/runtime/server/utils/withSigning.js +3 -3
- package/dist/runtime/server/vercel-insights-sink.js +1 -1
- package/dist/runtime/server/x-embed.js +8 -4
- package/dist/runtime/unhead-features.d.ts +1 -0
- package/dist/runtime/unhead-features.js +3 -0
- package/dist/runtime/utils/abortable-promise.d.ts +8 -0
- package/dist/runtime/utils/abortable-promise.js +63 -0
- package/dist/runtime/utils/after-next-paint.d.ts +1 -1
- package/dist/runtime/utils/after-next-paint.js +16 -1
- package/dist/runtime/utils/usercentrics-consent.d.ts +10 -0
- package/dist/runtime/utils/usercentrics-consent.js +88 -0
- package/dist/runtime/utils/youtube-readiness.d.ts +7 -0
- package/dist/runtime/utils/youtube-readiness.js +45 -0
- package/dist/runtime/utils.d.ts +3 -1
- package/dist/runtime/utils.js +29 -0
- package/package.json +2 -1
- package/dist/devtools-client/_nuxt/BGGk5RYW.js +0 -1
- package/dist/devtools-client/_nuxt/C8xLTMBy.js +0 -28
- package/dist/devtools-client/_nuxt/builds/meta/0c193d7f-fdc4-4ec6-b4c0-7ba4cc94709b.json +0 -1
- package/dist/devtools-client/_nuxt/error-404.CIn5oEzb.css +0 -1
- package/dist/devtools-client/_nuxt/error-500.B1YZl8g8.css +0 -1
|
@@ -1,10 +1,17 @@
|
|
|
1
1
|
import { useScript as _useScript } from "@unhead/vue/scripts";
|
|
2
2
|
import { defu } from "defu";
|
|
3
3
|
import { injectHead, onNuxtReady, useHead, useNuxtApp, useRuntimeConfig } from "nuxt/app";
|
|
4
|
-
import { markRaw, ref } from "vue";
|
|
4
|
+
import { markRaw, ref, watch } from "vue";
|
|
5
5
|
import { resolveTrigger } from "#build/nuxt-scripts-trigger-resolver";
|
|
6
6
|
import { debugEnabled } from "../debug.js";
|
|
7
7
|
import { logger } from "../logger.js";
|
|
8
|
+
const DEVTOOLS_EVENT_LIMIT = 250;
|
|
9
|
+
const DEVTOOLS_NETWORK_REQUEST_LIMIT = 500;
|
|
10
|
+
function pushBounded(items, item, limit) {
|
|
11
|
+
items.push(item);
|
|
12
|
+
if (items.length > limit)
|
|
13
|
+
items.splice(0, items.length - limit);
|
|
14
|
+
}
|
|
8
15
|
function resolveProxyPrefix() {
|
|
9
16
|
const devtoolsConfig = useRuntimeConfig().public["nuxt-scripts-devtools"];
|
|
10
17
|
return devtoolsConfig?.proxyPrefix || "/_scripts/p";
|
|
@@ -67,6 +74,7 @@ function observeNetworkRequests(payload, domains, onUpdate, scriptSrc) {
|
|
|
67
74
|
const proxyPrefix = resolveProxyPrefix();
|
|
68
75
|
const matchesScript = createDomainMatcher(domains, proxyPrefix, scriptSrc);
|
|
69
76
|
const seen = /* @__PURE__ */ new Set();
|
|
77
|
+
const seenOrder = [];
|
|
70
78
|
function entryKey(entry) {
|
|
71
79
|
return `${entry.name}@${entry.startTime}`;
|
|
72
80
|
}
|
|
@@ -77,7 +85,13 @@ function observeNetworkRequests(payload, domains, onUpdate, scriptSrc) {
|
|
|
77
85
|
if (!matchesScript(entry))
|
|
78
86
|
return false;
|
|
79
87
|
seen.add(key);
|
|
80
|
-
|
|
88
|
+
seenOrder.push(key);
|
|
89
|
+
if (seenOrder.length > DEVTOOLS_NETWORK_REQUEST_LIMIT) {
|
|
90
|
+
const oldest = seenOrder.shift();
|
|
91
|
+
if (oldest)
|
|
92
|
+
seen.delete(oldest);
|
|
93
|
+
}
|
|
94
|
+
pushBounded(payload.networkRequests, toNetworkRequest(entry, proxyPrefix), DEVTOOLS_NETWORK_REQUEST_LIMIT);
|
|
81
95
|
return true;
|
|
82
96
|
}
|
|
83
97
|
for (const entry of performance.getEntriesByType("resource"))
|
|
@@ -131,15 +145,35 @@ export function useScript(input, options) {
|
|
|
131
145
|
});
|
|
132
146
|
const nuxtApp2 = useNuxtApp();
|
|
133
147
|
ensureScripts(nuxtApp2);
|
|
148
|
+
const existing = nuxtApp2.$scripts[src];
|
|
149
|
+
if (existing)
|
|
150
|
+
return existing;
|
|
134
151
|
const status = ref("loaded");
|
|
135
152
|
let disconnectObserver = () => {
|
|
136
153
|
};
|
|
137
|
-
|
|
154
|
+
let stopAppUnmountHook = () => {
|
|
155
|
+
};
|
|
156
|
+
let cleaned2 = false;
|
|
157
|
+
let stub;
|
|
158
|
+
const cleanup = () => {
|
|
159
|
+
if (cleaned2)
|
|
160
|
+
return;
|
|
161
|
+
cleaned2 = true;
|
|
162
|
+
disconnectObserver();
|
|
163
|
+
stopAppUnmountHook();
|
|
164
|
+
if (nuxtApp2.$scripts[src] === stub)
|
|
165
|
+
delete nuxtApp2.$scripts[src];
|
|
166
|
+
if (import.meta.dev && import.meta.client && nuxtApp2._scripts?.[src]) {
|
|
167
|
+
delete nuxtApp2._scripts[src];
|
|
168
|
+
nuxtApp2.hooks.callHook("scripts:updated", { scripts: nuxtApp2._scripts });
|
|
169
|
+
}
|
|
170
|
+
};
|
|
171
|
+
stub = {
|
|
138
172
|
id: src,
|
|
139
173
|
status,
|
|
140
174
|
load: () => Promise.resolve({}),
|
|
141
175
|
remove: () => {
|
|
142
|
-
|
|
176
|
+
cleanup();
|
|
143
177
|
return false;
|
|
144
178
|
},
|
|
145
179
|
entry: void 0
|
|
@@ -147,6 +181,8 @@ export function useScript(input, options) {
|
|
|
147
181
|
nuxtApp2.$scripts[src] = stub;
|
|
148
182
|
if (import.meta.dev && import.meta.client) {
|
|
149
183
|
let syncScripts = function() {
|
|
184
|
+
if (cleaned2)
|
|
185
|
+
return;
|
|
150
186
|
nuxtApp2._scripts[src] = payload;
|
|
151
187
|
nuxtApp2.hooks.callHook("scripts:updated", { scripts: nuxtApp2._scripts });
|
|
152
188
|
};
|
|
@@ -168,6 +204,7 @@ export function useScript(input, options) {
|
|
|
168
204
|
disconnectObserver = observeNetworkRequests(payload, domains, syncScripts, src);
|
|
169
205
|
syncScripts();
|
|
170
206
|
}
|
|
207
|
+
stopAppUnmountHook = nuxtApp2.hooks.hook("app:unmount", cleanup);
|
|
171
208
|
return stub;
|
|
172
209
|
}
|
|
173
210
|
if (import.meta.dev && options.bundle === "unsupported") {
|
|
@@ -210,31 +247,75 @@ export function useScript(input, options) {
|
|
|
210
247
|
options.trigger = onNuxtReady;
|
|
211
248
|
}
|
|
212
249
|
}
|
|
213
|
-
const
|
|
214
|
-
const
|
|
250
|
+
const unheadOptions = { ...options };
|
|
251
|
+
const instance = _useScript(input, unheadOptions);
|
|
252
|
+
delete unheadOptions.eventContext;
|
|
253
|
+
if (exists)
|
|
254
|
+
return instance;
|
|
255
|
+
markRaw(instance);
|
|
256
|
+
instance.toJSON = () => ({ id: instance.id, status: instance.status.value });
|
|
257
|
+
const cleanupFns = /* @__PURE__ */ new Set();
|
|
258
|
+
let cleaned = false;
|
|
259
|
+
const publicStatus = instance.status;
|
|
260
|
+
let stopStatusSync = () => {
|
|
261
|
+
};
|
|
262
|
+
const addCleanup = (cleanup) => {
|
|
263
|
+
if (cleaned)
|
|
264
|
+
cleanup();
|
|
265
|
+
else
|
|
266
|
+
cleanupFns.add(cleanup);
|
|
267
|
+
};
|
|
268
|
+
const cleanupInstance = () => {
|
|
269
|
+
if (cleaned)
|
|
270
|
+
return;
|
|
271
|
+
cleaned = true;
|
|
272
|
+
for (const cleanup of cleanupFns)
|
|
273
|
+
cleanup();
|
|
274
|
+
cleanupFns.clear();
|
|
275
|
+
if (nuxtApp.$scripts[id] === instance)
|
|
276
|
+
delete nuxtApp.$scripts[id];
|
|
277
|
+
if (import.meta.dev && import.meta.client && nuxtApp._scripts?.[instance.id]) {
|
|
278
|
+
delete nuxtApp._scripts[instance.id];
|
|
279
|
+
nuxtApp.hooks.callHook("scripts:updated", { scripts: nuxtApp._scripts });
|
|
280
|
+
}
|
|
281
|
+
};
|
|
282
|
+
let currentRemove = instance.remove;
|
|
283
|
+
let currentLoad = instance.load;
|
|
284
|
+
addCleanup(() => stopStatusSync());
|
|
215
285
|
instance.remove = () => {
|
|
216
|
-
|
|
217
|
-
|
|
286
|
+
const result = currentRemove();
|
|
287
|
+
cleanupInstance();
|
|
288
|
+
return result;
|
|
218
289
|
};
|
|
219
|
-
const _load = instance.load;
|
|
220
290
|
instance.load = async () => {
|
|
221
291
|
if (err) {
|
|
222
292
|
return Promise.reject(err);
|
|
223
293
|
}
|
|
224
|
-
return
|
|
294
|
+
return currentLoad();
|
|
225
295
|
};
|
|
226
296
|
instance.reload = async () => {
|
|
227
|
-
|
|
297
|
+
if (err)
|
|
298
|
+
return Promise.reject(err);
|
|
299
|
+
currentRemove();
|
|
228
300
|
const reloadInput = typeof input === "string" ? { src: input, key: `${id}-${Date.now()}` } : { ...input, key: `${id}-${Date.now()}` };
|
|
229
|
-
const
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
301
|
+
const reloadOptions = { ...options, trigger: "client" };
|
|
302
|
+
const reloaded = _useScript(reloadInput, reloadOptions);
|
|
303
|
+
delete reloadOptions.eventContext;
|
|
304
|
+
currentRemove = reloaded.remove;
|
|
305
|
+
currentLoad = reloaded.load;
|
|
306
|
+
stopStatusSync();
|
|
307
|
+
stopStatusSync = watch(reloaded.status, (status) => publicStatus.value = status, {
|
|
308
|
+
flush: "sync",
|
|
309
|
+
immediate: true
|
|
233
310
|
});
|
|
234
|
-
|
|
311
|
+
instance.entry = reloaded.entry;
|
|
312
|
+
return currentLoad();
|
|
235
313
|
};
|
|
236
314
|
nuxtApp.$scripts[id] = instance;
|
|
237
|
-
|
|
315
|
+
addCleanup(nuxtApp.hooks.hook("app:unmount", () => {
|
|
316
|
+
instance.remove();
|
|
317
|
+
}));
|
|
318
|
+
if (import.meta.client && debugEnabled && !exists) {
|
|
238
319
|
const registryKey = options?.devtools?.registryKey;
|
|
239
320
|
const src = input?.src;
|
|
240
321
|
const trigger = options?.trigger;
|
|
@@ -252,7 +333,7 @@ export function useScript(input, options) {
|
|
|
252
333
|
...ctx,
|
|
253
334
|
trigger: typeof trigger === "object" ? trigger instanceof Promise ? "promise" : JSON.stringify(trigger) : trigger
|
|
254
335
|
});
|
|
255
|
-
headHooks.hook("script:updated", (entry) => {
|
|
336
|
+
addCleanup(headHooks.hook("script:updated", (entry) => {
|
|
256
337
|
if (entry.script.id !== instance.id)
|
|
257
338
|
return;
|
|
258
339
|
const status = entry.script.status;
|
|
@@ -264,7 +345,7 @@ export function useScript(input, options) {
|
|
|
264
345
|
payload.loadMs = Math.round(performance.now() - tLoadStart);
|
|
265
346
|
const fn = status === "error" ? log.warn : log.debug;
|
|
266
347
|
fn(`status: ${status}`, payload);
|
|
267
|
-
});
|
|
348
|
+
}));
|
|
268
349
|
const _origLoad = instance.load;
|
|
269
350
|
instance.load = () => {
|
|
270
351
|
log.debug("load() called", ctx);
|
|
@@ -283,12 +364,11 @@ export function useScript(input, options) {
|
|
|
283
364
|
}
|
|
284
365
|
if (import.meta.dev && import.meta.client) {
|
|
285
366
|
let syncScripts = function() {
|
|
367
|
+
if (cleaned)
|
|
368
|
+
return;
|
|
286
369
|
nuxtApp._scripts[instance.id] = payload;
|
|
287
370
|
nuxtApp.hooks.callHook("scripts:updated", { scripts: nuxtApp._scripts });
|
|
288
371
|
};
|
|
289
|
-
if (exists) {
|
|
290
|
-
return instance;
|
|
291
|
-
}
|
|
292
372
|
const payload = {
|
|
293
373
|
...options.devtools,
|
|
294
374
|
src: input.src,
|
|
@@ -298,64 +378,61 @@ export function useScript(input, options) {
|
|
|
298
378
|
};
|
|
299
379
|
nuxtApp._scripts = nuxtApp._scripts || {};
|
|
300
380
|
if (!nuxtApp._scripts[instance.id]) {
|
|
301
|
-
headHooks.hook("script:updated", (ctx) => {
|
|
381
|
+
addCleanup(headHooks.hook("script:updated", (ctx) => {
|
|
302
382
|
if (ctx.script.id !== instance.id)
|
|
303
383
|
return;
|
|
304
|
-
payload.events
|
|
384
|
+
pushBounded(payload.events, {
|
|
305
385
|
type: "status",
|
|
306
386
|
status: ctx.script.status,
|
|
307
387
|
at: Date.now()
|
|
308
|
-
});
|
|
388
|
+
}, DEVTOOLS_EVENT_LIMIT);
|
|
309
389
|
payload.$script = instance;
|
|
310
390
|
syncScripts();
|
|
311
|
-
});
|
|
312
|
-
headHooks.hook("script:instance-fn", (ctx) => {
|
|
391
|
+
}));
|
|
392
|
+
addCleanup(headHooks.hook("script:instance-fn", (ctx) => {
|
|
313
393
|
if (ctx.script.id !== instance.id || String(ctx.fn).startsWith("__v_"))
|
|
314
394
|
return;
|
|
315
|
-
payload.events
|
|
395
|
+
pushBounded(payload.events, {
|
|
316
396
|
type: "fn-call",
|
|
317
397
|
fn: ctx.fn,
|
|
318
398
|
at: Date.now()
|
|
319
|
-
});
|
|
399
|
+
}, DEVTOOLS_EVENT_LIMIT);
|
|
320
400
|
syncScripts();
|
|
321
|
-
});
|
|
401
|
+
}));
|
|
322
402
|
payload.$script = instance;
|
|
323
403
|
if (err) {
|
|
324
|
-
payload.events
|
|
404
|
+
pushBounded(payload.events, {
|
|
325
405
|
type: "status",
|
|
326
406
|
status: "validation-failed",
|
|
327
407
|
args: err,
|
|
328
408
|
at: Date.now()
|
|
329
|
-
});
|
|
409
|
+
}, DEVTOOLS_EVENT_LIMIT);
|
|
330
410
|
}
|
|
331
|
-
payload.events
|
|
411
|
+
pushBounded(payload.events, {
|
|
332
412
|
type: "status",
|
|
333
413
|
status: "awaitingLoad",
|
|
334
414
|
trigger: options?.trigger,
|
|
335
415
|
at: Date.now()
|
|
336
|
-
});
|
|
416
|
+
}, DEVTOOLS_EVENT_LIMIT);
|
|
337
417
|
const scriptHostname = extractExternalHostname(input.src);
|
|
338
418
|
const domains = /* @__PURE__ */ new Set([
|
|
339
419
|
...scriptHostname ? [scriptHostname] : [],
|
|
340
420
|
...options.devtools?.domains || []
|
|
341
421
|
]);
|
|
342
422
|
let disconnectObserver = observeNetworkRequests(payload, domains, syncScripts, input.src);
|
|
343
|
-
|
|
423
|
+
addCleanup(() => disconnectObserver());
|
|
344
424
|
const _origReload = instance.reload;
|
|
345
|
-
instance.remove = () => {
|
|
346
|
-
disconnectObserver();
|
|
347
|
-
return _origRemove();
|
|
348
|
-
};
|
|
349
425
|
instance.reload = async () => {
|
|
350
426
|
disconnectObserver();
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
427
|
+
try {
|
|
428
|
+
return await _origReload();
|
|
429
|
+
} finally {
|
|
430
|
+
if (!cleaned)
|
|
431
|
+
disconnectObserver = observeNetworkRequests(payload, domains, syncScripts, input.src);
|
|
432
|
+
}
|
|
354
433
|
};
|
|
355
434
|
syncScripts();
|
|
356
435
|
}
|
|
357
436
|
}
|
|
358
|
-
markRaw(instance);
|
|
359
|
-
instance.toJSON = () => ({ id: instance.id, status: instance.status.value });
|
|
360
437
|
return instance;
|
|
361
438
|
}
|
|
@@ -11,30 +11,46 @@ export function useScriptEventPage(onChange) {
|
|
|
11
11
|
if (import.meta.server)
|
|
12
12
|
return payload;
|
|
13
13
|
let lastPayload = { path: "", title: "" };
|
|
14
|
-
let
|
|
15
|
-
|
|
14
|
+
let disposed = false;
|
|
15
|
+
const pendingCleanups = /* @__PURE__ */ new Set();
|
|
16
16
|
const stopPageFinishHook = nuxt.hooks.hook("page:finish", () => {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
17
|
+
let settled = false;
|
|
18
|
+
let stopDomWatcher = () => {
|
|
19
|
+
};
|
|
20
|
+
const timer = setTimeout(finish, 100);
|
|
21
|
+
function cleanup() {
|
|
22
|
+
clearTimeout(timer);
|
|
23
|
+
stopDomWatcher();
|
|
24
|
+
pendingCleanups.delete(cleanup);
|
|
25
|
+
}
|
|
26
|
+
function finish() {
|
|
27
|
+
if (settled)
|
|
28
|
+
return;
|
|
29
|
+
settled = true;
|
|
30
|
+
cleanup();
|
|
31
|
+
queueMicrotask(() => {
|
|
32
|
+
if (disposed)
|
|
33
|
+
return;
|
|
34
|
+
payload.value = {
|
|
35
|
+
path: route.fullPath,
|
|
36
|
+
title: document.title
|
|
37
|
+
};
|
|
38
|
+
if (lastPayload.path !== payload.value.path || lastPayload.title !== payload.value.title) {
|
|
39
|
+
if (onChange) {
|
|
40
|
+
onChange(payload.value);
|
|
41
|
+
}
|
|
42
|
+
lastPayload = payload.value;
|
|
31
43
|
}
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
pendingCleanups.add(cleanup);
|
|
47
|
+
stopDomWatcher = head.hooks.hook("dom:rendered", finish);
|
|
35
48
|
});
|
|
36
49
|
onScopeDispose(() => {
|
|
37
|
-
|
|
50
|
+
disposed = true;
|
|
51
|
+
for (const cleanup of pendingCleanups)
|
|
52
|
+
cleanup();
|
|
53
|
+
pendingCleanups.clear();
|
|
38
54
|
stopPageFinishHook();
|
|
39
55
|
});
|
|
40
56
|
return payload;
|
|
@@ -8,15 +8,29 @@ export function useScriptTriggerIdleTimeout(options) {
|
|
|
8
8
|
}
|
|
9
9
|
const { timeout } = options;
|
|
10
10
|
return new Promise((resolve) => {
|
|
11
|
+
let disposed = false;
|
|
12
|
+
let settled = false;
|
|
13
|
+
let stopTimer = () => {
|
|
14
|
+
};
|
|
15
|
+
const settle = (value) => {
|
|
16
|
+
if (settled)
|
|
17
|
+
return;
|
|
18
|
+
settled = true;
|
|
19
|
+
stopTimer();
|
|
20
|
+
resolve(value);
|
|
21
|
+
};
|
|
22
|
+
tryOnScopeDispose(() => {
|
|
23
|
+
disposed = true;
|
|
24
|
+
settle(false);
|
|
25
|
+
});
|
|
11
26
|
onNuxtReady(() => {
|
|
27
|
+
if (disposed)
|
|
28
|
+
return;
|
|
12
29
|
const { start, stop } = useTimeoutFn(() => {
|
|
13
|
-
|
|
30
|
+
settle(true);
|
|
14
31
|
}, timeout, { immediate: false });
|
|
32
|
+
stopTimer = stop;
|
|
15
33
|
start();
|
|
16
|
-
tryOnScopeDispose(() => {
|
|
17
|
-
stop();
|
|
18
|
-
resolve(false);
|
|
19
|
-
});
|
|
20
34
|
});
|
|
21
35
|
});
|
|
22
36
|
}
|
|
@@ -8,27 +8,40 @@ export function useScriptTriggerInteraction(options) {
|
|
|
8
8
|
}
|
|
9
9
|
const { events, target = document.documentElement } = options;
|
|
10
10
|
return new Promise((resolve) => {
|
|
11
|
+
let disposed = false;
|
|
12
|
+
let settled = false;
|
|
13
|
+
const cleanupFns = [];
|
|
14
|
+
const cleanup = () => {
|
|
15
|
+
cleanupFns.splice(0).forEach((fn) => fn());
|
|
16
|
+
};
|
|
17
|
+
const settle = (value) => {
|
|
18
|
+
if (settled)
|
|
19
|
+
return;
|
|
20
|
+
settled = true;
|
|
21
|
+
cleanup();
|
|
22
|
+
resolve(value);
|
|
23
|
+
};
|
|
24
|
+
tryOnScopeDispose(() => {
|
|
25
|
+
disposed = true;
|
|
26
|
+
settle(false);
|
|
27
|
+
});
|
|
11
28
|
onNuxtReady(() => {
|
|
29
|
+
if (disposed)
|
|
30
|
+
return;
|
|
12
31
|
if (!target) {
|
|
13
|
-
|
|
32
|
+
settle(false);
|
|
14
33
|
return;
|
|
15
34
|
}
|
|
16
|
-
const cleanupFns = [];
|
|
17
35
|
events.forEach((event) => {
|
|
18
|
-
const
|
|
36
|
+
const cleanup2 = useEventListener(
|
|
19
37
|
target,
|
|
20
38
|
event,
|
|
21
39
|
() => {
|
|
22
|
-
|
|
23
|
-
resolve(true);
|
|
40
|
+
settle(true);
|
|
24
41
|
},
|
|
25
42
|
{ once: true, passive: true }
|
|
26
43
|
);
|
|
27
|
-
cleanupFns.push(
|
|
28
|
-
});
|
|
29
|
-
tryOnScopeDispose(() => {
|
|
30
|
-
cleanupFns.forEach((fn) => fn());
|
|
31
|
-
resolve(false);
|
|
44
|
+
cleanupFns.push(cleanup2);
|
|
32
45
|
});
|
|
33
46
|
});
|
|
34
47
|
});
|
|
@@ -9,31 +9,34 @@ export function useScriptTriggerServiceWorker(options) {
|
|
|
9
9
|
resolve(true);
|
|
10
10
|
return;
|
|
11
11
|
}
|
|
12
|
-
let
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
let settled = false;
|
|
13
|
+
let timer;
|
|
14
|
+
const cleanup = () => {
|
|
15
|
+
navigator.serviceWorker.removeEventListener("controllerchange", onControllerChange);
|
|
16
|
+
if (timer !== void 0) {
|
|
17
|
+
clearTimeout(timer);
|
|
18
|
+
timer = void 0;
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
const done = (value) => {
|
|
22
|
+
if (settled)
|
|
15
23
|
return;
|
|
16
|
-
|
|
17
|
-
|
|
24
|
+
settled = true;
|
|
25
|
+
cleanup();
|
|
26
|
+
resolve(value);
|
|
18
27
|
};
|
|
28
|
+
function onControllerChange() {
|
|
29
|
+
done(true);
|
|
30
|
+
}
|
|
31
|
+
tryOnScopeDispose(() => done(false));
|
|
19
32
|
if (navigator.serviceWorker.controller) {
|
|
20
|
-
done();
|
|
33
|
+
done(true);
|
|
21
34
|
return;
|
|
22
35
|
}
|
|
23
|
-
const onControllerChange = () => {
|
|
24
|
-
navigator.serviceWorker.removeEventListener("controllerchange", onControllerChange);
|
|
25
|
-
done();
|
|
26
|
-
};
|
|
27
36
|
navigator.serviceWorker.addEventListener("controllerchange", onControllerChange);
|
|
28
|
-
|
|
29
|
-
navigator.serviceWorker.removeEventListener("controllerchange", onControllerChange);
|
|
37
|
+
timer = setTimeout(() => {
|
|
30
38
|
console.warn("[nuxt-scripts] Service worker not controlling after timeout, loading scripts anyway");
|
|
31
|
-
done();
|
|
39
|
+
done(true);
|
|
32
40
|
}, timeout);
|
|
33
|
-
tryOnScopeDispose(() => {
|
|
34
|
-
navigator.serviceWorker.removeEventListener("controllerchange", onControllerChange);
|
|
35
|
-
clearTimeout(timer);
|
|
36
|
-
resolve(false);
|
|
37
|
-
});
|
|
38
41
|
});
|
|
39
42
|
}
|
|
@@ -5,15 +5,23 @@ export default defineNuxtPlugin(() => {
|
|
|
5
5
|
const version = config.public["nuxt-scripts"]?.version;
|
|
6
6
|
const firstPartyData = config.public["nuxt-scripts-devtools"] || null;
|
|
7
7
|
let lastScripts = {};
|
|
8
|
+
let disposed = false;
|
|
9
|
+
let requestController;
|
|
8
10
|
function pushState(scripts) {
|
|
11
|
+
if (disposed)
|
|
12
|
+
return;
|
|
9
13
|
if (scripts)
|
|
10
14
|
lastScripts = scripts;
|
|
11
15
|
const route = nuxtApp.$router?.currentRoute?.value;
|
|
12
16
|
if (route?.path?.startsWith("/__nuxt-scripts"))
|
|
13
17
|
return;
|
|
18
|
+
requestController?.abort();
|
|
19
|
+
const controller = new AbortController();
|
|
20
|
+
requestController = controller;
|
|
14
21
|
fetch("/__nuxt-scripts-api/state", {
|
|
15
22
|
method: "POST",
|
|
16
23
|
headers: { "Content-Type": "application/json" },
|
|
24
|
+
signal: controller.signal,
|
|
17
25
|
body: JSON.stringify({
|
|
18
26
|
scripts: serializeScripts(lastScripts),
|
|
19
27
|
version,
|
|
@@ -21,16 +29,33 @@ export default defineNuxtPlugin(() => {
|
|
|
21
29
|
route: route ? { path: route.path, fullPath: route.fullPath, query: route.query } : null
|
|
22
30
|
})
|
|
23
31
|
}).catch((error) => {
|
|
24
|
-
if (import.meta.dev)
|
|
32
|
+
if (import.meta.dev && error?.name !== "AbortError")
|
|
25
33
|
console.warn("[nuxt-scripts] Failed to sync standalone devtools state:", error);
|
|
34
|
+
}).finally(() => {
|
|
35
|
+
if (requestController === controller)
|
|
36
|
+
requestController = void 0;
|
|
26
37
|
});
|
|
27
38
|
}
|
|
28
|
-
nuxtApp.hooks.hook("scripts:updated", (ctx) => {
|
|
39
|
+
const stopScriptsHook = nuxtApp.hooks.hook("scripts:updated", (ctx) => {
|
|
29
40
|
pushState(ctx.scripts);
|
|
30
41
|
});
|
|
31
|
-
nuxtApp.$router?.afterEach(() => {
|
|
42
|
+
const stopRouterHook = nuxtApp.$router?.afterEach(() => {
|
|
32
43
|
pushState();
|
|
33
44
|
});
|
|
45
|
+
let stopUnmountHook = () => {
|
|
46
|
+
};
|
|
47
|
+
const cleanup = () => {
|
|
48
|
+
if (disposed)
|
|
49
|
+
return;
|
|
50
|
+
disposed = true;
|
|
51
|
+
requestController?.abort();
|
|
52
|
+
requestController = void 0;
|
|
53
|
+
lastScripts = {};
|
|
54
|
+
stopScriptsHook();
|
|
55
|
+
stopRouterHook?.();
|
|
56
|
+
stopUnmountHook();
|
|
57
|
+
};
|
|
58
|
+
stopUnmountHook = nuxtApp.hooks.hook("app:unmount", cleanup);
|
|
34
59
|
pushState(nuxtApp._scripts || {});
|
|
35
60
|
});
|
|
36
61
|
function serializeScripts(scripts) {
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
type ScriptApi = Record<string | symbol, any>;
|
|
2
|
+
/**
|
|
3
|
+
* Keeps Unhead's recording proxy while an SDK loads, then forwards calls to
|
|
4
|
+
* the resolved SDK without discarding their return values.
|
|
5
|
+
*/
|
|
6
|
+
export declare function createNpmScriptProxy<T extends ScriptApi>(fallback: T, getApi: () => T | undefined): T;
|
|
7
|
+
export {};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
function walk(root, path) {
|
|
2
|
+
let owner;
|
|
3
|
+
let value = root;
|
|
4
|
+
for (const key of path) {
|
|
5
|
+
if (value == null)
|
|
6
|
+
return { owner: void 0, value: void 0 };
|
|
7
|
+
owner = value;
|
|
8
|
+
value = Reflect.get(value, key, value);
|
|
9
|
+
}
|
|
10
|
+
return { owner, value };
|
|
11
|
+
}
|
|
12
|
+
export function createNpmScriptProxy(fallback, getApi) {
|
|
13
|
+
function node(path, fallbackValue) {
|
|
14
|
+
const children = /* @__PURE__ */ new Map();
|
|
15
|
+
return new Proxy(() => {
|
|
16
|
+
}, {
|
|
17
|
+
get(_, property) {
|
|
18
|
+
const api = getApi();
|
|
19
|
+
let value;
|
|
20
|
+
if (api) {
|
|
21
|
+
const current = walk(api, path).value;
|
|
22
|
+
value = current == null ? void 0 : Reflect.get(current, property, current);
|
|
23
|
+
} else {
|
|
24
|
+
value = Reflect.get(fallbackValue, property, fallbackValue);
|
|
25
|
+
}
|
|
26
|
+
if (typeof value !== "function")
|
|
27
|
+
return value;
|
|
28
|
+
let child = children.get(property);
|
|
29
|
+
if (!child) {
|
|
30
|
+
child = node([...path, property], value);
|
|
31
|
+
children.set(property, child);
|
|
32
|
+
}
|
|
33
|
+
return child;
|
|
34
|
+
},
|
|
35
|
+
apply(_, thisArg, args) {
|
|
36
|
+
const api = getApi();
|
|
37
|
+
if (api) {
|
|
38
|
+
const { owner, value } = walk(api, path);
|
|
39
|
+
return Reflect.apply(value, owner, args);
|
|
40
|
+
}
|
|
41
|
+
return Reflect.apply(fallbackValue, thisArg, args);
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
return node([], fallback);
|
|
46
|
+
}
|
|
@@ -3,7 +3,6 @@ import { logger } from "./logger.js";
|
|
|
3
3
|
export function createNpmScriptStub(options) {
|
|
4
4
|
const status = ref("awaitingLoad");
|
|
5
5
|
const loadedCallbacks = [];
|
|
6
|
-
let initPromise = null;
|
|
7
6
|
let hasInitialized = false;
|
|
8
7
|
const proxy = options.use?.() || {};
|
|
9
8
|
const stub = {
|
|
@@ -17,12 +16,11 @@ export function createNpmScriptStub(options) {
|
|
|
17
16
|
try {
|
|
18
17
|
if (options.clientInit) {
|
|
19
18
|
console.log(`[NpmScriptStub] Initializing ${options.key}...`);
|
|
20
|
-
|
|
21
|
-
await initPromise;
|
|
19
|
+
await options.clientInit();
|
|
22
20
|
console.log(`[NpmScriptStub] ${options.key} initialized successfully`);
|
|
23
21
|
}
|
|
24
22
|
status.value = "loaded";
|
|
25
|
-
loadedCallbacks.forEach((cb) => {
|
|
23
|
+
loadedCallbacks.splice(0).forEach((cb) => {
|
|
26
24
|
try {
|
|
27
25
|
cb(proxy);
|
|
28
26
|
} catch (error) {
|
|
@@ -30,6 +28,7 @@ export function createNpmScriptStub(options) {
|
|
|
30
28
|
}
|
|
31
29
|
});
|
|
32
30
|
} catch (error) {
|
|
31
|
+
loadedCallbacks.splice(0);
|
|
33
32
|
logger.error(`[NpmScriptStub] Failed to initialize ${options.key}:`, error);
|
|
34
33
|
status.value = "error";
|
|
35
34
|
}
|
|
@@ -37,7 +36,7 @@ export function createNpmScriptStub(options) {
|
|
|
37
36
|
onLoaded(callback) {
|
|
38
37
|
if (status.value === "loaded") {
|
|
39
38
|
callback(proxy);
|
|
40
|
-
} else {
|
|
39
|
+
} else if (status.value !== "error") {
|
|
41
40
|
loadedCallbacks.push(callback);
|
|
42
41
|
}
|
|
43
42
|
},
|