@nuxt/scripts 1.0.0-beta.1 → 1.0.0-beta.3

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.
Files changed (70) hide show
  1. package/README.md +6 -0
  2. package/dist/client/200.html +1 -1
  3. package/dist/client/404.html +1 -1
  4. package/dist/client/_nuxt/CD5B-xvT.js +1 -0
  5. package/dist/client/_nuxt/D-kOnTuH.js +162 -0
  6. package/dist/client/_nuxt/DdVDSbUA.js +1 -0
  7. package/dist/client/_nuxt/{DTDyDxvR.js → Ds2G8aQM.js} +1 -1
  8. package/dist/client/_nuxt/builds/latest.json +1 -1
  9. package/dist/client/_nuxt/builds/meta/f1474569-6922-450d-bc3f-4fd5f3e1391a.json +1 -0
  10. package/dist/client/_nuxt/entry.D45OuV0w.css +1 -0
  11. package/dist/client/_nuxt/error-404.B57D-jUQ.css +1 -0
  12. package/dist/client/_nuxt/error-500.DTHUW7BI.css +1 -0
  13. package/dist/client/index.html +1 -1
  14. package/dist/module.d.mts +87 -2
  15. package/dist/module.json +1 -1
  16. package/dist/module.mjs +678 -142
  17. package/dist/registry.mjs +11 -0
  18. package/dist/runtime/components/ScriptInstagramEmbed.d.vue.ts +53 -0
  19. package/dist/runtime/components/ScriptInstagramEmbed.vue +38 -0
  20. package/dist/runtime/components/ScriptInstagramEmbed.vue.d.ts +53 -0
  21. package/dist/runtime/components/ScriptXEmbed.d.vue.ts +82 -0
  22. package/dist/runtime/components/ScriptXEmbed.vue +76 -0
  23. package/dist/runtime/components/ScriptXEmbed.vue.d.ts +82 -0
  24. package/dist/runtime/composables/useScript.js +24 -3
  25. package/dist/runtime/composables/useScriptTriggerServiceWorker.d.ts +7 -0
  26. package/dist/runtime/composables/useScriptTriggerServiceWorker.js +39 -0
  27. package/dist/runtime/plugins/sw-register.client.d.ts +2 -0
  28. package/dist/runtime/plugins/sw-register.client.js +12 -0
  29. package/dist/runtime/registry/instagram-embed.d.ts +23 -0
  30. package/dist/runtime/registry/instagram-embed.js +22 -0
  31. package/dist/runtime/registry/lemon-squeezy.d.ts +0 -1
  32. package/dist/runtime/registry/plausible-analytics.js +2 -2
  33. package/dist/runtime/registry/posthog.d.ts +1 -0
  34. package/dist/runtime/registry/posthog.js +2 -8
  35. package/dist/runtime/registry/tiktok-pixel.d.ts +1 -0
  36. package/dist/runtime/registry/tiktok-pixel.js +1 -0
  37. package/dist/runtime/registry/x-embed.d.ts +77 -0
  38. package/dist/runtime/registry/x-embed.js +41 -0
  39. package/dist/runtime/server/instagram-embed-asset.d.ts +2 -0
  40. package/dist/runtime/server/instagram-embed-asset.js +42 -0
  41. package/dist/runtime/server/instagram-embed-image.d.ts +2 -0
  42. package/dist/runtime/server/instagram-embed-image.js +54 -0
  43. package/dist/runtime/server/instagram-embed.d.ts +2 -0
  44. package/dist/runtime/server/instagram-embed.js +91 -0
  45. package/dist/runtime/server/proxy-handler.d.ts +6 -0
  46. package/dist/runtime/server/proxy-handler.js +246 -0
  47. package/dist/runtime/server/sw-handler.d.ts +2 -0
  48. package/dist/runtime/server/sw-handler.js +25 -0
  49. package/dist/runtime/server/utils/privacy.d.ts +141 -0
  50. package/dist/runtime/server/utils/privacy.js +309 -0
  51. package/dist/runtime/server/x-embed-image.d.ts +2 -0
  52. package/dist/runtime/server/x-embed-image.js +53 -0
  53. package/dist/runtime/server/x-embed.d.ts +49 -0
  54. package/dist/runtime/server/x-embed.js +31 -0
  55. package/dist/runtime/sw/proxy-sw.template.d.ts +1 -0
  56. package/dist/runtime/sw/proxy-sw.template.js +54 -0
  57. package/dist/runtime/types.d.ts +29 -0
  58. package/dist/runtime/utils/pure.d.ts +13 -0
  59. package/dist/runtime/utils/pure.js +67 -0
  60. package/dist/runtime/utils.d.ts +1 -1
  61. package/dist/runtime/utils.js +2 -1
  62. package/dist/types.d.mts +1 -1
  63. package/package.json +27 -26
  64. package/dist/client/_nuxt/Bdf7Qtwg.js +0 -1
  65. package/dist/client/_nuxt/CoyZWCgl.js +0 -162
  66. package/dist/client/_nuxt/Ds1k3yKJ.js +0 -1
  67. package/dist/client/_nuxt/builds/meta/62574f80-71d4-4f9e-8b96-145c85230d99.json +0 -1
  68. package/dist/client/_nuxt/entry.BjfcJo5q.css +0 -1
  69. package/dist/client/_nuxt/error-404.D45Vtjcx.css +0 -1
  70. package/dist/client/_nuxt/error-500.BOm1rWQf.css +0 -1
