@dxup/nuxt 0.3.1 → 0.3.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 CHANGED
@@ -60,9 +60,22 @@ useFetch("/api/foo");
60
60
  // Also `$fetch` and `useLazyFetch`.
61
61
  ```
62
62
 
63
+ ### 4. pageMeta
64
+
65
+ Go to definition for page metadata.
66
+
67
+ ```ts
68
+ definePageMeta({
69
+ layout: "admin",
70
+ // ^^^^^^^
71
+ middleware: ["auth"],
72
+ // ^^^^^^
73
+ });
74
+ ```
75
+
63
76
  It will fallback to resolve the URL from your `public` directory when no nitro routes match.
64
77
 
65
- ### 4. runtimeConfig
78
+ ### 5. runtimeConfig
66
79
 
67
80
  Go to definition for runtime config.
68
81
 
@@ -73,7 +86,7 @@ Go to definition for runtime config.
73
86
  </template>
74
87
  ```
75
88
 
76
- ### 5. typedPages
89
+ ### 6. typedPages
77
90
 
78
91
  Go to definition for typed pages.
79
92
 
@@ -86,7 +99,7 @@ Go to definition for typed pages.
86
99
 
87
100
  It can be triggered on the `name` property of an object literal constrained by the `RouteLocationRaw` type.
88
101
 
89
- ### 6. unimport
102
+ ### 7. unimport
90
103
 
91
104
  Find references for SFC on `<template>`.
92
105
 
