@dxup/nuxt 0.0.3 → 0.0.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/README.md +1 -0
- package/dist/module.d.ts +1 -0
- package/dist/module.js +67 -4
- package/dist/{ast-DJW3KREB.cjs → src-BfXMgjZD.cjs} +7 -7
- package/dist/typescript.cjs +97 -11
- package/dist/vue/nitro-routes.cjs +2 -2
- package/package.json +7 -2
package/README.md
CHANGED
|
@@ -8,6 +8,7 @@ This is a collection of TypeScript and Vue plugins that improves Nuxt DX.
|
|
|
8
8
|
|
|
9
9
|
## Features
|
|
10
10
|
|
|
11
|
+
- Update references when renaming auto imported component files
|
|
11
12
|
- Go to definition for nitro routes in data fetching methods within Vue files
|
|
12
13
|
- Go to definition for runtime config
|
|
13
14
|
- [@dxup/unimport](/packages/unimport)
|
package/dist/module.d.ts
CHANGED
package/dist/module.js
CHANGED
|
@@ -1,8 +1,67 @@
|
|
|
1
1
|
import { addTemplate, defineNuxtModule } from "@nuxt/kit";
|
|
2
|
+
import { Buffer } from "node:buffer";
|
|
3
|
+
import EventEmitter from "node:events";
|
|
4
|
+
import { mkdir, open, readFile, writeFile } from "node:fs/promises";
|
|
5
|
+
import { watch } from "chokidar";
|
|
6
|
+
import { dirname, join } from "pathe";
|
|
2
7
|
|
|
3
8
|
//#region package.json
|
|
4
9
|
var name = "@dxup/nuxt";
|
|
5
10
|
|
|
11
|
+
//#endregion
|
|
12
|
+
//#region src/event/client.ts
|
|
13
|
+
const responseRE = /^```json \{(?<key>.*)\}\n(?<value>[\s\S]*?)\n```$/;
|
|
14
|
+
async function createEventClient(nuxt) {
|
|
15
|
+
const path = join(nuxt.options.buildDir, "dxup/events.md");
|
|
16
|
+
await mkdir(dirname(path), { recursive: true });
|
|
17
|
+
await writeFile(path, "");
|
|
18
|
+
const fd = await open(path, "r");
|
|
19
|
+
const watcher = watch(path, { ignoreInitial: true });
|
|
20
|
+
nuxt.hook("close", async () => {
|
|
21
|
+
await fd.close();
|
|
22
|
+
await watcher.close();
|
|
23
|
+
});
|
|
24
|
+
const client = new EventEmitter();
|
|
25
|
+
let offset = 0;
|
|
26
|
+
watcher.on("change", async (path$1, stats) => {
|
|
27
|
+
if (!stats || stats.size <= offset) return;
|
|
28
|
+
const pos = offset;
|
|
29
|
+
offset = stats.size;
|
|
30
|
+
const buffer = Buffer.alloc(offset - pos);
|
|
31
|
+
await fd.read(buffer, 0, buffer.length, pos);
|
|
32
|
+
const match = buffer.toString("utf-8").trim().match(responseRE);
|
|
33
|
+
if (match) {
|
|
34
|
+
const { key, value } = match.groups;
|
|
35
|
+
client.emit(key, JSON.parse(value));
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
return client;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
//#endregion
|
|
42
|
+
//#region src/module/events.ts
|
|
43
|
+
const uppercaseRE = /[A-Z]/;
|
|
44
|
+
async function onComponentsRename(nuxt, { fileName, references }) {
|
|
45
|
+
const component = Object.values(nuxt.apps).flatMap((app) => app.components).find((c) => c.filePath === fileName);
|
|
46
|
+
if (!component) return;
|
|
47
|
+
const tasks = Object.entries(references).map(async ([fileName$1, references$1]) => {
|
|
48
|
+
const code = await readFile(fileName$1, "utf-8");
|
|
49
|
+
const chunks = [];
|
|
50
|
+
let offset = 0;
|
|
51
|
+
for (const { textSpan, lazy } of references$1) {
|
|
52
|
+
const start = textSpan.start;
|
|
53
|
+
const end = start + textSpan.length;
|
|
54
|
+
const oldName = code.slice(start, end);
|
|
55
|
+
const newName = uppercaseRE.test(oldName) ? lazy ? "Lazy" + component.pascalName : component.pascalName : lazy ? "lazy-" + component.kebabName : component.kebabName;
|
|
56
|
+
chunks.push(code.slice(offset, start), newName);
|
|
57
|
+
offset = end;
|
|
58
|
+
}
|
|
59
|
+
chunks.push(code.slice(offset));
|
|
60
|
+
await writeFile(fileName$1, chunks.join(""));
|
|
61
|
+
});
|
|
62
|
+
await Promise.all(tasks);
|
|
63
|
+
}
|
|
64
|
+
|
|
6
65
|
//#endregion
|
|
7
66
|
//#region src/module/index.ts
|
|
8
67
|
var module_default = defineNuxtModule({
|
|
@@ -11,6 +70,7 @@ var module_default = defineNuxtModule({
|
|
|
11
70
|
configKey: "dxup"
|
|
12
71
|
},
|
|
13
72
|
defaults: {
|
|
73
|
+
components: true,
|
|
14
74
|
nitroRoutes: true,
|
|
15
75
|
runtimeConfig: true,
|
|
16
76
|
unimport: true
|
|
@@ -19,24 +79,27 @@ var module_default = defineNuxtModule({
|
|
|
19
79
|
const pluginsTs = [{ name: "@dxup/nuxt" }];
|
|
20
80
|
const pluginsVue = [];
|
|
21
81
|
if (options.nitroRoutes) pluginsVue.push("@dxup/nuxt/vue/nitro-routes");
|
|
22
|
-
if (options.unimport) pluginsTs.
|
|
82
|
+
if (options.unimport) pluginsTs.unshift({ name: "@dxup/unimport" });
|
|
23
83
|
append(pluginsTs, nuxt.options, "typescript", "tsConfig", "compilerOptions");
|
|
24
84
|
append(pluginsTs, nuxt.options.nitro, "typescript", "tsConfig", "compilerOptions");
|
|
25
85
|
append(pluginsTs, nuxt.options, "typescript", "sharedTsConfig", "compilerOptions");
|
|
26
86
|
append(pluginsTs, nuxt.options, "typescript", "nodeTsConfig", "compilerOptions");
|
|
27
87
|
append(pluginsVue, nuxt.options, "typescript", "tsConfig", "vueCompilerOptions");
|
|
28
88
|
addTemplate({
|
|
29
|
-
filename: "dxup.json",
|
|
89
|
+
filename: "dxup/data.json",
|
|
30
90
|
write: true,
|
|
31
91
|
getContents() {
|
|
32
92
|
const data = {
|
|
93
|
+
buildDir: nuxt.options.buildDir,
|
|
94
|
+
configFiles: [...nuxt.options._nuxtConfigFiles, ...nuxt.options._layers.map((layer) => layer._configFile).filter(Boolean)],
|
|
95
|
+
components: options.components,
|
|
33
96
|
nitroRoutes: options.nitroRoutes,
|
|
34
|
-
runtimeConfig: options.runtimeConfig
|
|
35
|
-
configFiles: [...nuxt.options._nuxtConfigFiles, ...nuxt.options._layers.map((layer) => layer._configFile).filter(Boolean)]
|
|
97
|
+
runtimeConfig: options.runtimeConfig
|
|
36
98
|
};
|
|
37
99
|
return JSON.stringify(data, null, 2);
|
|
38
100
|
}
|
|
39
101
|
});
|
|
102
|
+
(await createEventClient(nuxt)).on("components:rename", (data) => onComponentsRename(nuxt, data));
|
|
40
103
|
}
|
|
41
104
|
});
|
|
42
105
|
function append(plugins, target, ...keys) {
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
|
|
2
|
-
//#region src/
|
|
3
|
-
function* forEachNode(node) {
|
|
2
|
+
//#region ../shared/src/index.ts
|
|
3
|
+
function* forEachNode(ts, node) {
|
|
4
4
|
yield node;
|
|
5
5
|
const children = [];
|
|
6
|
-
|
|
6
|
+
ts.forEachChild(node, (child) => {
|
|
7
7
|
children.push(child);
|
|
8
8
|
});
|
|
9
|
-
for (const child of children) yield* forEachNode(child);
|
|
9
|
+
for (const child of children) yield* forEachNode(ts, child);
|
|
10
10
|
}
|
|
11
|
-
function walkNodes(node, callback) {
|
|
11
|
+
function walkNodes(ts, node, callback) {
|
|
12
12
|
callback(node, () => {
|
|
13
|
-
|
|
14
|
-
walkNodes(child, callback);
|
|
13
|
+
ts.forEachChild(node, (child) => {
|
|
14
|
+
walkNodes(ts, child, callback);
|
|
15
15
|
});
|
|
16
16
|
});
|
|
17
17
|
}
|
package/dist/typescript.cjs
CHANGED
|
@@ -21,27 +21,51 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
21
21
|
}) : target, mod));
|
|
22
22
|
|
|
23
23
|
//#endregion
|
|
24
|
-
const
|
|
25
|
-
let
|
|
26
|
-
|
|
24
|
+
const require_src = require('./src-BfXMgjZD.cjs');
|
|
25
|
+
let pathe = require("pathe");
|
|
26
|
+
pathe = __toESM(pathe);
|
|
27
|
+
let node_fs_promises = require("node:fs/promises");
|
|
28
|
+
node_fs_promises = __toESM(node_fs_promises);
|
|
27
29
|
|
|
30
|
+
//#region src/event/server.ts
|
|
31
|
+
function createEventServer(info) {
|
|
32
|
+
const path = (0, pathe.join)(info.project.getCurrentDirectory(), "dxup/events.md");
|
|
33
|
+
function write(key, data) {
|
|
34
|
+
return (0, node_fs_promises.appendFile)(path, `\`\`\`json {${key}}\n${JSON.stringify(data, null, 2)}\n\`\`\`\n`).catch();
|
|
35
|
+
}
|
|
36
|
+
return { write };
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
//#endregion
|
|
28
40
|
//#region src/typescript/index.ts
|
|
29
41
|
const plugin = (module$1) => {
|
|
30
42
|
const { typescript: ts } = module$1;
|
|
31
43
|
return { create(info) {
|
|
32
|
-
const
|
|
44
|
+
const currentDirectory = info.languageServiceHost.getCurrentDirectory();
|
|
45
|
+
const path = (0, pathe.join)(currentDirectory, "dxup/data.json");
|
|
33
46
|
const data = {
|
|
47
|
+
buildDir: currentDirectory,
|
|
48
|
+
configFiles: [],
|
|
49
|
+
components: true,
|
|
34
50
|
nitroRoutes: true,
|
|
35
51
|
runtimeConfig: true,
|
|
36
|
-
configFiles: [],
|
|
37
52
|
...JSON.parse(ts.sys.readFile(path) ?? "{}")
|
|
38
53
|
};
|
|
54
|
+
const server = createEventServer(info);
|
|
39
55
|
const context = {
|
|
40
56
|
ts,
|
|
41
57
|
info,
|
|
42
|
-
data
|
|
58
|
+
data,
|
|
59
|
+
server
|
|
43
60
|
};
|
|
44
|
-
|
|
61
|
+
setTimeout(() => {
|
|
62
|
+
context.language = (info.project.__vue__ ?? info.project["program"]?.__vue__)?.language;
|
|
63
|
+
}, 500);
|
|
64
|
+
for (const [key, method] of [
|
|
65
|
+
["findRenameLocations", findRenameLocations.bind(null, context)],
|
|
66
|
+
["getDefinitionAndBoundSpan", getDefinitionAndBoundSpan.bind(null, context)],
|
|
67
|
+
["getEditsForFileRename", getEditsForFileRename.bind(null, context)]
|
|
68
|
+
]) {
|
|
45
69
|
const original = info.languageService[key];
|
|
46
70
|
info.languageService[key] = method(original);
|
|
47
71
|
}
|
|
@@ -49,10 +73,18 @@ const plugin = (module$1) => {
|
|
|
49
73
|
} };
|
|
50
74
|
};
|
|
51
75
|
var typescript_default = plugin;
|
|
76
|
+
function findRenameLocations(context, findRenameLocations$1) {
|
|
77
|
+
const { data } = context;
|
|
78
|
+
return (...args) => {
|
|
79
|
+
return findRenameLocations$1(...args)?.filter((edit) => {
|
|
80
|
+
return !edit.fileName.startsWith(data.buildDir);
|
|
81
|
+
});
|
|
82
|
+
};
|
|
83
|
+
}
|
|
52
84
|
function getDefinitionAndBoundSpan(context, getDefinitionAndBoundSpan$1) {
|
|
53
85
|
const { info, data } = context;
|
|
54
|
-
return (
|
|
55
|
-
const result = getDefinitionAndBoundSpan$1(
|
|
86
|
+
return (...args) => {
|
|
87
|
+
const result = getDefinitionAndBoundSpan$1(...args);
|
|
56
88
|
if (!result?.definitions?.length) return result;
|
|
57
89
|
const program = info.languageService.getProgram();
|
|
58
90
|
const definitions = new Set(result.definitions);
|
|
@@ -78,7 +110,7 @@ function getDefinitionAndBoundSpan(context, getDefinitionAndBoundSpan$1) {
|
|
|
78
110
|
function visitNitroRoutes(context, sourceFile, definition, getDefinitionAndBoundSpan$1) {
|
|
79
111
|
const { ts } = context;
|
|
80
112
|
const definitions = [];
|
|
81
|
-
for (const node of
|
|
113
|
+
for (const node of require_src.forEachNode(ts, sourceFile)) {
|
|
82
114
|
if (!ts.isPropertySignature(node) || !node.type || !ts.isTypeLiteralNode(node.type)) continue;
|
|
83
115
|
const { textSpan } = definition;
|
|
84
116
|
const start = node.name.getStart(sourceFile);
|
|
@@ -100,7 +132,7 @@ function visitRuntimeConfig(context, sourceFile, definition) {
|
|
|
100
132
|
const { ts } = context;
|
|
101
133
|
let definitions = [];
|
|
102
134
|
const path = [];
|
|
103
|
-
|
|
135
|
+
require_src.walkNodes(ts, sourceFile, (node, next) => {
|
|
104
136
|
let key;
|
|
105
137
|
if (ts.isInterfaceDeclaration(node) && ts.isIdentifier(node.name)) key = node.name.text;
|
|
106
138
|
else if (ts.isPropertySignature(node) && ts.isIdentifier(node.name)) {
|
|
@@ -175,6 +207,60 @@ function* proxyRuntimeConfig(context, definition, path) {
|
|
|
175
207
|
}
|
|
176
208
|
}
|
|
177
209
|
}
|
|
210
|
+
function getEditsForFileRename(context, getEditsForFileRename$1) {
|
|
211
|
+
const { ts, info, data, server } = context;
|
|
212
|
+
return (...args) => {
|
|
213
|
+
const result = getEditsForFileRename$1(...args);
|
|
214
|
+
if (!result?.length) return result;
|
|
215
|
+
const program = info.languageService.getProgram();
|
|
216
|
+
const changes = [];
|
|
217
|
+
const references = {};
|
|
218
|
+
for (const change of result) {
|
|
219
|
+
const { fileName, textChanges } = change;
|
|
220
|
+
if (data.components && fileName.endsWith("components.d.ts")) {
|
|
221
|
+
const sourceFile = program.getSourceFile(fileName);
|
|
222
|
+
if (!sourceFile) continue;
|
|
223
|
+
const nodes = [];
|
|
224
|
+
if (fileName.endsWith("types/components.d.ts")) {
|
|
225
|
+
for (const node of require_src.forEachNode(ts, sourceFile)) if (ts.isPropertySignature(node)) nodes.push(node);
|
|
226
|
+
} else for (const node of require_src.forEachNode(ts, sourceFile)) if (ts.isVariableDeclaration(node)) nodes.push(node);
|
|
227
|
+
for (const node of nodes) {
|
|
228
|
+
const start = node.getStart(sourceFile);
|
|
229
|
+
const end = node.getEnd();
|
|
230
|
+
if (textChanges.every(({ span }) => span.start < start || span.start + span.length > end)) continue;
|
|
231
|
+
const symbols = info.languageService.findReferences(fileName, start);
|
|
232
|
+
const lazy = node.type && ts.isTypeReferenceNode(node.type) && ts.isIdentifier(node.type.typeName) && node.type.typeName.text === "LazyComponent";
|
|
233
|
+
for (const reference of symbols?.flatMap(({ references: references$1 }) => references$1) ?? []) {
|
|
234
|
+
if (reference.isDefinition) continue;
|
|
235
|
+
const { fileName: fileName$1, textSpan } = reference;
|
|
236
|
+
(references[fileName$1] ??= []).push({
|
|
237
|
+
textSpan: toSourceSpan(context.language, fileName$1, textSpan) ?? textSpan,
|
|
238
|
+
lazy: lazy || void 0
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
if (!fileName.startsWith(data.buildDir)) changes.push(change);
|
|
244
|
+
}
|
|
245
|
+
if (Object.keys(references).length) server.write("components:rename", {
|
|
246
|
+
fileName: args[1],
|
|
247
|
+
references
|
|
248
|
+
});
|
|
249
|
+
return changes;
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
function toSourceSpan(language, fileName, textSpan) {
|
|
253
|
+
const sourceScript = language?.scripts.get(fileName);
|
|
254
|
+
if (!sourceScript?.generated) return;
|
|
255
|
+
const serviceScript = sourceScript.generated.languagePlugin.typescript?.getServiceScript(sourceScript.generated.root);
|
|
256
|
+
if (!serviceScript) return;
|
|
257
|
+
const map = language.maps.get(serviceScript.code, sourceScript);
|
|
258
|
+
const leadingOffset = sourceScript.snapshot.getLength();
|
|
259
|
+
for (const [start, end] of map.toSourceRange(textSpan.start - leadingOffset, textSpan.start + textSpan.length - leadingOffset, false)) return {
|
|
260
|
+
start,
|
|
261
|
+
length: end - start
|
|
262
|
+
};
|
|
263
|
+
}
|
|
178
264
|
|
|
179
265
|
//#endregion
|
|
180
266
|
module.exports = typescript_default;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const
|
|
1
|
+
const require_src = require('../src-BfXMgjZD.cjs');
|
|
2
2
|
|
|
3
3
|
//#region src/vue/nitro-routes.ts
|
|
4
4
|
const functionNames = new Set([
|
|
@@ -14,7 +14,7 @@ const plugin = ({ modules: { typescript: ts } }) => {
|
|
|
14
14
|
const { scriptSetup } = sfc;
|
|
15
15
|
if (!scriptSetup) return;
|
|
16
16
|
const codes = [];
|
|
17
|
-
for (const node of
|
|
17
|
+
for (const node of require_src.forEachNode(ts, scriptSetup.ast)) if (ts.isCallExpression(node) && ts.isIdentifier(node.expression) && functionNames.has(node.expression.text) && node.arguments.length && ts.isStringLiteralLike(node.arguments[0])) {
|
|
18
18
|
const arg = node.arguments[0];
|
|
19
19
|
codes.push(`/** @type {__VLS_InternalApi[`, [
|
|
20
20
|
arg.getText(scriptSetup.ast),
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dxup/nuxt",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.0.
|
|
4
|
+
"version": "0.0.4",
|
|
5
5
|
"description": "TypeScript and Vue plugins for Nuxt",
|
|
6
6
|
"author": "KazariEX",
|
|
7
7
|
"license": "MIT",
|
|
@@ -18,9 +18,14 @@
|
|
|
18
18
|
],
|
|
19
19
|
"dependencies": {
|
|
20
20
|
"@nuxt/kit": "^4.1.2",
|
|
21
|
+
"chokidar": "^4.0.3",
|
|
22
|
+
"pathe": "2.0.3",
|
|
21
23
|
"@dxup/unimport": "^0.0.1"
|
|
22
24
|
},
|
|
23
25
|
"devDependencies": {
|
|
26
|
+
"@dxup/shared": "",
|
|
27
|
+
"@volar/language-core": "^2.4.23",
|
|
28
|
+
"@volar/typescript": "^2.4.23",
|
|
24
29
|
"@vue/language-core": "^3.0.8",
|
|
25
30
|
"nuxt": "^4.1.2",
|
|
26
31
|
"typescript": "^5.9.2"
|
|
@@ -28,6 +33,6 @@
|
|
|
28
33
|
"scripts": {
|
|
29
34
|
"build": "tsdown",
|
|
30
35
|
"dev": "tsdown -w --sourcemap",
|
|
31
|
-
"release": "
|
|
36
|
+
"release": "node ../../scripts/release.ts"
|
|
32
37
|
}
|
|
33
38
|
}
|