@@ -57,8 +57,24 @@ export type NuxtUseScriptOptions<T extends Record<symbol | string, any> = {}> =
57
57
  * - `false` - Do not bundle the script. (default)
58
58
  *
59
59
  * Note: Using 'force' may significantly increase build time as scripts will be re-downloaded on every build.
60
+ *
61
+ * @deprecated Use `scripts.firstParty: true` in nuxt.config instead for bundling and routing scripts through your domain.
60
62
  */
61
63
  bundle?: boolean | 'force';
64
+ /**
65
+ * Opt-out of first-party routing for this specific script when global `scripts.firstParty` is enabled.
66
+ * Set to `false` to load this script directly from its original source instead of through your domain.
67
+ *
68
+ * Note: This option only works as an opt-out. To enable first-party routing, use the global `scripts.firstParty` option in nuxt.config.
69
+ */
70
+ firstParty?: false;
71
+ /**
72
+ * Load the script in a web worker using Partytown.
73
+ * When enabled, adds `type="text/partytown"` to the script tag.
74
+ * Requires @nuxtjs/partytown to be installed and configured separately.
75
+ * @see https://partytown.qwik.dev/
76
+ */
77
+ partytown?: boolean;
62
78
  /**
63
79
  * Skip any schema validation for the script input. This is useful for loading the script stubs for development without
64
80
  * loading the actual script and not getting warnings.
@@ -99,6 +115,8 @@ export type NuxtUseScriptOptionsSerializable = Omit<NuxtUseScriptOptions, 'use'
99
115
  idleTimeout: number;
100
116
  } | {
101
117
  interaction: string[];
118
+ } | {
119
+ serviceWorker: true;
102
120
  };
103
121
  };
104
122
  export type NuxtUseScriptInput = UseScriptInput;
@@ -193,6 +211,17 @@ export type RegistryScriptInput<T = EmptyOptionsSchema, Bundelable extends boole
193
211
  export interface RegistryScript {
194
212
  import?: Import;
195
213
  scriptBundling?: false | ((options?: any) => string | false);
214
+ /**
215
+ * First-party routing configuration for this script.
216
+ * - `string` - The proxy config key to use (e.g., 'googleAnalytics', 'metaPixel')
217
+ * - `false` - Explicitly disable first-party routing for this script
218
+ * - `undefined` - Use the default key derived from the function name
219
+ *
220
+ * When set to a string, the script's URLs will be rewritten and collection
221
+ * endpoints will be routed through your server when `scripts.firstParty` is enabled.
222
+ * @internal
223
+ */
224
+ proxy?: string | false;
196
225
  label?: string;