package/dist/module.d.mts CHANGED
@@ -18,6 +18,11 @@ interface ModuleOptions {
18
18
  * @default true
19
19
  */
20
20
  nitroRoutes?: boolean;
21
+ /**
22
+ * Whether to enable Go to Definition for page metadata.
23
+ * @default true
24
+ */
25
+ pageMeta?: boolean;
21
26
  /**
22
27
  * Whether to enable Go to Definition for runtime config.
23
28
  * @default true
@@ -45,6 +50,7 @@ declare const _default: _nuxt_schema0.NuxtModule<ModuleOptions, {
45
50
  components: true;
46
51
  importGlob: true;
47
52
  nitroRoutes: true;
53
+ pageMeta: true;
48
54
  runtimeConfig: true;
49
55
  typedPages: true;
50
56
  unimport: true;
package/dist/module.mjs CHANGED
@@ -73,6 +73,7 @@ var module_default = defineNuxtModule().with({
73
73
  components: true,
74
74
  importGlob: true,
75
75
  nitroRoutes: true,
76
+ pageMeta: true,
76
77
  runtimeConfig: true,
77
78
  typedPages: true,
78
79
  unimport: true
@@ -88,16 +89,28 @@ var module_default = defineNuxtModule().with({
88
89
  filename: "dxup/data.json",
89
90
  write: true,
90
91
  getContents({ nuxt: nuxt$1, app }) {
92
+ const layouts = Object.fromEntries(Object.values(app.layouts).map((item) => [item.name, item.file]));
93
+ const middleware = app.middleware.reduce((acc, item) => {
94
+ if (!item.global) acc[item.name] = item.path;
95
+ return acc;
96
+ }, {});
91
97
  const nitroRoutes = useNitro().scannedHandlers.reduce((acc, item) => {
92
98
  if (item.route && item.method) (acc[item.route] ??= {})[item.method] = item.handler;
93
99
  return acc;
94
100
  }, {});
101
+ const typedPages = app.pages?.reduce(function reducer(acc, page) {
102
+ if (page.name && page.file) acc[page.name] = page.file;
103
+ if (page.children) for (const child of page.children) reducer(acc, child);
104
+ return acc;
105
+ }, {});
95
106
  const data = {
96
107
  buildDir: nuxt$1.options.buildDir,
97
108
  publicDir: nuxt$1.options.dir.public,
98
109
  configFiles: [...nuxt$1.options._nuxtConfigFiles, ...nuxt$1.options._layers.map((layer) => layer._configFile).filter(Boolean)],
110
+ layouts,
111
+ middleware,
99
112
  nitroRoutes,
100
- typedPages: Object.fromEntries(app.pages?.map((page) => [page.name, page.file]) ?? []),
113
+ typedPages,
101
114
  features: {
102
115
  ...options.features,
103
116
  unimport: { componentReferences: typeof options.features.unimport === "object" ? options.features.unimport.componentReferences : options.features.unimport }
@@ -36,12 +36,15 @@ const initialValue = {
36
36
  buildDir: "",
37
37
  publicDir: "",
38
38
  configFiles: [],
39
+ layouts: {},
40
+ middleware: {},
39
41
  nitroRoutes: {},
40
42
  typedPages: {},
41
43
  features: {
42
44
  components: true,
43
45
  importGlob: true,
44
46
  nitroRoutes: true,
47
+ pageMeta: true,
45
48
  runtimeConfig: true,
46
49
  typedPages: true,
47
50
  unimport: { componentReferences: true }
@@ -84,18 +87,6 @@ function createModuleDefinition(ts, path) {
84
87
  function isVueVirtualCode(code) {
85
88
  return code?.languageId === "vue";
86
89
  }
87
- function toSourceSpan(language, fileName, textSpan) {
88
- const sourceScript = language?.scripts.get(fileName);
89
- if (!sourceScript?.generated) return;
90
- const serviceScript = sourceScript.generated.languagePlugin.typescript?.getServiceScript(sourceScript.generated.root);
91
- if (!serviceScript) return;
92
- const map = language.maps.get(serviceScript.code, sourceScript);
93
- const leadingOffset = sourceScript.snapshot.getLength();
94
- for (const [start, end] of map.toSourceRange(textSpan.start - leadingOffset, textSpan.start + textSpan.length - leadingOffset, false)) return {
95
- start,
96
- length: end - start
97
- };
98
- }
99
90
  function withVirtualOffset(language, sourceScript, position, method) {
100
91
  const serviceScript = sourceScript.generated.languagePlugin.typescript?.getServiceScript(sourceScript.generated.root);
101
92
  if (!serviceScript) return;
@@ -198,6 +189,7 @@ const fetchFunctions = new Set([
198
189
  "useFetch",
199
190
  "useLazyFetch"
200
191
  ]);
192
+ const pageMetaKeys = new Set(["layout", "middleware"]);
201
193
  function postprocess(context, language, getDefinitionAndBoundSpan) {
202
194
  const { ts } = context;
203
195
  return (...args) => {
@@ -238,6 +230,7 @@ function preprocess$1(context, getDefinitionAndBoundSpan) {
238
230
  for (const node of forEachTouchingNode(ts, sourceFile, args[1])) {
239
231
  if (data.features.importGlob) result$1 ??= visitImportGlob(ts, info, sourceFile, node, args[1]);
240
232
  if (data.features.nitroRoutes) result$1 ??= visitNitroRoutes(ts, data, checker, sourceFile, node, args[1]);
233
+ if (data.features.pageMeta) result$1 ??= visitPageMeta(ts, data, sourceFile, node, args[1]);
241
234
  if (data.features.typedPages) result$1 ??= visitTypedPages(ts, data, checker, sourceFile, node, args[1]);
242
235
  }
243
236
  if (result$1) return result$1;
@@ -331,12 +324,51 @@ function visitNitroRoutes(ts, data, checker, sourceFile, node, position) {
331
324
  definitions: paths.map((path) => createModuleDefinition(ts, path))
332
325
  };
333
326
  }
327
+ function visitPageMeta(ts, data, sourceFile, node, position) {
328
+ if (!ts.isPropertyAssignment(node) || !ts.isIdentifier(node.name) || !pageMetaKeys.has(node.name.text) || !ts.isCallExpression(node.parent.parent) || !ts.isIdentifier(node.parent.parent.expression) || node.parent.parent.expression.text !== "definePageMeta") return;
329
+ switch (node.name.text) {
330
+ case "layout": {
331
+ if (!ts.isStringLiteralLike(node.initializer)) return;
332
+ const start = node.initializer.getStart(sourceFile);
333
+ const end = node.initializer.getEnd();
334
+ if (position < start || position > end) return;
335
+ const path = data.layouts[node.initializer.text];
336
+ if (path === void 0) return;
337
+ return {
338
+ textSpan: {
339
+ start,
340
+ length: end - start
341
+ },
342
+ definitions: [createModuleDefinition(ts, path)]
343
+ };
344
+ }
345
+ case "middleware": {
346
+ const literals = ts.isStringLiteralLike(node.initializer) ? [node.initializer] : ts.isArrayLiteralExpression(node.initializer) ? node.initializer.elements.filter(ts.isStringLiteralLike) : [];
347
+ for (const literal of literals) {
348
+ const start = literal.getStart(sourceFile);
349
+ const end = literal.getEnd();
350
+ if (position < start || position > end) continue;
351
+ const path = data.middleware[literal.text];
352
+ if (path === void 0) continue;
353
+ return {
354
+ textSpan: {
355
+ start,
356
+ length: end - start
357
+ },
358
+ definitions: [createModuleDefinition(ts, path)]
359
+ };
360
+ }
361
+ break;
362
+ }
363
+ }
364
+ }
334
365
  function visitTypedPages(ts, data, checker, sourceFile, node, position) {
335
366
  if (!ts.isPropertyAssignment(node) || !ts.isIdentifier(node.name) || node.name.text !== "name" || !ts.isStringLiteralLike(node.initializer)) return;
336
367
  const start = node.initializer.getStart(sourceFile);
337
368
  const end = node.initializer.getEnd();
338
369
  if (position < start || position > end) return;
339
- if (checker.getContextualType(node.parent)?.getNonNullableType().aliasSymbol?.name !== "RouteLocationRaw") return;
370
+ const contextualType = checker.getContextualType(node.parent)?.getNonNullableType();
371
+ if (contextualType?.aliasSymbol?.name !== "RouteLocationRaw" && (!contextualType?.isUnion() || contextualType.types.every((type) => type.symbol?.name !== "RouteLocationAsPathTyped"))) return;
340
372
  const path = data.typedPages[node.initializer.text];
341
373
  if (path === void 0) return;
342
374
  return {
@@ -430,7 +462,8 @@ function preprocess(context, getEditsForFileRename) {
430
462
  return (...args) => {
431
463
  const result = getEditsForFileRename(...args);
432
464
  if (!result?.length) return result;
433
- const program = info.languageService.getProgram();
465
+ const languageService = info.project.getLanguageService();
466
+ const program = languageService.getProgram();
434
467
  const references = {};
435
468
  for (const change of result) {
436
469
  const { fileName, textChanges } = change;
@@ -440,10 +473,10 @@ function preprocess(context, getEditsForFileRename) {
440
473
  for (const { span } of textChanges) for (const node of forEachTouchingNode(ts, sourceFile, span.start)) {
441
474
  if (!ts.isPropertySignature(node) && !ts.isVariableDeclaration(node)) continue;
442
475
  const position = node.name.getStart(sourceFile);
443
- const res = info.languageService.getReferencesAtPosition(fileName, position)?.filter((entry) => !entry.fileName.startsWith(data.buildDir));
476
+ const res = languageService.getReferencesAtPosition(fileName, position)?.filter((entry) => !entry.fileName.startsWith(data.buildDir))?.sort((a, b) => a.textSpan.start - b.textSpan.start);
444
477
  const lazy = node.type && ts.isTypeReferenceNode(node.type) && ts.isIdentifier(node.type.typeName) && node.type.typeName.text === "LazyComponent";
445
478
  for (const { fileName: fileName$1, textSpan } of res ?? []) (references[fileName$1] ??= []).push({
446
- textSpan: toSourceSpan(context.language, fileName$1, textSpan) ?? textSpan,
479
+ textSpan,
447
480
  lazy: lazy || void 0
448
481
  });
449
482
  break;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@dxup/nuxt",
3
3
  "type": "module",
4
- "version": "0.3.1",
4
+ "version": "0.3.2",
5
5
  "description": "TypeScript plugin for Nuxt",
6
6
  "author": "KazariEX",
7
7
  "license": "MIT",