@nuxt/hints 0.0.0 → 1.0.0-alpha.10

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 (210) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +140 -0
  3. package/dist/client/200.html +1 -0
  4. package/dist/client/404.html +1 -0
  5. package/dist/client/_nuxt/2EtD6e53.js +1 -0
  6. package/dist/client/_nuxt/32ctXXKs.js +1 -0
  7. package/dist/client/_nuxt/3e1v2bzS.js +1 -0
  8. package/dist/client/_nuxt/5X7smno1.js +1 -0
  9. package/dist/client/_nuxt/5i3qLPDT.js +1 -0
  10. package/dist/client/_nuxt/B0m2ddpp.js +1 -0
  11. package/dist/client/_nuxt/B1dDrJ26.js +1 -0
  12. package/dist/client/_nuxt/B5Mb093_.js +1 -0
  13. package/dist/client/_nuxt/B6aJPvgy.js +1 -0
  14. package/dist/client/_nuxt/B7mTdjB0.js +1 -0
  15. package/dist/client/_nuxt/BA47KaF1.js +1 -0
  16. package/dist/client/_nuxt/BD7vbABK.js +1 -0
  17. package/dist/client/_nuxt/BEDo0Tqx.js +1 -0
  18. package/dist/client/_nuxt/BGJmEYvX.js +1 -0
  19. package/dist/client/_nuxt/BIGW1oBm.js +1 -0
  20. package/dist/client/_nuxt/BLmx8bSh.js +1 -0
  21. package/dist/client/_nuxt/BLtJtn59.js +1 -0
  22. package/dist/client/_nuxt/BN7gUcg9.js +1 -0
  23. package/dist/client/_nuxt/BPQ3VLAy.js +1 -0
  24. package/dist/client/_nuxt/BUw7H-hv.js +1 -0
  25. package/dist/client/_nuxt/BXkSAIEj.js +1 -0
  26. package/dist/client/_nuxt/BchVSmrD.js +6 -0
  27. package/dist/client/_nuxt/BfHTSMKl.js +1 -0
  28. package/dist/client/_nuxt/BfjtVDDH.js +1 -0
  29. package/dist/client/_nuxt/BgDCqdQA.js +1 -0
  30. package/dist/client/_nuxt/Bkuqu6BP.js +1 -0
  31. package/dist/client/_nuxt/Bp3cYrEr.js +1 -0
  32. package/dist/client/_nuxt/Br6cN0cg.js +1 -0
  33. package/dist/client/_nuxt/BthQWCQV.js +1 -0
  34. package/dist/client/_nuxt/Buea-lGh.js +1 -0
  35. package/dist/client/_nuxt/Bw305WKR.js +1 -0
  36. package/dist/client/_nuxt/Bxupbja9.js +4 -0
  37. package/dist/client/_nuxt/BygCkY0G.js +1 -0
  38. package/dist/client/_nuxt/Byy-EI8A.js +1 -0
  39. package/dist/client/_nuxt/BzJJZx-M.js +1 -0
  40. package/dist/client/_nuxt/C39BiMTA.js +1 -0
  41. package/dist/client/_nuxt/C3Wv6jpd.js +1 -0
  42. package/dist/client/_nuxt/C3mMm8J8.js +1 -0
  43. package/dist/client/_nuxt/C4gqWexZ.js +1 -0
  44. package/dist/client/_nuxt/C8M2exoo.js +1 -0
  45. package/dist/client/_nuxt/C9dUb6Cb.js +1 -0
  46. package/dist/client/_nuxt/C9oPPf7i.js +1 -0
  47. package/dist/client/_nuxt/C9tS-k6U.js +1 -0
  48. package/dist/client/_nuxt/CD8AGNRT.js +1 -0
  49. package/dist/client/_nuxt/CDVJQ6XC.js +1 -0
  50. package/dist/client/_nuxt/CFHQjOhq.js +1 -0
  51. package/dist/client/_nuxt/CG6Dc4jp.js +1 -0
  52. package/dist/client/_nuxt/CH1njM8p.js +1 -0
  53. package/dist/client/_nuxt/CMTm3GFP.js +1 -0
  54. package/dist/client/_nuxt/COt5Ahok.js +1 -0
  55. package/dist/client/_nuxt/CS3Unz2-.js +1 -0
  56. package/dist/client/_nuxt/CTRr51gU.js +1 -0
  57. package/dist/client/_nuxt/CVO1_9PV.js +1 -0
  58. package/dist/client/_nuxt/CVdnzihN.js +1 -0
  59. package/dist/client/_nuxt/CW8IKDeL.js +1 -0
  60. package/dist/client/_nuxt/CXZktZb0.js +1 -0
  61. package/dist/client/_nuxt/CXtECtnM.js +1 -0
  62. package/dist/client/_nuxt/CYsAdtH9.js +1 -0
  63. package/dist/client/_nuxt/CafNBF8u.js +1 -0
  64. package/dist/client/_nuxt/CbfX1IO0.js +1 -0
  65. package/dist/client/_nuxt/Cc68jesL.js +1 -0
  66. package/dist/client/_nuxt/CfQXZHmo.js +1 -0
  67. package/dist/client/_nuxt/Cj5Yp3dK.js +1 -0
  68. package/dist/client/_nuxt/CkXjmgJE.js +1 -0
  69. package/dist/client/_nuxt/Cl0AqbOI.js +1 -0
  70. package/dist/client/_nuxt/Cm3UrAx6.js +1 -0
  71. package/dist/client/_nuxt/CmIQRyeF.js +1 -0
  72. package/dist/client/_nuxt/Cmh6b_Ma.js +1 -0
  73. package/dist/client/_nuxt/Cn-bp-IR.js +1 -0
  74. package/dist/client/_nuxt/CnnebwVN.js +1 -0
  75. package/dist/client/_nuxt/Cp-IABpG.js +1 -0
  76. package/dist/client/_nuxt/Csfq5Kiy.js +1 -0
  77. package/dist/client/_nuxt/CufHLc7y.js +1 -0
  78. package/dist/client/_nuxt/CuhuY25u.js +1 -0
  79. package/dist/client/_nuxt/Cuk6v7N8.js +1 -0
  80. package/dist/client/_nuxt/Cvjx9yec.js +1 -0
  81. package/dist/client/_nuxt/CxbxFI8M.js +1 -0
  82. package/dist/client/_nuxt/CyktbL80.js +1 -0
  83. package/dist/client/_nuxt/CylS5w8V.js +1 -0
  84. package/dist/client/_nuxt/D-2ljcwZ.js +1 -0
  85. package/dist/client/_nuxt/D0r3Knsf.js +1 -0
  86. package/dist/client/_nuxt/D2Qjm2dq.js +1 -0
  87. package/dist/client/_nuxt/D2ZA7i9S.js +1 -0
  88. package/dist/client/_nuxt/D4_iv3hh.js +1 -0
  89. package/dist/client/_nuxt/D4h5O-jR.js +1 -0
  90. package/dist/client/_nuxt/D5KoaKCx.js +1 -0
  91. package/dist/client/_nuxt/D7oLnXFd.js +1 -0
  92. package/dist/client/_nuxt/D87Tk5Gz.js +1 -0
  93. package/dist/client/_nuxt/DAi9KRSo.js +1 -0
  94. package/dist/client/_nuxt/DBKV2OwM.js +1 -0
  95. package/dist/client/_nuxt/DEthMvLe.js +1 -0
  96. package/dist/client/_nuxt/DFWUc33u.js +1 -0
  97. package/dist/client/_nuxt/DFlZdHUX.js +1 -0
  98. package/dist/client/_nuxt/DGP4VlC8.js +1 -0
  99. package/dist/client/_nuxt/DGztddWO.js +1 -0
  100. package/dist/client/_nuxt/DH5Ifo-i.js +1 -0
  101. package/dist/client/_nuxt/DHJKELXO.js +1 -0
  102. package/dist/client/_nuxt/DHQR4-dF.js +1 -0
  103. package/dist/client/_nuxt/DJjDtW9f.js +1 -0
  104. package/dist/client/_nuxt/DPfMkruS.js +1 -0
  105. package/dist/client/_nuxt/DQyhUUbL.js +1 -0
  106. package/dist/client/_nuxt/DRw_LuNl.js +1 -0
  107. package/dist/client/_nuxt/DSeZwD4N.js +1 -0
  108. package/dist/client/_nuxt/DU1UobuO.js +1 -0
  109. package/dist/client/_nuxt/DUszq2jm.js +1 -0
  110. package/dist/client/_nuxt/DVMEJ2y_.js +1 -0
  111. package/dist/client/_nuxt/DWedfzmr.js +1 -0
  112. package/dist/client/_nuxt/DXbdFlpD.js +1 -0
  113. package/dist/client/_nuxt/DYE7WIF3.js +1 -0
  114. package/dist/client/_nuxt/DZxFcAj9.js +1 -0
  115. package/dist/client/_nuxt/DaskW291.js +1 -0
  116. package/dist/client/_nuxt/DcaNXYhu.js +1 -0
  117. package/dist/client/_nuxt/Ddv68eIx.js +1 -0
  118. package/dist/client/_nuxt/Des-eS-w.js +1 -0
  119. package/dist/client/_nuxt/DgsIRcX7.js +1 -0
  120. package/dist/client/_nuxt/DnULxvSX.js +1 -0
  121. package/dist/client/_nuxt/DqQDbK_p.js +1 -0
  122. package/dist/client/_nuxt/DqwNpetd.js +1 -0
  123. package/dist/client/_nuxt/Dspwwk_N.js +1 -0
  124. package/dist/client/_nuxt/Dx-B1_4e.js +1 -0
  125. package/dist/client/_nuxt/DxNHbxmM.js +1 -0
  126. package/dist/client/_nuxt/DxSwrfjg.js +1 -0
  127. package/dist/client/_nuxt/E3gJ1_iC.js +1 -0
  128. package/dist/client/_nuxt/GsRaNv29.js +1 -0
  129. package/dist/client/_nuxt/L9t79GZl.js +1 -0
  130. package/dist/client/_nuxt/MzD3tlZU.js +1 -0
  131. package/dist/client/_nuxt/SCyfE3vN.js +1 -0
  132. package/dist/client/_nuxt/W9tJ9s81.js +1 -0
  133. package/dist/client/_nuxt/X0qVHnNL.js +1 -0
  134. package/dist/client/_nuxt/Yzrsuije.js +1 -0
  135. package/dist/client/_nuxt/bN70gL4F.js +1 -0
  136. package/dist/client/_nuxt/builds/latest.json +1 -0
  137. package/dist/client/_nuxt/builds/meta/988a741f-ba30-4645-9949-60dd86de74e2.json +1 -0
  138. package/dist/client/_nuxt/entry.bXb283Sw.css +1 -0
  139. package/dist/client/_nuxt/error-404.LspKb3Ne.css +1 -0
  140. package/dist/client/_nuxt/error-500.B_qDdXYW.css +1 -0
  141. package/dist/client/_nuxt/fuZLfV_i.js +1 -0
  142. package/dist/client/_nuxt/g9-lgVsj.js +1 -0
  143. package/dist/client/_nuxt/gufSdAgD.js +36 -0
  144. package/dist/client/_nuxt/hJgmCMqR.js +1 -0
  145. package/dist/client/_nuxt/hegEt444.js +1 -0
  146. package/dist/client/_nuxt/hydration.C8A3o8hr.css +1 -0
  147. package/dist/client/_nuxt/m17aaUwq.js +1 -0
  148. package/dist/client/_nuxt/qdsjHGoJ.js +1 -0
  149. package/dist/client/_nuxt/wDzz0qaB.js +1 -0
  150. package/dist/client/_nuxt/zVBI731p.js +9 -0
  151. package/dist/client/component-lazy-load/index.html +1 -0
  152. package/dist/client/hydration/index.html +1 -0
  153. package/dist/client/index.html +1 -0
  154. package/dist/client/third-party-scripts/index.html +1 -0
  155. package/dist/client/web-vitals/index.html +1 -0
  156. package/dist/module.d.mts +10 -0
  157. package/dist/module.json +9 -0
  158. package/dist/module.mjs +442 -0
  159. package/dist/runtime/core/components/nuxt-island.d.ts +2 -0
  160. package/dist/runtime/core/components/nuxt-island.js +15 -0
  161. package/dist/runtime/core/features.d.ts +4 -0
  162. package/dist/runtime/core/features.js +10 -0
  163. package/dist/runtime/core/plugins/features.client.d.ts +2 -0
  164. package/dist/runtime/core/plugins/features.client.js +16 -0
  165. package/dist/runtime/core/plugins/vue-tracer-state.client.d.ts +2 -0
  166. package/dist/runtime/core/plugins/vue-tracer-state.client.js +7 -0
  167. package/dist/runtime/core/server/sse.d.ts +2 -0
  168. package/dist/runtime/core/server/sse.js +16 -0
  169. package/dist/runtime/core/server/types.d.ts +12 -0
  170. package/dist/runtime/core/server/types.js +2 -0
  171. package/dist/runtime/core/types.d.ts +9 -0
  172. package/dist/runtime/core/types.js +0 -0
  173. package/dist/runtime/hydration/component.d.ts +3 -0
  174. package/dist/runtime/hydration/component.js +22 -0
  175. package/dist/runtime/hydration/composables.d.ts +5 -0
  176. package/dist/runtime/hydration/composables.js +45 -0
  177. package/dist/runtime/hydration/nitro.plugin.d.ts +2 -0
  178. package/dist/runtime/hydration/nitro.plugin.js +65 -0
  179. package/dist/runtime/hydration/plugin.client.d.ts +2 -0
  180. package/dist/runtime/hydration/plugin.client.js +11 -0
  181. package/dist/runtime/hydration/types.d.ts +29 -0
  182. package/dist/runtime/hydration/types.js +0 -0
  183. package/dist/runtime/hydration/utils.d.ts +4 -0
  184. package/dist/runtime/hydration/utils.js +26 -0
  185. package/dist/runtime/lazy-load/composables.d.ts +11 -0
  186. package/dist/runtime/lazy-load/composables.js +52 -0
  187. package/dist/runtime/lazy-load/nitro.plugin.d.ts +2 -0
  188. package/dist/runtime/lazy-load/nitro.plugin.js +59 -0
  189. package/dist/runtime/lazy-load/plugin.client.d.ts +2 -0
  190. package/dist/runtime/lazy-load/plugin.client.js +73 -0
  191. package/dist/runtime/lazy-load/schema.d.ts +28 -0
  192. package/dist/runtime/lazy-load/schema.js +16 -0
  193. package/dist/runtime/lazy-load/utils.d.ts +2 -0
  194. package/dist/runtime/lazy-load/utils.js +4 -0
  195. package/dist/runtime/logger.d.ts +3 -0
  196. package/dist/runtime/logger.js +8 -0
  197. package/dist/runtime/third-party-scripts/nitro.plugin.d.ts +2 -0
  198. package/dist/runtime/third-party-scripts/nitro.plugin.js +48 -0
  199. package/dist/runtime/third-party-scripts/plugin.client.d.ts +2 -0
  200. package/dist/runtime/third-party-scripts/plugin.client.js +93 -0
  201. package/dist/runtime/third-party-scripts/utils.d.ts +1 -0
  202. package/dist/runtime/third-party-scripts/utils.js +2 -0
  203. package/dist/runtime/types.d.ts +80 -0
  204. package/dist/runtime/web-vitals/plugin.client.d.ts +13 -0
  205. package/dist/runtime/web-vitals/plugin.client.js +138 -0
  206. package/dist/runtime/web-vitals/utils.d.ts +36 -0
  207. package/dist/runtime/web-vitals/utils.js +15 -0
  208. package/dist/types.d.mts +3 -0
  209. package/package.json +70 -2
  210. /package/dist/{.gitkeep → client/_nuxt/third-party-scripts.tn0RQdqM.css} +0 -0