197
226
  src?: string | false;
198
227
  category?: string;
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Proxy configuration for third-party scripts.
3
+ */
4
+ export interface ProxyRewrite {
5
+ /** Domain and path to match (e.g., 'www.google-analytics.com/g/collect') */
6
+ from: string;
7
+ /** Local path to rewrite to (e.g., '/_scripts/c/ga/g/collect') */
8
+ to: string;
9
+ }
10
+ /**
11
+ * Rewrite URLs in script content based on proxy config.
12
+ */
13
+ export declare function rewriteScriptUrls(content: string, rewrites: ProxyRewrite[]): string;
@@ -0,0 +1,67 @@
1
+ import { parseURL, joinURL } from "ufo";
2
+ export function rewriteScriptUrls(content, rewrites) {
3
+ let result = content;
4
+ const literalRegex = /(['"`])(.*?)\1/g;
5
+ for (const { from, to } of rewrites) {
6
+ const isSuffixMatch = from.startsWith(".");
7
+ const fromSlashIdx = from.indexOf("/");
8
+ const fromHost = fromSlashIdx > 0 ? from.slice(0, fromSlashIdx) : from;
9
+ const fromPath = fromSlashIdx > 0 ? from.slice(fromSlashIdx) : "";
10
+ result = result.replace(literalRegex, (match, quote, inner) => {
11
+ if (!inner.includes(fromHost)) return match;
12
+ const url = parseURL(inner);
13
+ let shouldRewrite = false;
14
+ let rewriteSuffix = "";
15
+ if (url.host) {
16
+ const hostMatches = isSuffixMatch ? url.host.endsWith(fromHost) : url.host === fromHost;
17
+ if (hostMatches) {
18
+ const fullPath = url.pathname + (url.search || "") + (url.hash || "");
19
+ if (fromPath && fullPath.startsWith(fromPath)) {
20
+ shouldRewrite = true;
21
+ rewriteSuffix = fullPath.slice(fromPath.length);
22
+ } else if (!fromPath) {
23
+ shouldRewrite = true;
24
+ rewriteSuffix = fullPath;
25
+ }
26
+ }
27
+ } else if (inner.startsWith("//")) {
28
+ const hostPart = inner.slice(2).split("/")[0];
29
+ const hostMatches = isSuffixMatch ? hostPart?.endsWith(fromHost) ?? false : hostPart === fromHost;
30
+ if (hostMatches) {
31
+ const remainder = inner.slice(2 + (hostPart?.length ?? 0));
32
+ if (fromPath && remainder.startsWith(fromPath)) {
33
+ shouldRewrite = true;
34
+ rewriteSuffix = remainder.slice(fromPath.length);
35
+ } else if (!fromPath) {
36
+ shouldRewrite = true;
37
+ rewriteSuffix = remainder;
38
+ }
39
+ }
40
+ } else if (fromPath && (inner.startsWith(from) || isSuffixMatch && inner.includes(from))) {
41
+ const domainEnd = inner.indexOf(from) + from.length;
42
+ const nextChar = inner[domainEnd];
43
+ if (!nextChar || nextChar === "/" || nextChar === "?" || nextChar === "#") {
44
+ shouldRewrite = true;
45
+ rewriteSuffix = inner.slice(domainEnd);
46
+ }
47
+ }
48
+ if (shouldRewrite) {
49
+ const rewritten = rewriteSuffix === "/" || rewriteSuffix.startsWith("?") || rewriteSuffix.startsWith("#") ? to + rewriteSuffix : joinURL(to, rewriteSuffix);
50
+ return quote + rewritten + quote;
51
+ }
52
+ return match;
53
+ });
54
+ }
55
+ const gaRewrite = rewrites.find((r) => r.from.includes("google-analytics.com/g/collect"));
56
+ if (gaRewrite) {
57
+ result = result.replace(
58
+ /"https:\/\/"\+\(.*?\)\+"\.google-analytics\.com\/g\/collect"/g,
59
+ `"${gaRewrite.to}"`
60
+ );
61
+ result = result.replace(
62
+ /"https:\/\/"\+\(.*?\)\+"\.analytics\.google\.com\/g\/collect"/g,
63
+ `"${gaRewrite.to}"`
64
+ );
65
+ }
66
+ return result;
67
+ }
@@ -15,4 +15,4 @@ type OptionsFn<O> = (options: InferIfSchema<O>, ctx: {
15
15
  });
16
16
  export declare function scriptRuntimeConfig<T extends keyof ScriptRegistry>(key: T): ScriptRegistry[T];
17
17
  export declare function useRegistryScript<T extends Record<string | symbol, any>, O = EmptyOptionsSchema>(registryKey: keyof ScriptRegistry | string, optionsFn: OptionsFn<O>, _userOptions?: RegistryScriptInput<O>): UseScriptContext<UseFunctionType<NuxtUseScriptOptions<T>, T>>;
18
- export {};
18
+ export * from './utils/pure.js';
@@ -1,9 +1,9 @@
1
1
  import { defu } from "defu";
2
2
  import { useRuntimeConfig } from "nuxt/app";
3
+ import { parseURL, withQuery, parseQuery } from "ufo";
3
4
  import { useScript } from "./composables/useScript.js";
4
5
  import { createNpmScriptStub } from "./npm-script-stub.js";
5
6
  import { parse } from "#nuxt-scripts-validator";
6
- import { parseURL, withQuery, parseQuery } from "ufo";
7
7
  function validateScriptInputSchema(key, schema, options) {
8
8
  if (import.meta.dev) {
9
9
  try {
@@ -95,3 +95,4 @@ export function useRegistryScript(registryKey, optionsFn, _userOptions) {
95
95
  };
96
96
  return useScript(scriptInput, scriptOptions);
97
97
  }
98
+ export * from "./utils/pure.js";
package/dist/types.d.mts CHANGED
@@ -6,4 +6,4 @@ declare module '@nuxt/schema' {
6
6
 
7
7
  export { default } from './module.mjs'
8
8
 
9
- export { type ModuleHooks, type ModuleOptions } from './module.mjs'
9
+ export { type FirstPartyOptions, type FirstPartyPrivacy, type ModuleHooks, type ModuleOptions } from './module.mjs'
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@nuxt/scripts",
3
3
  "type": "module",
4
- "version": "1.0.0-beta.1",
4
+ "version": "1.0.0-beta.3",
5
5
  "description": "Load third-party scripts with better performance, privacy and DX in Nuxt Apps.",
6
6
  "author": {
7
7
  "website": "https://harlanzw.com",
@@ -87,51 +87,52 @@
87
87
  }
88
88
  },
89
89
  "dependencies": {
90
- "@nuxt/kit": "^4.2.2",
91
- "@vueuse/core": "^14.1.0",
90
+ "@nuxt/devtools-kit": "^3.2.2",
91
+ "@nuxt/kit": "^4.3.1",
92
+ "@vueuse/core": "^14.2.1",
92
93
  "consola": "^3.4.2",
93
94
  "defu": "^6.1.4",
94
- "estree-walker": "^3.0.3",
95
95
  "h3": "^1.15.5",
96
96
  "magic-string": "^0.30.21",
97
97
  "ofetch": "^1.5.1",
98
98
  "ohash": "^2.0.11",
99
+ "oxc-parser": "^0.115.0",
100
+ "oxc-walker": "^0.7.0",
99
101
  "pathe": "^2.0.3",
100
102
  "pkg-types": "^2.3.0",
101
103
  "sirv": "^3.0.2",
102
104
  "std-env": "^3.10.0",
103
105
  "ufo": "^1.6.3",
104
- "unplugin": "^2.3.11",
106
+ "unplugin": "^3.0.0",
105
107
  "unstorage": "^1.17.4",
106
108
  "valibot": "^1.2.0"
107
109
  },
108
110
  "devDependencies": {
109
- "@nuxt/devtools-kit": "^3.1.1",
110
- "@nuxt/devtools-ui-kit": "^3.1.1",
111
- "@nuxt/eslint-config": "^1.12.1",
111
+ "@nuxt/devtools-ui-kit": "^3.2.2",
112
+ "@nuxt/eslint-config": "^1.15.2",
112
113
  "@nuxt/module-builder": "^1.0.2",
113
- "@nuxt/test-utils": "3.19.2",
114
- "@paypal/paypal-js": "^9.2.0",
114
+ "@nuxt/test-utils": "^4.0.0",
115
+ "@nuxtjs/partytown": "^2.0.0",
116
+ "@paypal/paypal-js": "^9.3.0",
115
117
  "@types/semver": "^7.7.1",
116
- "@typescript-eslint/typescript-estree": "^8.53.1",
118
+ "@typescript-eslint/typescript-estree": "^8.56.1",
117
119
  "@vue/test-utils": "^2.4.6",
118
- "acorn-loose": "^8.5.2",
119
- "bumpp": "^10.4.0",
120
+ "bumpp": "^10.4.1",
120
121
  "changelogen": "^0.6.2",
121
- "eslint": "^9.39.2",
122
- "eslint-plugin-n": "^17.23.2",
123
- "happy-dom": "^20.3.4",
122
+ "eslint": "^10.0.2",
123
+ "eslint-plugin-n": "^17.24.0",
124
+ "happy-dom": "^20.7.0",
124
125
  "knitwork": "^1.3.0",
125
- "nuxt": "^4.2.2",
126
- "playwright-core": "^1.57.0",
127
- "posthog-js": "^1.331.0",
128
- "shiki": "^3.21.0",
126
+ "nuxt": "^4.3.1",
127
+ "playwright-core": "^1.58.2",
128
+ "posthog-js": "^1.353.1",
129
+ "shiki": "^3.22.0",
129
130
  "typescript": "5.9.3",
130
- "vitest": "^4.0.17",
131
- "vue": "^3.5.27",
132
- "vue-router": "^4.6.4",
133
- "vue-tsc": "^3.2.2",
134
- "@nuxt/scripts": "1.0.0-beta.1"
131
+ "vitest": "^4.0.18",
132
+ "vue": "^3.5.29",
133
+ "vue-router": "^5.0.3",
134
+ "vue-tsc": "^3.2.5",
135
+ "@nuxt/scripts": "1.0.0-beta.3"
135
136
  },
136
137
  "resolutions": {
137
138
  "@nuxt/scripts": "workspace:*"
@@ -142,7 +143,7 @@
142
143
  "client:dev": "nuxi dev client --port 3300",
143
144
  "dev": "nuxi dev playground",
144
145
  "dev:ssl": "nuxi dev playground --https",
145
- "prepare:fixtures": "nuxi prepare test/fixtures/basic && nuxi prepare test/fixtures/cdn && nuxi prepare test/fixtures/extend-registry",
146
+ "prepare:fixtures": "nuxi prepare test/fixtures/basic && nuxi prepare test/fixtures/cdn && nuxi prepare test/fixtures/extend-registry && nuxi prepare test/fixtures/partytown && nuxi prepare test/fixtures/first-party",
146
147
  "dev:prepare": "nuxt-module-build build --stub && nuxt-module-build prepare && nuxi prepare playground && pnpm run prepare:fixtures",
147
148
  "typecheck": "vue-tsc --noEmit",
148
149
  "bump": "bumpp package.json --commit --push --tag",
@@ -1 +0,0 @@
1
- import{_ as s,c as a,o as i,a as t,t as n,b as u,w as c,d as l,e as d}from"./CoyZWCgl.js";import{u as f}from"./DTDyDxvR.js";const p={class:"antialiased bg-white dark:bg-[#020420] dark:text-white font-sans grid min-h-screen overflow-hidden place-content-center text-[#020420] tracking-wide"},m={class:"max-w-520px text-center"},h=["textContent"],g=["textContent"],b=["textContent"],x={class:"flex items-center justify-center w-full"},y={__name:"error-404",props:{appName:{type:String,default:"Nuxt"},statusCode:{type:Number,default:404},statusMessage:{type:String,default:"Page not found"},description:{type:String,default:"Sorry, the page you are looking for could not be found."},backHome:{type:String,default:"Go back home"}},setup(e){const r=e;return f({title:`${r.statusCode} - ${r.statusMessage} | ${r.appName}`,script:[{innerHTML:`!function(){const e=document.createElement("link").relList;if(!(e&&e.supports&&e.supports("modulepreload"))){for(const e of document.querySelectorAll('link[rel="modulepreload"]'))r(e);new MutationObserver(e=>{for(const o of e)if("childList"===o.type)for(const e of o.addedNodes)"LINK"===e.tagName&&"modulepreload"===e.rel&&r(e)}).observe(document,{childList:!0,subtree:!0})}function r(e){if(e.ep)return;e.ep=!0;const r=function(e){const r={};return e.integrity&&(r.integrity=e.integrity),e.referrerPolicy&&(r.referrerPolicy=e.referrerPolicy),"use-credentials"===e.crossOrigin?r.credentials="include":"anonymous"===e.crossOrigin?r.credentials="omit":r.credentials="same-origin",r}(e);fetch(e.href,r)}}();`}],style:[{innerHTML:'*,:after,:before{border-color:var(--un-default-border-color,#e5e7eb);border-style:solid;border-width:0;box-sizing:border-box}:after,:before{--un-content:""}html{line-height:1.5;-webkit-text-size-adjust:100%;font-family:ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;font-feature-settings:normal;font-variation-settings:normal;-moz-tab-size:4;tab-size:4;-webkit-tap-highlight-color:transparent}body{line-height:inherit;margin:0}h1,h2{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}h1,h2,p{margin:0}*,:after,:before{--un-rotate:0;--un-rotate-x:0;--un-rotate-y:0;--un-rotate-z:0;--un-scale-x:1;--un-scale-y:1;--un-scale-z:1;--un-skew-x:0;--un-skew-y:0;--un-translate-x:0;--un-translate-y:0;--un-translate-z:0;--un-pan-x: ;--un-pan-y: ;--un-pinch-zoom: ;--un-scroll-snap-strictness:proximity;--un-ordinal: ;--un-slashed-zero: ;--un-numeric-figure: ;--un-numeric-spacing: ;--un-numeric-fraction: ;--un-border-spacing-x:0;--un-border-spacing-y:0;--un-ring-offset-shadow:0 0 transparent;--un-ring-shadow:0 0 transparent;--un-shadow-inset: ;--un-shadow:0 0 transparent;--un-ring-inset: ;--un-ring-offset-width:0px;--un-ring-offset-color:#fff;--un-ring-width:0px;--un-ring-color:rgba(147,197,253,.5);--un-blur: ;--un-brightness: ;--un-contrast: ;--un-drop-shadow: ;--un-grayscale: ;--un-hue-rotate: ;--un-invert: ;--un-saturate: ;--un-sepia: ;--un-backdrop-blur: ;--un-backdrop-brightness: ;--un-backdrop-contrast: ;--un-backdrop-grayscale: ;--un-backdrop-hue-rotate: ;--un-backdrop-invert: ;--un-backdrop-opacity: ;--un-backdrop-saturate: ;--un-backdrop-sepia: }'}]}),(k,w)=>{const o=d;return i(),a("div",p,[t("div",m,[t("h1",{class:"font-semibold leading-none mb-4 sm:text-[110px] tabular-nums text-[80px]",textContent:n(e.statusCode)},null,8,h),t("h2",{class:"font-semibold mb-2 sm:text-3xl text-2xl",textContent:n(e.statusMessage)},null,8,g),t("p",{class:"mb-4 px-2 text-[#64748B] text-md",textContent:n(e.description)},null,8,b),t("div",x,[u(o,{to:"/",class:"font-medium hover:text-[#00DC82] text-sm underline underline-offset-3"},{default:c(()=>[l(n(e.backHome),1)]),_:1})])])])}}},v=s(y,[["__scopeId","data-v-75dfa5e6"]]);export{v as default};