@dxup/nuxt 0.3.0 → 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 +28 -2
- package/dist/module.d.mts +12 -0
- package/dist/module.mjs +16 -1
- package/dist/typescript.cjs +92 -47
- package/package.json +1 -1
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
|
-
###
|
|
78
|
+
### 5. runtimeConfig
|
|
66
79
|
|
|
67
80
|
Go to definition for runtime config.
|
|
68
81
|
|
|
@@ -73,7 +86,20 @@ Go to definition for runtime config.
|
|
|
73
86
|
</template>
|
|
74
87
|
```
|
|
75
88
|
|
|
76
|
-
###
|
|
89
|
+
### 6. typedPages
|
|
90
|
+
|
|
91
|
+
Go to definition for typed pages.
|
|
92
|
+
|
|
93
|
+
```vue
|
|
94
|
+
<template>
|
|
95
|
+
<nuxt-link :to="{ name: `about` }"/>
|
|
96
|
+
<!-- ^^^^^^^ -->
|
|
97
|
+
</template>
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
It can be triggered on the `name` property of an object literal constrained by the `RouteLocationRaw` type.
|
|
101
|
+
|
|
102
|
+
### 7. unimport
|
|
77
103
|
|
|
78
104
|
Find references for SFC on `<template>`.
|
|
79
105
|
|
package/dist/module.d.mts
CHANGED
|
@@ -18,11 +18,21 @@ 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
|
|
24
29
|
*/
|
|
25
30
|
runtimeConfig?: boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Whether to enable Go to Definition for typed pages.
|
|
33
|
+
* @default true
|
|
34
|
+
*/
|
|
35
|
+
typedPages?: boolean;
|
|
26
36
|
/**
|
|
27
37
|
* Whether to enable enhanced navigation for auto imported APIs.
|
|
28
38
|
* @default true
|
|
@@ -40,7 +50,9 @@ declare const _default: _nuxt_schema0.NuxtModule<ModuleOptions, {
|
|
|
40
50
|
components: true;
|
|
41
51
|
importGlob: true;
|
|
42
52
|
nitroRoutes: true;
|
|
53
|
+
pageMeta: true;
|
|
43
54
|
runtimeConfig: true;
|
|
55
|
+
typedPages: true;
|
|
44
56
|
unimport: true;
|
|
45
57
|
};
|
|
46
58
|
}, true>;
|
package/dist/module.mjs
CHANGED
|
@@ -73,7 +73,9 @@ var module_default = defineNuxtModule().with({
|
|
|
73
73
|
components: true,
|
|
74
74
|
importGlob: true,
|
|
75
75
|
nitroRoutes: true,
|
|
76
|
+
pageMeta: true,
|
|
76
77
|
runtimeConfig: true,
|
|
78
|
+
typedPages: true,
|
|
77
79
|
unimport: true
|
|
78
80
|
} },
|
|
79
81
|
async setup(options, nuxt) {
|
|
@@ -86,16 +88,29 @@ var module_default = defineNuxtModule().with({
|
|
|
86
88
|
addTemplate({
|
|
87
89
|
filename: "dxup/data.json",
|
|
88
90
|
write: true,
|
|
89
|
-
getContents({ nuxt: nuxt$1 }) {
|
|
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
|
+
}, {});
|
|
90
97
|
const nitroRoutes = useNitro().scannedHandlers.reduce((acc, item) => {
|
|
91
98
|
if (item.route && item.method) (acc[item.route] ??= {})[item.method] = item.handler;
|
|
92
99
|
return acc;
|
|
93
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
|
+
}, {});
|
|
94
106
|
const data = {
|
|
95
107
|
buildDir: nuxt$1.options.buildDir,
|
|
96
108
|
publicDir: nuxt$1.options.dir.public,
|
|
97
109
|
configFiles: [...nuxt$1.options._nuxtConfigFiles, ...nuxt$1.options._layers.map((layer) => layer._configFile).filter(Boolean)],
|
|
110
|
+
layouts,
|
|
111
|
+
middleware,
|
|
98
112
|
nitroRoutes,
|
|
113
|
+
typedPages,
|
|
99
114
|
features: {
|
|
100
115
|
...options.features,
|
|
101
116
|
unimport: { componentReferences: typeof options.features.unimport === "object" ? options.features.unimport.componentReferences : options.features.unimport }
|
package/dist/typescript.cjs
CHANGED
|
@@ -36,12 +36,17 @@ const initialValue = {
|
|
|
36
36
|
buildDir: "",
|
|
37
37
|
publicDir: "",
|
|
38
38
|
configFiles: [],
|
|
39
|
+
layouts: {},
|
|
40
|
+
middleware: {},
|
|
39
41
|
nitroRoutes: {},
|
|
42
|
+
typedPages: {},
|
|
40
43
|
features: {
|
|
41
44
|
components: true,
|
|
42
45
|
importGlob: true,
|
|
43
46
|
nitroRoutes: true,
|
|
47
|
+
pageMeta: true,
|
|
44
48
|
runtimeConfig: true,
|
|
49
|
+
typedPages: true,
|
|
45
50
|
unimport: { componentReferences: true }
|
|
46
51
|
}
|
|
47
52
|
};
|
|
@@ -66,21 +71,22 @@ function createData(ts, info) {
|
|
|
66
71
|
|
|
67
72
|
//#endregion
|
|
68
73
|
//#region src/typescript/utils.ts
|
|
74
|
+
function createModuleDefinition(ts, path) {
|
|
75
|
+
return {
|
|
76
|
+
fileName: path,
|
|
77
|
+
textSpan: {
|
|
78
|
+
start: 0,
|
|
79
|
+
length: 0
|
|
80
|
+
},
|
|
81
|
+
kind: ts.ScriptElementKind.moduleElement,
|
|
82
|
+
name: `"${path}"`,
|
|
83
|
+
containerKind: ts.ScriptElementKind.unknown,
|
|
84
|
+
containerName: ""
|
|
85
|
+
};
|
|
86
|
+
}
|
|
69
87
|
function isVueVirtualCode(code) {
|
|
70
88
|
return code?.languageId === "vue";
|
|
71
89
|
}
|
|
72
|
-
function toSourceSpan(language, fileName, textSpan) {
|
|
73
|
-
const sourceScript = language?.scripts.get(fileName);
|
|
74
|
-
if (!sourceScript?.generated) return;
|
|
75
|
-
const serviceScript = sourceScript.generated.languagePlugin.typescript?.getServiceScript(sourceScript.generated.root);
|
|
76
|
-
if (!serviceScript) return;
|
|
77
|
-
const map = language.maps.get(serviceScript.code, sourceScript);
|
|
78
|
-
const leadingOffset = sourceScript.snapshot.getLength();
|
|
79
|
-
for (const [start, end] of map.toSourceRange(textSpan.start - leadingOffset, textSpan.start + textSpan.length - leadingOffset, false)) return {
|
|
80
|
-
start,
|
|
81
|
-
length: end - start
|
|
82
|
-
};
|
|
83
|
-
}
|
|
84
90
|
function withVirtualOffset(language, sourceScript, position, method) {
|
|
85
91
|
const serviceScript = sourceScript.generated.languagePlugin.typescript?.getServiceScript(sourceScript.generated.root);
|
|
86
92
|
if (!serviceScript) return;
|
|
@@ -183,6 +189,7 @@ const fetchFunctions = new Set([
|
|
|
183
189
|
"useFetch",
|
|
184
190
|
"useLazyFetch"
|
|
185
191
|
]);
|
|
192
|
+
const pageMetaKeys = new Set(["layout", "middleware"]);
|
|
186
193
|
function postprocess(context, language, getDefinitionAndBoundSpan) {
|
|
187
194
|
const { ts } = context;
|
|
188
195
|
return (...args) => {
|
|
@@ -199,10 +206,10 @@ function postprocess(context, language, getDefinitionAndBoundSpan) {
|
|
|
199
206
|
definitions: [{
|
|
200
207
|
fileName: args[0],
|
|
201
208
|
textSpan,
|
|
202
|
-
kind: ts.ScriptElementKind.
|
|
203
|
-
name:
|
|
209
|
+
kind: ts.ScriptElementKind.memberVariableElement,
|
|
210
|
+
name: "default",
|
|
204
211
|
containerKind: ts.ScriptElementKind.unknown,
|
|
205
|
-
containerName:
|
|
212
|
+
containerName: args[0]
|
|
206
213
|
}]
|
|
207
214
|
};
|
|
208
215
|
return result;
|
|
@@ -219,12 +226,14 @@ function preprocess$1(context, getDefinitionAndBoundSpan) {
|
|
|
219
226
|
const sourceFile = program$1.getSourceFile(args[0]);
|
|
220
227
|
if (!sourceFile) return;
|
|
221
228
|
const checker = program$1.getTypeChecker();
|
|
222
|
-
let
|
|
229
|
+
let result$1;
|
|
223
230
|
for (const node of forEachTouchingNode(ts, sourceFile, args[1])) {
|
|
224
|
-
if (data.features.importGlob)
|
|
225
|
-
if (data.features.nitroRoutes)
|
|
231
|
+
if (data.features.importGlob) result$1 ??= visitImportGlob(ts, info, sourceFile, node, args[1]);
|
|
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]);
|
|
234
|
+
if (data.features.typedPages) result$1 ??= visitTypedPages(ts, data, checker, sourceFile, node, args[1]);
|
|
226
235
|
}
|
|
227
|
-
if (
|
|
236
|
+
if (result$1) return result$1;
|
|
228
237
|
}
|
|
229
238
|
if (!result?.definitions?.length) return result;
|
|
230
239
|
const program = info.languageService.getProgram();
|
|
@@ -232,7 +241,7 @@ function preprocess$1(context, getDefinitionAndBoundSpan) {
|
|
|
232
241
|
for (const definition of result.definitions) {
|
|
233
242
|
const sourceFile = program.getSourceFile(definition.fileName);
|
|
234
243
|
if (!sourceFile) continue;
|
|
235
|
-
let result$1
|
|
244
|
+
let result$1;
|
|
236
245
|
if (data.features.runtimeConfig && definition.fileName.endsWith("runtime-config.d.ts")) result$1 = visitRuntimeConfig(context, sourceFile, definition);
|
|
237
246
|
if (result$1?.length) {
|
|
238
247
|
for (const definition$1 of result$1) definitions.add(definition$1);
|
|
@@ -271,17 +280,7 @@ function visitImportGlob(ts, info, sourceFile, node, position) {
|
|
|
271
280
|
start,
|
|
272
281
|
length: end - start
|
|
273
282
|
},
|
|
274
|
-
definitions: fileNames.map((fileName) => (
|
|
275
|
-
fileName,
|
|
276
|
-
textSpan: {
|
|
277
|
-
start: 0,
|
|
278
|
-
length: 0
|
|
279
|
-
},
|
|
280
|
-
kind: ts.ScriptElementKind.unknown,
|
|
281
|
-
name: fileName,
|
|
282
|
-
containerKind: ts.ScriptElementKind.unknown,
|
|
283
|
-
containerName: ""
|
|
284
|
-
}))
|
|
283
|
+
definitions: fileNames.map((fileName) => createModuleDefinition(ts, fileName))
|
|
285
284
|
};
|
|
286
285
|
}
|
|
287
286
|
function visitNitroRoutes(ts, data, checker, sourceFile, node, position) {
|
|
@@ -322,17 +321,62 @@ function visitNitroRoutes(ts, data, checker, sourceFile, node, position) {
|
|
|
322
321
|
start,
|
|
323
322
|
length: end - start
|
|
324
323
|
},
|
|
325
|
-
definitions: paths.map((path) => (
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
324
|
+
definitions: paths.map((path) => createModuleDefinition(ts, path))
|
|
325
|
+
};
|
|
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
|
+
}
|
|
365
|
+
function visitTypedPages(ts, data, checker, sourceFile, node, position) {
|
|
366
|
+
if (!ts.isPropertyAssignment(node) || !ts.isIdentifier(node.name) || node.name.text !== "name" || !ts.isStringLiteralLike(node.initializer)) return;
|
|
367
|
+
const start = node.initializer.getStart(sourceFile);
|
|
368
|
+
const end = node.initializer.getEnd();
|
|
369
|
+
if (position < start || position > end) 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;
|
|
372
|
+
const path = data.typedPages[node.initializer.text];
|
|
373
|
+
if (path === void 0) return;
|
|
374
|
+
return {
|
|
375
|
+
textSpan: {
|
|
376
|
+
start,
|
|
377
|
+
length: end - start
|
|
378
|
+
},
|
|
379
|
+
definitions: [createModuleDefinition(ts, path)]
|
|
336
380
|
};
|
|
337
381
|
}
|
|
338
382
|
function visitRuntimeConfig(context, sourceFile, definition) {
|
|
@@ -418,7 +462,8 @@ function preprocess(context, getEditsForFileRename) {
|
|
|
418
462
|
return (...args) => {
|
|
419
463
|
const result = getEditsForFileRename(...args);
|
|
420
464
|
if (!result?.length) return result;
|
|
421
|
-
const
|
|
465
|
+
const languageService = info.project.getLanguageService();
|
|
466
|
+
const program = languageService.getProgram();
|
|
422
467
|
const references = {};
|
|
423
468
|
for (const change of result) {
|
|
424
469
|
const { fileName, textChanges } = change;
|
|
@@ -428,10 +473,10 @@ function preprocess(context, getEditsForFileRename) {
|
|
|
428
473
|
for (const { span } of textChanges) for (const node of forEachTouchingNode(ts, sourceFile, span.start)) {
|
|
429
474
|
if (!ts.isPropertySignature(node) && !ts.isVariableDeclaration(node)) continue;
|
|
430
475
|
const position = node.name.getStart(sourceFile);
|
|
431
|
-
const res =
|
|
476
|
+
const res = languageService.getReferencesAtPosition(fileName, position)?.filter((entry) => !entry.fileName.startsWith(data.buildDir))?.sort((a, b) => a.textSpan.start - b.textSpan.start);
|
|
432
477
|
const lazy = node.type && ts.isTypeReferenceNode(node.type) && ts.isIdentifier(node.type.typeName) && node.type.typeName.text === "LazyComponent";
|
|
433
478
|
for (const { fileName: fileName$1, textSpan } of res ?? []) (references[fileName$1] ??= []).push({
|
|
434
|
-
textSpan
|
|
479
|
+
textSpan,
|
|
435
480
|
lazy: lazy || void 0
|
|
436
481
|
});
|
|
437
482
|
break;
|
|
@@ -460,7 +505,7 @@ const plugin = (module$1) => {
|
|
|
460
505
|
data,
|
|
461
506
|
server: createEventServer(info)
|
|
462
507
|
};
|
|
463
|
-
|
|
508
|
+
queueMicrotask(() => {
|
|
464
509
|
context.language = info.project.__vue__?.language;
|
|
465
510
|
if (!context.language || !data.features.unimport.componentReferences) return;
|
|
466
511
|
const languageService = info.project.getLanguageService();
|
|
@@ -477,7 +522,7 @@ const plugin = (module$1) => {
|
|
|
477
522
|
return Reflect.set(...args);
|
|
478
523
|
}
|
|
479
524
|
});
|
|
480
|
-
}
|
|
525
|
+
});
|
|
481
526
|
for (const [key, method] of [
|
|
482
527
|
["findRenameLocations", findRenameLocations_exports],
|
|
483
528
|
["getDefinitionAndBoundSpan", getDefinitionAndBoundSpan_exports],
|