@@ -0,0 +1,9 @@
1
+ {
2
+ "name": "@nuxt/hints",
3
+ "configKey": "hints",
4
+ "version": "1.0.0-alpha.10",
5
+ "builder": {
6
+ "@nuxt/module-builder": "1.0.2",
7
+ "unbuild": "3.6.1"
8
+ }
9
+ }
@@ -0,0 +1,442 @@
1
+ import { addDevServerHandler, useNuxt, defineNuxtModule, createResolver, addTemplate, addServerTemplate, addPlugin, addComponent, addServerHandler, addBuildPlugin, addServerPlugin } from '@nuxt/kit';
2
+ import { HINTS_SSE_ROUTE } from '../dist/runtime/core/server/types.js';
3
+ import { existsSync } from 'node:fs';
4
+ import { eventHandler, proxyRequest } from 'h3';
5
+ import { genImport } from 'knitwork';
6
+ import MagicString from 'magic-string';
7
+ import { dirname, resolve, parse } from 'node:path';
8
+ import { parseSync, Visitor } from 'oxc-parser';
9
+ import { createUnplugin } from 'unplugin';
10
+ import { fileURLToPath } from 'node:url';
11
+
12
+ const DEVTOOLS_UI_ROUTE = "/__nuxt-hints";
13
+ const DEVTOOLS_UI_LOCAL_PORT = 3300;
14
+ function setupDevToolsUI(nuxt, resolver) {
15
+ const clientPath = resolver.resolve("./client");
16
+ const isProductionBuild = existsSync(clientPath);
17
+ if (isProductionBuild) {
18
+ nuxt.hook("vite:serverCreated", async (server) => {
19
+ const sirv = await import('sirv').then((r) => r.default || r);
20
+ server.middlewares.use(
21
+ DEVTOOLS_UI_ROUTE,
22
+ sirv(clientPath, { dev: true, single: true })
23
+ );
24
+ });
25
+ } else {
26
+ addDevServerHandler({
27
+ route: DEVTOOLS_UI_ROUTE,
28
+ handler: eventHandler((e) => {
29
+ return proxyRequest(e, "http://localhost:" + DEVTOOLS_UI_LOCAL_PORT + DEVTOOLS_UI_ROUTE + e.path);
30
+ })
31
+ });
32
+ }
33
+ nuxt.hook("devtools:customTabs", (tabs) => {
34
+ tabs.push({
35
+ name: "hints",
36
+ title: "Hints",
37
+ icon: "carbon:idea",
38
+ category: "analyze",
39
+ view: {
40
+ type: "iframe",
41
+ src: DEVTOOLS_UI_ROUTE
42
+ }
43
+ });
44
+ });
45
+ }
46
+
47
+ const distDir = dirname(fileURLToPath(import.meta.url));
48
+
49
+ const INCLUDE_VUE_RE = /\.vue$/;
50
+ const EXCLUDE_NODE_MODULES$1 = /node_modules|dist/;
51
+ const DEFINE_COMPONENT_RE = /defineComponent/;
52
+ const DEFINE_NUXT_COMPONENT_RE = /defineNuxtComponent/;
53
+ const skipPath$1 = normalizePath$1(resolve(distDir, "runtime/hydration/component.ts"));
54
+ const InjectHydrationPlugin = createUnplugin(() => {
55
+ return [
56
+ {
57
+ name: "@nuxt/hints:modify-hydration-composable-import",
58
+ enforce: "post",
59
+ transform: {
60
+ filter: {
61
+ id: {
62
+ include: /.(vue|ts|js|tsx|jsx)$/,
63
+ exclude: [skipPath$1, EXCLUDE_NODE_MODULES$1]
64
+ },
65
+ code: {
66
+ include: [DEFINE_COMPONENT_RE, DEFINE_NUXT_COMPONENT_RE]
67
+ }
68
+ },
69
+ async handler(code, id) {
70
+ const m = new MagicString(code);
71
+ const { program } = parseSync(id, code);
72
+ const imports = program.body.filter((node) => node.type === "ImportDeclaration");
73
+ const hasDefineComponent = DEFINE_COMPONENT_RE.test(code);
74
+ const hasDefineNuxtComponent = DEFINE_NUXT_COMPONENT_RE.test(code);
75
+ const defineComponentImport = findImportSpecifier(
76
+ imports,
77
+ "defineComponent",
78
+ ["vue", "#imports"],
79
+ (specifier, nextSpecifier) => {
80
+ m.remove(
81
+ specifier.start,
82
+ nextSpecifier?.start ?? specifier.end
83
+ );
84
+ }
85
+ );
86
+ const defineComponentAlias = defineComponentImport?.local.name || "defineComponent";
87
+ const defineNuxtComponentImport = findImportSpecifier(
88
+ imports,
89
+ "defineNuxtComponent",
90
+ ["#app/composables/component", "#imports", "#app", "nuxt/app"],
91
+ (specifier, next) => {
92
+ m.remove(
93
+ specifier.start,
94
+ next?.start ?? specifier.end
95
+ );
96
+ }
97
+ );
98
+ const defineNuxtComponentAlias = defineNuxtComponentImport?.local.name || "defineNuxtComponent";
99
+ const importsToAdd = new Set([
100
+ hasDefineComponent && genImport(
101
+ "@nuxt/hints/runtime/hydration/component",
102
+ [defineComponentAlias === "defineComponent" ? "defineComponent" : { name: "defineComponent", as: defineComponentAlias }]
103
+ ),
104
+ hasDefineNuxtComponent && genImport(
105
+ "@nuxt/hints/runtime/hydration/component",
106
+ [defineNuxtComponentAlias === "defineNuxtComponent" ? "defineNuxtComponent" : { name: "defineNuxtComponent", as: defineNuxtComponentAlias }]
107
+ )
108
+ ].filter(Boolean));
109
+ m.prepend([...importsToAdd].join("\n") + "\n");
110
+ if (m.hasChanged()) {
111
+ return {
112
+ code: m.toString(),
113
+ map: m.generateMap({ hires: true })
114
+ };
115
+ }
116
+ }
117
+ }
118
+ },
119
+ {
120
+ name: "@nuxt/hints:inject-hydration-composable",
121
+ enforce: "post",
122
+ transform: {
123
+ filter: {
124
+ id: {
125
+ include: INCLUDE_VUE_RE,
126
+ exclude: [skipPath$1, EXCLUDE_NODE_MODULES$1]
127
+ },
128
+ code: {
129
+ exclude: [DEFINE_COMPONENT_RE, DEFINE_NUXT_COMPONENT_RE]
130
+ }
131
+ },
132
+ handler(code, id) {
133
+ const m = new MagicString(code);
134
+ const { program } = parseSync(id, code);
135
+ const exportDeclaration = program.body.find(
136
+ (node) => node.type === "ExportDefaultDeclaration"
137
+ )?.declaration;
138
+ if (exportDeclaration) {
139
+ m.prepend(genImport(
140
+ "@nuxt/hints/runtime/hydration/component",
141
+ ["defineComponent"]
142
+ ));
143
+ m.overwrite(
144
+ exportDeclaration.start,
145
+ exportDeclaration.end,
146
+ `defineComponent(${code.slice(exportDeclaration.start, exportDeclaration.end)})`
147
+ );
148
+ }
149
+ if (m.hasChanged()) {
150
+ return {
151
+ code: m.toString(),
152
+ map: m.generateMap({ hires: true })
153
+ };
154
+ }
155
+ }
156
+ }
157
+ }
158
+ ];
159
+ });
160
+ function findImportSpecifier(importDecl, importedName, pkgNames, callback) {
161
+ const names = Array.isArray(pkgNames) ? pkgNames : [pkgNames];
162
+ const allSpecifiers = importDecl.filter((imp) => names.includes(imp.source.value)).flatMap((decl) => decl.specifiers.map((spec, i) => ({ spec, next: decl.specifiers[i + 1] })));
163
+ const match = allSpecifiers.find(
164
+ ({ spec }) => spec.type === "ImportSpecifier" && spec.imported.type === "Identifier" && spec.imported.name === importedName
165
+ );
166
+ if (match) {
167
+ callback?.(match.spec, match.next);
168
+ return match.spec;
169
+ }
170
+ }
171
+ function normalizePath$1(path) {
172
+ return path.replace(/\\/g, "/");
173
+ }
174
+
175
+ function findDefineComponentCalls(program) {
176
+ const imports = program.body.filter(
177
+ (node) => node.type === "ImportDeclaration"
178
+ );
179
+ const defineComponentImport = findImport("defineComponent", imports);
180
+ const defineComponentNames = /* @__PURE__ */ new Set(["defineNuxtComponent"]);
181
+ if (defineComponentImport) {
182
+ for (const specifier of defineComponentImport.specifiers) {
183
+ if (specifier.type === "ImportSpecifier" && specifier.imported.type === "Identifier") {
184
+ defineComponentNames.add(specifier.local.name);
185
+ }
186
+ }
187
+ }
188
+ const defineComponentNodes = [];
189
+ const visitor = new Visitor({
190
+ CallExpression(node) {
191
+ if (node.callee.type === "Identifier" && defineComponentNames.has(node.callee.name)) {
192
+ defineComponentNodes.push(node);
193
+ }
194
+ }
195
+ });
196
+ visitor.visit(program);
197
+ return defineComponentNodes;
198
+ }
199
+ function findImport(name, imports) {
200
+ return imports.find((imp) => {
201
+ return imp.specifiers.some((specifier) => {
202
+ if (specifier.type === "ImportSpecifier" && specifier.imported.type === "Identifier") {
203
+ return specifier.imported.name === name;
204
+ }
205
+ return false;
206
+ });
207
+ });
208
+ }
209
+
210
+ const INCLUDE_FILES = /\.(vue|tsx?|jsx?)$/;
211
+ const EXCLUDE_NODE_MODULES = /node_modules/;
212
+ const skipPath = normalizePath(resolve(distDir, "runtime/lazy-load"));
213
+ const LazyLoadHintPlugin = createUnplugin(() => {
214
+ const nuxt = useNuxt();
215
+ let nuxtComponents = nuxt.apps.default.components;
216
+ nuxt.hook("components:extend", (extendedComponents) => {
217
+ nuxtComponents = extendedComponents;
218
+ });
219
+ return {
220
+ name: "@nuxt/hints:lazy-load-plugin",
221
+ enforce: "post",
222
+ transform: {
223
+ filter: {
224
+ id: {
225
+ include: INCLUDE_FILES,
226
+ exclude: [skipPath, EXCLUDE_NODE_MODULES]
227
+ }
228
+ },
229
+ handler(code, id) {
230
+ const m = new MagicString(code);
231
+ const { program } = parseSync(id, code);
232
+ const imports = program.body.filter(
233
+ (node) => node.type === "ImportDeclaration"
234
+ );
235
+ const directComponentImports = [];
236
+ for (const importDecl of imports) {
237
+ const source = importDecl.source.value;
238
+ if (!source.endsWith(".vue")) continue;
239
+ if (importDecl.importKind === "type") continue;
240
+ for (const specifier of importDecl.specifiers ?? []) {
241
+ if (specifier.type === "ImportDefaultSpecifier" || specifier.type === "ImportSpecifier") {
242
+ const localName = specifier.local.name;
243
+ directComponentImports.push({
244
+ name: localName,
245
+ source,
246
+ start: importDecl.start,
247
+ end: importDecl.end,
248
+ specifier
249
+ });
250
+ }
251
+ }
252
+ }
253
+ if (directComponentImports.length === 0) {
254
+ return;
255
+ }
256
+ m.prepend(genImport(
257
+ "@nuxt/hints/runtime/lazy-load/composables",
258
+ ["__wrapImportedComponent", "__wrapMainComponent"]
259
+ ) + "\n" + genImport(
260
+ "@nuxt/hints/runtime/lazy-load/composables",
261
+ ["useLazyComponentTracking"]
262
+ ) + "\n");
263
+ const wrapperStatements = directComponentImports.map((imp) => {
264
+ const originalName = `__original_${imp.name}`;
265
+ const resolvedName = resolveComponentName(imp, nuxtComponents);
266
+ return `const ${imp.name} = __wrapImportedComponent(${originalName}, '${resolvedName}', '${imp.source}', '${normalizePath(id)}')`;
267
+ }).join("\n");
268
+ for (const imp of directComponentImports) {
269
+ const specifier = imp.specifier;
270
+ const localName = specifier.local.name;
271
+ const newName = `__original_${localName}`;
272
+ if (specifier.type === "ImportDefaultSpecifier") {
273
+ m.overwrite(
274
+ specifier.local.start,
275
+ specifier.local.end,
276
+ newName
277
+ );
278
+ } else if (specifier.type === "ImportSpecifier" && specifier.imported.type === "Identifier" && specifier.imported.name !== specifier.local.name) {
279
+ m.overwrite(
280
+ specifier.local.start,
281
+ specifier.local.end,
282
+ newName
283
+ );
284
+ } else {
285
+ m.overwrite(
286
+ specifier.local.start,
287
+ specifier.local.end,
288
+ `${localName} as ${newName}`
289
+ );
290
+ }
291
+ }
292
+ if (code.includes("_sfc_main")) {
293
+ const wrappedComponents = directComponentImports.map((imp) => {
294
+ const componentName = resolveComponentName(imp, nuxtComponents);
295
+ return `{ componentName: '${componentName}', importSource: '${imp.source}', importedBy: '${normalizePath(id)}', rendered: false }`;
296
+ }).join(", ");
297
+ m.replace("export default _sfc_main", `const _sfc_main_wrapped = __wrapMainComponent(_sfc_main, [${wrappedComponents}]);
298
+ export default _sfc_main_wrapped`);
299
+ }
300
+ const components = findDefineComponentCalls(program);
301
+ if (components && components.length > 0) {
302
+ for (const comp of components) {
303
+ injectUseLazyComponentTrackingInComponentSetup(comp, m, directComponentImports, id, nuxtComponents);
304
+ }
305
+ }
306
+ const lastImport = imports[imports.length - 1];
307
+ if (lastImport) {
308
+ m.appendRight(lastImport.end, "\n" + wrapperStatements);
309
+ } else {
310
+ m.prepend(wrapperStatements + "\n");
311
+ }
312
+ if (m.hasChanged()) {
313
+ return {
314
+ code: m.toString(),
315
+ map: m.generateMap({ hires: true })
316
+ };
317
+ }
318
+ }
319
+ }
320
+ };
321
+ });
322
+ function normalizePath(path) {
323
+ return path.replace(/\\/g, "/");
324
+ }
325
+ function resolveComponentName(imp, nuxtComponents) {
326
+ const component = nuxtComponents.find((c) => c.filePath === imp.source);
327
+ if (component) return component.pascalName;
328
+ return imp.name.startsWith("__nuxt") ? parse(imp.source).name : imp.name;
329
+ }
330
+ function injectUseLazyComponentTrackingInComponentSetup(node, magicString, directComponentImports, id, nuxtComponents) {
331
+ if (node.arguments.length === 1) {
332
+ const arg = node.arguments[0];
333
+ if (arg?.type === "ObjectExpression") {
334
+ const properties = arg.properties;
335
+ const setupProp = properties.find(
336
+ (prop) => prop.type === "Property" && prop.key.type === "Identifier" && prop.key.name === "setup"
337
+ );
338
+ if (setupProp && setupProp.type === "Property") {
339
+ const setupFunc = setupProp.value;
340
+ if (setupFunc.type === "FunctionExpression" || setupFunc.type === "ArrowFunctionExpression") {
341
+ const insertPos = (setupFunc.body?.start ?? 0) + 1;
342
+ const componentsArray = directComponentImports.map((imp) => {
343
+ const componentName = resolveComponentName(imp, nuxtComponents);
344
+ return `{ componentName: '${componentName}', importSource: '${imp.source}', importedBy: '${normalizePath(id)}', rendered: false }`;
345
+ }).join(", ");
346
+ const injectionCode = `
347
+ const lazyHydrationState = useLazyComponentTracking([${componentsArray}]);
348
+ `;
349
+ magicString.appendLeft(insertPos, injectionCode);
350
+ }
351
+ }
352
+ }
353
+ }
354
+ }
355
+
356
+ function isFeatureDevtoolsEnabled(options, feature) {
357
+ return typeof options.features[feature] === "object" ? options.features[feature].devtools : !!options.features[feature];
358
+ }
359
+ function isFeatureEnabled(options, feature) {
360
+ return !!options.features[feature];
361
+ }
362
+
363
+ const moduleName = "@nuxt/hints";
364
+ const module$1 = defineNuxtModule({
365
+ meta: {
366
+ name: moduleName,
367
+ configKey: "hints"
368
+ },
369
+ defaults: {
370
+ devtools: true,
371
+ features: {
372
+ hydration: true,
373
+ lazyLoad: true,
374
+ webVitals: true,
375
+ thirdPartyScripts: true
376
+ }
377
+ },
378
+ setup(options, nuxt) {
379
+ if (!nuxt.options.dev) {
380
+ return;
381
+ }
382
+ nuxt.options.nitro.experimental = nuxt.options.nitro.experimental || {};
383
+ nuxt.options.nitro.experimental.websocket = true;
384
+ const resolver = createResolver(import.meta.url);
385
+ const hintsConfigContent = `export const features = ${JSON.stringify(options.features)}`;
386
+ const hintsConfig = addTemplate({
387
+ filename: "#hints-config",
388
+ getContents: () => hintsConfigContent
389
+ });
390
+ nuxt.options.alias["#hints-config"] = hintsConfig.dst;
391
+ addServerTemplate({
392
+ filename: "#hints-config",
393
+ getContents: () => hintsConfigContent
394
+ });
395
+ addPlugin(resolver.resolve("./runtime/core/plugins/features.client"));
396
+ addComponent({
397
+ name: "NuxtIsland",
398
+ filePath: resolver.resolve("./runtime/core/components/nuxt-island"),
399
+ priority: 1e3
400
+ });
401
+ addServerHandler({
402
+ route: HINTS_SSE_ROUTE,
403
+ handler: resolver.resolve("./runtime/core/server/sse")
404
+ });
405
+ if (isFeatureEnabled(options, "webVitals")) {
406
+ addPlugin(resolver.resolve("./runtime/web-vitals/plugin.client"));
407
+ }
408
+ if (isFeatureEnabled(options, "hydration")) {
409
+ addPlugin(resolver.resolve("./runtime/hydration/plugin.client"));
410
+ addBuildPlugin(InjectHydrationPlugin);
411
+ addServerPlugin(resolver.resolve("./runtime/hydration/nitro.plugin"));
412
+ }
413
+ if (isFeatureEnabled(options, "lazyLoad")) {
414
+ addPlugin(resolver.resolve("./runtime/lazy-load/plugin.client"));
415
+ if (isFeatureDevtoolsEnabled(options, "lazyLoad")) {
416
+ addServerPlugin(resolver.resolve("./runtime/lazy-load/nitro.plugin"));
417
+ }
418
+ nuxt.hook("modules:done", () => {
419
+ addBuildPlugin(LazyLoadHintPlugin, { client: false });
420
+ addBuildPlugin(LazyLoadHintPlugin, { server: false });
421
+ });
422
+ }
423
+ if (isFeatureEnabled(options, "thirdPartyScripts")) {
424
+ addPlugin(resolver.resolve("./runtime/third-party-scripts/plugin.client"));
425
+ if (isFeatureDevtoolsEnabled(options, "thirdPartyScripts")) {
426
+ addServerPlugin(resolver.resolve("./runtime/third-party-scripts/nitro.plugin"));
427
+ }
428
+ }
429
+ nuxt.hook("prepare:types", ({ references }) => {
430
+ references.push({
431
+ types: resolver.resolve("./runtime/types.d.ts")
432
+ });
433
+ });
434
+ if (options.devtools) {
435
+ setupDevToolsUI(nuxt, resolver);
436
+ addPlugin(resolver.resolve("./runtime/core/plugins/vue-tracer-state.client"));
437
+ }
438
+ nuxt.options.build.transpile.push(moduleName);
439
+ }
440
+ });
441
+
442
+ export { module$1 as default };
@@ -0,0 +1,2 @@
1
+ declare const HintsNuxtIsland: any;
2
+ export default HintsNuxtIsland;
@@ -0,0 +1,15 @@
1
+ import NuxtIsland from "#app/components/nuxt-island";
2
+ import { useNuxtApp } from "#imports";
3
+ import { logger } from "../../logger.js";
4
+ const originalSetup = NuxtIsland.setup;
5
+ const HintsNuxtIsland = Object.assign({}, NuxtIsland, {
6
+ setup(props, ctx) {
7
+ if (useNuxtApp().ssrContext?.islandContext) {
8
+ logger.warn(
9
+ `Nesting islands within islands is not recommanded for performance reasons. This leads to waterfall calls.`
10
+ );
11
+ }
12
+ return originalSetup(props, ctx);
13
+ }
14
+ });
15
+ export default HintsNuxtIsland;
@@ -0,0 +1,4 @@
1
+ import type { FeaturesName } from './types.js';
2
+ export declare function isFeatureDevtoolsEnabled(feature: FeaturesName): boolean;
3
+ export declare function isFeatureLogsEnabled(feature: FeaturesName): boolean;
4
+ export declare function isFeatureEnabled(feature: FeaturesName): boolean;
@@ -0,0 +1,10 @@
1
+ import { features } from "#hints-config";
2
+ export function isFeatureDevtoolsEnabled(feature) {
3
+ return typeof features[feature] === "object" ? features[feature].devtools : !!features[feature];
4
+ }
5
+ export function isFeatureLogsEnabled(feature) {
6
+ return typeof features[feature] === "object" ? features[feature].logs : !!features[feature];
7
+ }
8
+ export function isFeatureEnabled(feature) {
9
+ return !!features[feature];
10
+ }
@@ -0,0 +1,2 @@
1
+ declare const _default: any;
2
+ export default _default;
@@ -0,0 +1,16 @@
1
+ import { defineNuxtPlugin } from "#imports";
2
+ import { features } from "#hints-config";
3
+ export default defineNuxtPlugin({
4
+ name: "hints:features",
5
+ setup(nuxtApp) {
6
+ Object.defineProperty(nuxtApp, "hints", {
7
+ get() {
8
+ return Object.freeze({
9
+ config: {
10
+ features
11
+ }
12
+ });
13
+ }
14
+ });
15
+ }
16
+ });
@@ -0,0 +1,2 @@
1
+ declare const _default: any;
2
+ export default _default;
@@ -0,0 +1,7 @@
1
+ import * as tracerOverlay from "vite-plugin-vue-tracer/client/overlay";
2
+ import * as tracerRecord from "vite-plugin-vue-tracer/client/record";
3
+ import { defineNuxtPlugin } from "#imports";
4
+ export default defineNuxtPlugin((nuxtApp) => {
5
+ nuxtApp.__tracerOverlay = tracerOverlay;
6
+ nuxtApp.__tracerRecord = tracerRecord;
7
+ });
@@ -0,0 +1,2 @@
1
+ declare const _default: import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<void>>;
2
+ export default _default;
@@ -0,0 +1,16 @@
1
+ import { createEventStream, defineEventHandler } from "h3";
2
+ import { useNitroApp } from "nitropack/runtime";
3
+ export default defineEventHandler((event) => {
4
+ const nitro = useNitroApp();
5
+ const eventStream = createEventStream(event);
6
+ const context = {
7
+ eventStream,
8
+ unsubscribers: []
9
+ };
10
+ nitro.hooks.callHook("hints:sse:setup", context);
11
+ eventStream.onClosed(async () => {
12
+ context.unsubscribers.forEach((unsub) => unsub());
13
+ await eventStream.close();
14
+ });
15
+ return eventStream.send();
16
+ });
@@ -0,0 +1,12 @@
1
+ import type { EventHandler, EventStream, H3Event } from 'h3';
2
+ export interface HintsApiContext {
3
+ event: H3Event;
4
+ path: string;
5
+ handler?: EventHandler;
6
+ }
7
+ export interface HintsSseContext {
8
+ eventStream: EventStream;
9
+ unsubscribers: (() => void)[];
10
+ }
11
+ export declare const HINTS_ROUTE = "/__nuxt_hints";
12
+ export declare const HINTS_SSE_ROUTE = "/__nuxt_hints/sse";
@@ -0,0 +1,2 @@
1
+ export const HINTS_ROUTE = "/__nuxt_hints";
2
+ export const HINTS_SSE_ROUTE = "/__nuxt_hints/sse";
@@ -0,0 +1,9 @@
1
+ export type FeaturesName = 'hydration' | 'lazyLoad' | 'webVitals' | 'thirdPartyScripts';
2
+ /**
3
+ * FF used by modules options and to expose in the payload for devtools
4
+ */
5
+ export type FeatureFlags = {
6
+ logs: boolean;
7
+ devtools: boolean;
8
+ };
9
+ export type Features = Record<FeaturesName, FeatureFlags>;
File without changes
@@ -0,0 +1,3 @@
1
+ import { defineComponent as _defineComponent } from '#imports';
2
+ export declare const defineNuxtComponent: typeof _defineComponent;
3
+ export declare const defineComponent: typeof _defineComponent;
@@ -0,0 +1,22 @@
1
+ import { defineNuxtComponent as _defineNuxtComponent, defineComponent as _defineComponent } from "#imports";
2
+ import { useHydrationCheck } from "./composables.js";
3
+ export const defineNuxtComponent = function defineNuxtComponent2(...args) {
4
+ const [options, key] = args;
5
+ const { setup } = options;
6
+ options.setup = function(props, ctx) {
7
+ useHydrationCheck();
8
+ return setup ? setup(props, ctx) : void 0;
9
+ };
10
+ return _defineNuxtComponent(options, key);
11
+ };
12
+ export const defineComponent = function defineComponent2(...args) {
13
+ const [options] = args;
14
+ if (typeof options === "object" && options !== null) {
15
+ const { setup } = options;
16
+ options.setup = function(props, ctx) {
17
+ useHydrationCheck();
18
+ return setup ? setup(props, ctx) : void 0;
19
+ };
20
+ }
21
+ return _defineComponent(options);
22
+ };
@@ -0,0 +1,5 @@
1
+ /**
2
+ * prefer implementing onMismatch hook after vue 3.6
3
+ * compare element
4
+ */
5
+ export declare function useHydrationCheck(): void;
@@ -0,0 +1,45 @@
1
+ import { getCurrentInstance, inject, onMounted } from "vue";
2
+ import { useNuxtApp } from "#imports";
3
+ import { HYDRATION_ROUTE, formatHTML, logger } from "./utils.js";
4
+ import { clientOnlySymbol } from "#app/components/client-only";
5
+ import { isFeatureDevtoolsEnabled } from "../core/features.js";
6
+ export function useHydrationCheck() {
7
+ const isClientOnly = inject(clientOnlySymbol, false);
8
+ if (import.meta.server || isClientOnly) {
9
+ return;
10
+ }
11
+ const nuxtApp = useNuxtApp();
12
+ if (!nuxtApp.isHydrating || !nuxtApp.payload.serverRendered) {
13
+ return;
14
+ }
15
+ const instance = getCurrentInstance();
16
+ if (!instance) return;
17
+ const htmlPreHydration = formatHTML(instance.vnode.el?.outerHTML);
18
+ const vnodePrehydration = instance.vnode;
19
+ onMounted(() => {
20
+ const htmlPostHydration = formatHTML(instance.vnode.el?.outerHTML);
21
+ if (htmlPreHydration !== htmlPostHydration) {
22
+ const componentName = instance.type.name ?? instance.type.displayName ?? instance.type.__name;
23
+ const fileLocation = instance.type.__file ?? "unknown";
24
+ const body = {
25
+ htmlPreHydration,
26
+ htmlPostHydration,
27
+ componentName,
28
+ fileLocation
29
+ };
30
+ if (isFeatureDevtoolsEnabled("hydration")) {
31
+ $fetch(new URL(HYDRATION_ROUTE, window.location.origin).href, {
32
+ method: "POST",
33
+ body
34
+ }).then((payload) => {
35
+ nuxtApp.payload.__hints.hydration.push({
36
+ ...payload,
37
+ instance,
38
+ vnode: vnodePrehydration
39
+ });
40
+ });
41
+ }
42
+ logger.warn(`[hydration] Component ${componentName ?? instance.type.__file} seems to have different html pre and post-hydration. Please make sure you don't have any hydration issue.`);
43
+ }
44
+ });
45
+ }
@@ -0,0 +1,2 @@
1
+ import type { NitroApp } from 'nitropack/types';
2
+ export default function (nitroApp: NitroApp): void;