@dev-to/vue-plugin 0.2.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 +24 -0
- package/dist/constants.d.ts +15 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/debugTools.d.ts +12 -0
- package/dist/debugTools.d.ts.map +1 -0
- package/dist/devComponentMap.d.ts +4 -0
- package/dist/devComponentMap.d.ts.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +770 -0
- package/dist/lan.d.ts +2 -0
- package/dist/lan.d.ts.map +1 -0
- package/dist/pathUtils.d.ts +4 -0
- package/dist/pathUtils.d.ts.map +1 -0
- package/dist/plugin.d.ts +3 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/transformUtils.d.ts +9 -0
- package/dist/transformUtils.d.ts.map +1 -0
- package/dist/types.d.ts +49 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/virtualModules.d.ts +5 -0
- package/dist/virtualModules.d.ts.map +1 -0
- package/package.json +39 -0
package/README.md
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# @dev-to/vue-plugin
|
|
2
|
+
|
|
3
|
+
Vite plugin that exposes DevTo bridge endpoints for Vue component development.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
```ts
|
|
8
|
+
import { defineConfig } from 'vite'
|
|
9
|
+
import vue from '@vitejs/plugin-vue'
|
|
10
|
+
import { devToVuePlugin } from '@dev-to/vue-plugin'
|
|
11
|
+
|
|
12
|
+
export default defineConfig({
|
|
13
|
+
server: {
|
|
14
|
+
port: 5173,
|
|
15
|
+
cors: true,
|
|
16
|
+
},
|
|
17
|
+
plugins: [
|
|
18
|
+
vue(),
|
|
19
|
+
devToVuePlugin({
|
|
20
|
+
MyCard: 'src/components/MyCard.vue',
|
|
21
|
+
}),
|
|
22
|
+
],
|
|
23
|
+
})
|
|
24
|
+
```
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export declare const PLUGIN_NAME: "dev_to_vue";
|
|
2
|
+
export declare const PLUGIN_LOG_PREFIX: "[dev_to:vue]";
|
|
3
|
+
export declare const STABLE_BASE_PATH: "/__dev_to__";
|
|
4
|
+
export declare const STABLE_DISCOVERY_PATH: "/__dev_to__/discovery.json";
|
|
5
|
+
export declare const STABLE_DEBUG_HTML_PATH: "/__dev_to__/debug.html";
|
|
6
|
+
export declare const STABLE_DEBUG_JSON_PATH: "/__dev_to__/debug.json";
|
|
7
|
+
export declare const STABLE_VUE_BASE_PATH: "/__dev_to__/vue";
|
|
8
|
+
export declare const STABLE_CONTRACT_PATH: "/__dev_to__/vue/contract.js";
|
|
9
|
+
export declare const STABLE_INIT_PATH: "/__dev_to__/vue/init.js";
|
|
10
|
+
export declare const STABLE_VUE_RUNTIME_PATH: "/__dev_to__/vue/runtime.js";
|
|
11
|
+
export declare const STABLE_LOADER_UMD_PATH: "/__dev_to__/vue/loader.js";
|
|
12
|
+
export declare const STABLE_LOADER_BASE_PATH: "/__dev_to__/vue/loader";
|
|
13
|
+
export declare const EVENT_FULL_RELOAD: "dev_to:vue:full-reload";
|
|
14
|
+
export declare const EVENT_HMR_UPDATE: "dev_to:vue:hmr-update";
|
|
15
|
+
//# sourceMappingURL=constants.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAiBA,eAAO,MAAM,WAAW,cAAyD,CAAA;AACjF,eAAO,MAAM,iBAAiB,gBAA2D,CAAA;AAGzF,eAAO,MAAM,gBAAgB,eAAmB,CAAA;AAChD,eAAO,MAAM,qBAAqB,8BAAwB,CAAA;AAC1D,eAAO,MAAM,sBAAsB,0BAAyB,CAAA;AAC5D,eAAO,MAAM,sBAAsB,0BAAyB,CAAA;AAG5D,eAAO,MAAM,oBAAoB,mBAAuB,CAAA;AACxD,eAAO,MAAM,oBAAoB,+BAA2B,CAAA;AAC5D,eAAO,MAAM,gBAAgB,2BAAuB,CAAA;AACpD,eAAO,MAAM,uBAAuB,8BAA0B,CAAA;AAC9D,eAAO,MAAM,sBAAsB,6BAA6B,CAAA;AAChE,eAAO,MAAM,uBAAuB,0BAA8B,CAAA;AAElE,eAAO,MAAM,iBAAiB,0BAA+B,CAAA;AAC7D,eAAO,MAAM,gBAAgB,yBAA8B,CAAA"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ViteDevServer } from 'vite';
|
|
2
|
+
import type { BridgeContract, BridgeStats, DebugStartupState, DevComponentAudit, ResolvedDevComponentConfig } from './types.js';
|
|
3
|
+
export interface DebugToolsContext {
|
|
4
|
+
contract: BridgeContract;
|
|
5
|
+
stats: BridgeStats;
|
|
6
|
+
audit: DevComponentAudit;
|
|
7
|
+
resolvedConfig: ResolvedDevComponentConfig;
|
|
8
|
+
configDir: string;
|
|
9
|
+
open?: boolean;
|
|
10
|
+
}
|
|
11
|
+
export declare function installDebugTools(server: ViteDevServer, ctx: DebugToolsContext, state: DebugStartupState): void;
|
|
12
|
+
//# sourceMappingURL=debugTools.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"debugTools.d.ts","sourceRoot":"","sources":["../src/debugTools.ts"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,MAAM,CAAA;AAEzC,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,0BAA0B,EAAE,MAAM,YAAY,CAAA;AAE/H,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,cAAc,CAAA;IACxB,KAAK,EAAE,WAAW,CAAA;IAClB,KAAK,EAAE,iBAAiB,CAAA;IACxB,cAAc,EAAE,0BAA0B,CAAA;IAC1C,SAAS,EAAE,MAAM,CAAA;IACjB,IAAI,CAAC,EAAE,OAAO,CAAA;CACf;AA4ED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,aAAa,EAAE,GAAG,EAAE,iBAAiB,EAAE,KAAK,EAAE,iBAAiB,QAwNxG"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { DevComponentMapInput, ResolvedDevComponentConfig } from './types.js';
|
|
2
|
+
export declare function toViteFsPath(filePath: string): string;
|
|
3
|
+
export declare function resolveDevComponentConfig(rootDir: string, devComponentMap: DevComponentMapInput, fallbackRoot?: string): ResolvedDevComponentConfig;
|
|
4
|
+
//# sourceMappingURL=devComponentMap.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"devComponentMap.d.ts","sourceRoot":"","sources":["../src/devComponentMap.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,oBAAoB,EAAE,0BAA0B,EAAE,MAAM,YAAY,CAAA;AAElF,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,UAG5C;AAoED,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,MAAM,EACf,eAAe,EAAE,oBAAoB,EACrC,YAAY,CAAC,EAAE,MAAM,GACpB,0BAA0B,CA8D5B"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAE5C,YAAY,EACV,oBAAoB,EACpB,qBAAqB,GACtB,MAAM,YAAY,CAAA"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,770 @@
|
|
|
1
|
+
import node_path from "node:path";
|
|
2
|
+
import { mergeConfig } from "vite";
|
|
3
|
+
import { DEV_TO_BASE_PATH, DEV_TO_DEBUG_HTML_PATH, DEV_TO_DEBUG_JSON_PATH, DEV_TO_DISCOVERY_PATH, DEV_TO_NAMESPACE, DEV_TO_VUE_CONTRACT_KEY, DEV_TO_VUE_CONTRACT_PATH, DEV_TO_VUE_DEBUG_STATE_KEY, DEV_TO_VUE_DID_OPEN_BROWSER_KEY, DEV_TO_VUE_EVENT_FULL_RELOAD, DEV_TO_VUE_EVENT_HMR_UPDATE, DEV_TO_VUE_INIT_PATH, DEV_TO_VUE_LOADER_BASE_PATH, DEV_TO_VUE_LOADER_UMD_PATH, DEV_TO_VUE_NAMESPACE, DEV_TO_VUE_ORIGIN_KEY, DEV_TO_VUE_RESOLVE_ASSET_KEY, DEV_TO_VUE_RUNTIME_PATH } from "@dev-to/shared";
|
|
4
|
+
import { exec } from "node:child_process";
|
|
5
|
+
import node_fs from "node:fs";
|
|
6
|
+
import { createRequire } from "node:module";
|
|
7
|
+
import node_os from "node:os";
|
|
8
|
+
const PLUGIN_NAME = `${DEV_TO_NAMESPACE}_${DEV_TO_VUE_NAMESPACE}`;
|
|
9
|
+
const constants_PLUGIN_LOG_PREFIX = `[${DEV_TO_NAMESPACE}:${DEV_TO_VUE_NAMESPACE}]`;
|
|
10
|
+
const STABLE_BASE_PATH = DEV_TO_BASE_PATH;
|
|
11
|
+
const STABLE_DISCOVERY_PATH = DEV_TO_DISCOVERY_PATH;
|
|
12
|
+
const STABLE_DEBUG_HTML_PATH = DEV_TO_DEBUG_HTML_PATH;
|
|
13
|
+
const STABLE_DEBUG_JSON_PATH = DEV_TO_DEBUG_JSON_PATH;
|
|
14
|
+
const STABLE_CONTRACT_PATH = DEV_TO_VUE_CONTRACT_PATH;
|
|
15
|
+
const STABLE_INIT_PATH = DEV_TO_VUE_INIT_PATH;
|
|
16
|
+
const STABLE_VUE_RUNTIME_PATH = DEV_TO_VUE_RUNTIME_PATH;
|
|
17
|
+
const STABLE_LOADER_UMD_PATH = DEV_TO_VUE_LOADER_UMD_PATH;
|
|
18
|
+
const STABLE_LOADER_BASE_PATH = DEV_TO_VUE_LOADER_BASE_PATH;
|
|
19
|
+
const EVENT_FULL_RELOAD = DEV_TO_VUE_EVENT_FULL_RELOAD;
|
|
20
|
+
const EVENT_HMR_UPDATE = DEV_TO_VUE_EVENT_HMR_UPDATE;
|
|
21
|
+
function getLanIPv4Hosts() {
|
|
22
|
+
const nets = node_os.networkInterfaces();
|
|
23
|
+
const out = new Set();
|
|
24
|
+
for (const items of Object.values(nets))if (items) {
|
|
25
|
+
for (const info of items)if ('IPv4' === info.family && !info.internal) out.add(info.address);
|
|
26
|
+
}
|
|
27
|
+
return Array.from(out);
|
|
28
|
+
}
|
|
29
|
+
function openBrowser(url) {
|
|
30
|
+
const bridgePath = STABLE_DEBUG_HTML_PATH;
|
|
31
|
+
if ('darwin' === process.platform) {
|
|
32
|
+
const script = `
|
|
33
|
+
try
|
|
34
|
+
tell application "Google Chrome"
|
|
35
|
+
repeat with w in windows
|
|
36
|
+
repeat with t in tabs of w
|
|
37
|
+
if URL of t contains "${bridgePath}" then
|
|
38
|
+
set URL of t to "${url}"
|
|
39
|
+
set active tab index of w to (get index of t)
|
|
40
|
+
set index of w to 1
|
|
41
|
+
activate
|
|
42
|
+
return "found"
|
|
43
|
+
end if
|
|
44
|
+
end repeat
|
|
45
|
+
end repeat
|
|
46
|
+
end tell
|
|
47
|
+
end try
|
|
48
|
+
|
|
49
|
+
try
|
|
50
|
+
tell application "Microsoft Edge"
|
|
51
|
+
repeat with w in windows
|
|
52
|
+
repeat with t in tabs of w
|
|
53
|
+
if URL of t contains "${bridgePath}" then
|
|
54
|
+
set URL of t to "${url}"
|
|
55
|
+
set active tab index of w to (get index of t)
|
|
56
|
+
set index of w to 1
|
|
57
|
+
activate
|
|
58
|
+
return "found"
|
|
59
|
+
end if
|
|
60
|
+
end repeat
|
|
61
|
+
end repeat
|
|
62
|
+
end tell
|
|
63
|
+
end try
|
|
64
|
+
|
|
65
|
+
try
|
|
66
|
+
tell application "Safari"
|
|
67
|
+
repeat with w in windows
|
|
68
|
+
repeat with t in tabs of w
|
|
69
|
+
if URL of t contains "${bridgePath}" then
|
|
70
|
+
set URL of t to "${url}"
|
|
71
|
+
set current tab of w to t
|
|
72
|
+
set index of w to 1
|
|
73
|
+
activate
|
|
74
|
+
return "found"
|
|
75
|
+
end if
|
|
76
|
+
end repeat
|
|
77
|
+
end repeat
|
|
78
|
+
end tell
|
|
79
|
+
end try
|
|
80
|
+
|
|
81
|
+
return "not_found"
|
|
82
|
+
`.replace(/\n/g, ' ');
|
|
83
|
+
exec(`osascript -e '${script}'`, (err, stdout)=>{
|
|
84
|
+
if (err || 'found' !== stdout.trim()) exec(`open "${url}"`);
|
|
85
|
+
});
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
if ('win32' === process.platform) return void exec(`start "" "${url}"`);
|
|
89
|
+
exec(`xdg-open "${url}"`);
|
|
90
|
+
}
|
|
91
|
+
const globalState = globalThis;
|
|
92
|
+
let didOpenBrowser = Boolean(globalState[DEV_TO_VUE_DID_OPEN_BROWSER_KEY]);
|
|
93
|
+
function installDebugTools(server, ctx, state) {
|
|
94
|
+
const printStartupDebugUrl = ()=>{
|
|
95
|
+
if (state.didPrintStartupDebugUrl) return;
|
|
96
|
+
state.didPrintStartupDebugUrl = true;
|
|
97
|
+
const isHttps = !!server.config.server.https;
|
|
98
|
+
const proto = isHttps ? 'https' : 'http';
|
|
99
|
+
const addr = server.httpServer?.address();
|
|
100
|
+
const actualPort = addr && 'object' == typeof addr ? addr.port : void 0;
|
|
101
|
+
const port = (()=>{
|
|
102
|
+
if ('number' == typeof actualPort) return actualPort;
|
|
103
|
+
if ('number' == typeof server.config.server.port) return server.config.server.port;
|
|
104
|
+
return 5173;
|
|
105
|
+
})();
|
|
106
|
+
const logger = server.config.logger;
|
|
107
|
+
const info = 'function' == typeof logger?.info ? logger.info.bind(logger) : console.log;
|
|
108
|
+
setImmediate(()=>{
|
|
109
|
+
info('');
|
|
110
|
+
info(` DevTo: ${proto}://localhost:${port}${DEV_TO_BASE_PATH}`);
|
|
111
|
+
});
|
|
112
|
+
if (ctx.open && !didOpenBrowser) {
|
|
113
|
+
didOpenBrowser = true;
|
|
114
|
+
globalState[DEV_TO_VUE_DID_OPEN_BROWSER_KEY] = true;
|
|
115
|
+
const debugUrl = `${proto}://localhost:${port}${STABLE_DEBUG_HTML_PATH}`;
|
|
116
|
+
openBrowser(debugUrl);
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
try {
|
|
120
|
+
if (server.httpServer) {
|
|
121
|
+
server.httpServer.once('listening', printStartupDebugUrl);
|
|
122
|
+
if (server.httpServer.listening) printStartupDebugUrl();
|
|
123
|
+
}
|
|
124
|
+
} catch {}
|
|
125
|
+
server.middlewares.use((req, res, next)=>{
|
|
126
|
+
const url = req.url || '';
|
|
127
|
+
const pathname = String(url).split('?')[0];
|
|
128
|
+
const now = Date.now();
|
|
129
|
+
if (pathname === STABLE_CONTRACT_PATH) {
|
|
130
|
+
ctx.stats.contract.count += 1;
|
|
131
|
+
ctx.stats.contract.lastAt = now;
|
|
132
|
+
} else if (pathname === STABLE_INIT_PATH) {
|
|
133
|
+
ctx.stats.init.count += 1;
|
|
134
|
+
ctx.stats.init.lastAt = now;
|
|
135
|
+
} else if (pathname === STABLE_VUE_RUNTIME_PATH) {
|
|
136
|
+
ctx.stats.runtime.count += 1;
|
|
137
|
+
ctx.stats.runtime.lastAt = now;
|
|
138
|
+
}
|
|
139
|
+
if (url === STABLE_BASE_PATH || url === `${STABLE_BASE_PATH}/`) {
|
|
140
|
+
res.statusCode = 302;
|
|
141
|
+
res.setHeader('Location', STABLE_DEBUG_HTML_PATH);
|
|
142
|
+
res.end();
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
if (url.startsWith(STABLE_DISCOVERY_PATH)) {
|
|
146
|
+
const isHttps = !!server.config.server.https;
|
|
147
|
+
const proto = isHttps ? 'https' : 'http';
|
|
148
|
+
const addr = server.httpServer?.address();
|
|
149
|
+
const actualPort = addr && 'object' == typeof addr ? addr.port : void 0;
|
|
150
|
+
const lanHosts = getLanIPv4Hosts();
|
|
151
|
+
const candidateHosts = [
|
|
152
|
+
'localhost',
|
|
153
|
+
'127.0.0.1',
|
|
154
|
+
...lanHosts
|
|
155
|
+
];
|
|
156
|
+
const originCandidates = candidateHosts.map((h)=>`${proto}://${h}${actualPort ? `:${actualPort}` : ''}`);
|
|
157
|
+
const require = createRequire(import.meta.url);
|
|
158
|
+
let vueVersion = '3.x';
|
|
159
|
+
try {
|
|
160
|
+
const vuePkgPath = require.resolve('vue/package.json');
|
|
161
|
+
const vuePkg = JSON.parse(node_fs.readFileSync(vuePkgPath, 'utf-8'));
|
|
162
|
+
vueVersion = vuePkg.version || vueVersion;
|
|
163
|
+
} catch {}
|
|
164
|
+
const components = {};
|
|
165
|
+
for (const [name, entry] of Object.entries(ctx.contract?.dev?.componentMap || {}))components[name] = {
|
|
166
|
+
name,
|
|
167
|
+
entry,
|
|
168
|
+
framework: 'vue'
|
|
169
|
+
};
|
|
170
|
+
const discovery = {
|
|
171
|
+
framework: {
|
|
172
|
+
type: 'vue',
|
|
173
|
+
version: vueVersion
|
|
174
|
+
},
|
|
175
|
+
server: {
|
|
176
|
+
host: String(server.config.server.host || 'localhost'),
|
|
177
|
+
port: actualPort || server.config.server.port || 5173,
|
|
178
|
+
protocol: proto,
|
|
179
|
+
origins: originCandidates
|
|
180
|
+
},
|
|
181
|
+
endpoints: {
|
|
182
|
+
discovery: STABLE_DISCOVERY_PATH,
|
|
183
|
+
contract: STABLE_CONTRACT_PATH,
|
|
184
|
+
init: STABLE_INIT_PATH,
|
|
185
|
+
runtime: STABLE_VUE_RUNTIME_PATH,
|
|
186
|
+
debug: {
|
|
187
|
+
html: STABLE_DEBUG_HTML_PATH,
|
|
188
|
+
json: STABLE_DEBUG_JSON_PATH
|
|
189
|
+
},
|
|
190
|
+
loader: {
|
|
191
|
+
base: STABLE_LOADER_BASE_PATH,
|
|
192
|
+
umd: STABLE_LOADER_UMD_PATH
|
|
193
|
+
}
|
|
194
|
+
},
|
|
195
|
+
components,
|
|
196
|
+
events: {
|
|
197
|
+
fullReload: ctx.contract?.events?.fullReload || '',
|
|
198
|
+
hmrUpdate: ctx.contract?.events?.hmrUpdate || ''
|
|
199
|
+
},
|
|
200
|
+
protocol: {
|
|
201
|
+
version: '2.0.0',
|
|
202
|
+
apiLevel: 1
|
|
203
|
+
}
|
|
204
|
+
};
|
|
205
|
+
res.statusCode = 200;
|
|
206
|
+
res.setHeader('Content-Type', 'application/json; charset=utf-8');
|
|
207
|
+
res.setHeader('Access-Control-Allow-Origin', '*');
|
|
208
|
+
res.setHeader('Cache-Control', 'no-cache, no-store, must-revalidate');
|
|
209
|
+
res.end(JSON.stringify(discovery, null, 2));
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
if (url.startsWith(STABLE_DEBUG_JSON_PATH)) {
|
|
213
|
+
const isHttps = !!server.config.server.https;
|
|
214
|
+
const proto = isHttps ? 'https' : 'http';
|
|
215
|
+
const hostHeader = String(req.headers.host || '');
|
|
216
|
+
const addr = server.httpServer?.address();
|
|
217
|
+
const actualPort = addr && 'object' == typeof addr ? addr.port : void 0;
|
|
218
|
+
const lanHosts = getLanIPv4Hosts();
|
|
219
|
+
const candidateHosts = [
|
|
220
|
+
'localhost',
|
|
221
|
+
'127.0.0.1',
|
|
222
|
+
...lanHosts
|
|
223
|
+
];
|
|
224
|
+
const originCandidates = candidateHosts.map((h)=>`${proto}://${h}${actualPort ? `:${actualPort}` : ''}`);
|
|
225
|
+
const requestOrigin = hostHeader ? `${proto}://${hostHeader}` : originCandidates[0];
|
|
226
|
+
res.statusCode = 200;
|
|
227
|
+
res.setHeader('Content-Type', 'application/json; charset=utf-8');
|
|
228
|
+
res.end(JSON.stringify({
|
|
229
|
+
contract: ctx.contract,
|
|
230
|
+
stats: ctx.stats,
|
|
231
|
+
audit: ctx.audit,
|
|
232
|
+
server: {
|
|
233
|
+
protocol: proto,
|
|
234
|
+
hostHeader,
|
|
235
|
+
actualPort,
|
|
236
|
+
config: {
|
|
237
|
+
host: server.config.server.host,
|
|
238
|
+
port: server.config.server.port,
|
|
239
|
+
strictPort: server.config.server.strictPort,
|
|
240
|
+
cors: server.config.server.cors,
|
|
241
|
+
https: !!server.config.server.https
|
|
242
|
+
}
|
|
243
|
+
},
|
|
244
|
+
originCandidates,
|
|
245
|
+
usage: {
|
|
246
|
+
localStorageKey: 'VITE_DEV_SERVER_ORIGIN',
|
|
247
|
+
suggested: requestOrigin,
|
|
248
|
+
snippet: `localStorage.setItem('VITE_DEV_SERVER_ORIGIN', '${requestOrigin}'); location.reload();`
|
|
249
|
+
}
|
|
250
|
+
}, null, 2));
|
|
251
|
+
return;
|
|
252
|
+
}
|
|
253
|
+
if (url.startsWith(STABLE_DEBUG_HTML_PATH)) {
|
|
254
|
+
const isHttps = !!server.config.server.https;
|
|
255
|
+
const proto = isHttps ? 'https' : 'http';
|
|
256
|
+
const addr = server.httpServer?.address();
|
|
257
|
+
const actualPort = addr && 'object' == typeof addr ? addr.port : void 0;
|
|
258
|
+
const lanHosts = getLanIPv4Hosts();
|
|
259
|
+
const candidateHosts = [
|
|
260
|
+
'localhost',
|
|
261
|
+
'127.0.0.1',
|
|
262
|
+
...lanHosts
|
|
263
|
+
];
|
|
264
|
+
const originCandidates = candidateHosts.map((h)=>`${proto}://${h}${actualPort ? `:${actualPort}` : ''}`);
|
|
265
|
+
const html = renderDebugHtml({
|
|
266
|
+
originCandidates,
|
|
267
|
+
contract: ctx.contract
|
|
268
|
+
});
|
|
269
|
+
res.statusCode = 200;
|
|
270
|
+
res.setHeader('Content-Type', 'text/html; charset=utf-8');
|
|
271
|
+
res.end(html);
|
|
272
|
+
return;
|
|
273
|
+
}
|
|
274
|
+
next();
|
|
275
|
+
});
|
|
276
|
+
}
|
|
277
|
+
function renderDebugHtml(params) {
|
|
278
|
+
const { originCandidates, contract } = params;
|
|
279
|
+
const originsJson = JSON.stringify(originCandidates);
|
|
280
|
+
const contractJson = JSON.stringify(contract, null, 2);
|
|
281
|
+
return `<!doctype html>
|
|
282
|
+
<html lang="en">
|
|
283
|
+
<head>
|
|
284
|
+
<meta charset="utf-8" />
|
|
285
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
286
|
+
<title>DevTo Vue Debug</title>
|
|
287
|
+
<style>
|
|
288
|
+
body { font-family: system-ui, sans-serif; padding: 20px; color: #111827; }
|
|
289
|
+
h1 { font-size: 20px; margin-bottom: 8px; }
|
|
290
|
+
.card { border: 1px solid #e5e7eb; border-radius: 8px; padding: 12px; margin-bottom: 12px; }
|
|
291
|
+
.origin { display: flex; gap: 8px; align-items: center; margin-bottom: 8px; }
|
|
292
|
+
button { border: 1px solid #d1d5db; background: #fff; padding: 4px 8px; border-radius: 4px; cursor: pointer; }
|
|
293
|
+
pre { background: #f9fafb; padding: 10px; border-radius: 6px; overflow: auto; font-size: 12px; }
|
|
294
|
+
code { font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; }
|
|
295
|
+
</style>
|
|
296
|
+
</head>
|
|
297
|
+
<body>
|
|
298
|
+
<h1>DevTo Vue Debug</h1>
|
|
299
|
+
<div class="card">
|
|
300
|
+
<div><strong>Set origin in host</strong></div>
|
|
301
|
+
<div id="origin-list"></div>
|
|
302
|
+
<pre id="origin-cmd"></pre>
|
|
303
|
+
</div>
|
|
304
|
+
<div class="card">
|
|
305
|
+
<div><strong>Contract</strong></div>
|
|
306
|
+
<pre>${contractJson}</pre>
|
|
307
|
+
</div>
|
|
308
|
+
<script>
|
|
309
|
+
const origins = ${originsJson};
|
|
310
|
+
const list = document.getElementById('origin-list');
|
|
311
|
+
const cmd = document.getElementById('origin-cmd');
|
|
312
|
+
|
|
313
|
+
function makeCmd(origin) {
|
|
314
|
+
return "localStorage.setItem('VITE_DEV_SERVER_ORIGIN', '" + origin + "'); location.reload();";
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
function setCmd(origin) {
|
|
318
|
+
cmd.textContent = makeCmd(origin);
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
function copy(text) {
|
|
322
|
+
if (navigator.clipboard && navigator.clipboard.writeText) {
|
|
323
|
+
return navigator.clipboard.writeText(text);
|
|
324
|
+
}
|
|
325
|
+
const ta = document.createElement('textarea');
|
|
326
|
+
ta.value = text;
|
|
327
|
+
document.body.appendChild(ta);
|
|
328
|
+
ta.select();
|
|
329
|
+
document.execCommand('copy');
|
|
330
|
+
document.body.removeChild(ta);
|
|
331
|
+
return Promise.resolve();
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
origins.forEach(origin => {
|
|
335
|
+
const row = document.createElement('div');
|
|
336
|
+
row.className = 'origin';
|
|
337
|
+
const code = document.createElement('code');
|
|
338
|
+
code.textContent = origin;
|
|
339
|
+
const btn = document.createElement('button');
|
|
340
|
+
btn.textContent = 'Copy';
|
|
341
|
+
btn.onclick = () => {
|
|
342
|
+
setCmd(origin);
|
|
343
|
+
copy(makeCmd(origin));
|
|
344
|
+
};
|
|
345
|
+
row.appendChild(code);
|
|
346
|
+
row.appendChild(btn);
|
|
347
|
+
list.appendChild(row);
|
|
348
|
+
});
|
|
349
|
+
|
|
350
|
+
if (origins[0]) setCmd(origins[0]);
|
|
351
|
+
</script>
|
|
352
|
+
</body>
|
|
353
|
+
</html>`;
|
|
354
|
+
}
|
|
355
|
+
function tryResolveWithExtensions(p) {
|
|
356
|
+
const exts = [
|
|
357
|
+
'.vue',
|
|
358
|
+
'.tsx',
|
|
359
|
+
'.jsx',
|
|
360
|
+
'.ts',
|
|
361
|
+
'.js'
|
|
362
|
+
];
|
|
363
|
+
if (node_fs.existsSync(p)) return p;
|
|
364
|
+
const parsed = node_path.parse(p);
|
|
365
|
+
if (parsed.ext) for (const ext of exts){
|
|
366
|
+
const cand = node_path.join(parsed.dir, `${parsed.name}${ext}`);
|
|
367
|
+
if (node_fs.existsSync(cand)) return cand;
|
|
368
|
+
}
|
|
369
|
+
else for (const ext of exts){
|
|
370
|
+
const cand = `${p}${ext}`;
|
|
371
|
+
if (node_fs.existsSync(cand)) return cand;
|
|
372
|
+
}
|
|
373
|
+
return null;
|
|
374
|
+
}
|
|
375
|
+
function toViteFsPath(filePath) {
|
|
376
|
+
const normalized = filePath.replace(/\\/g, '/');
|
|
377
|
+
return normalized.startsWith('/') ? `/@fs${normalized}` : `/@fs/${normalized}`;
|
|
378
|
+
}
|
|
379
|
+
function resolveDefaultEntryAbs(rootDir) {
|
|
380
|
+
const appCandidates = [
|
|
381
|
+
node_path.resolve(rootDir, 'src/App.vue'),
|
|
382
|
+
node_path.resolve(rootDir, 'src/App.ts'),
|
|
383
|
+
node_path.resolve(rootDir, 'src/App.tsx'),
|
|
384
|
+
node_path.resolve(rootDir, 'src/App.jsx'),
|
|
385
|
+
node_path.resolve(rootDir, 'src/App.js')
|
|
386
|
+
];
|
|
387
|
+
const foundApp = appCandidates.find((p)=>node_fs.existsSync(p));
|
|
388
|
+
if (foundApp) return foundApp;
|
|
389
|
+
const mainCandidates = [
|
|
390
|
+
node_path.resolve(rootDir, 'src/main.ts'),
|
|
391
|
+
node_path.resolve(rootDir, 'src/main.tsx'),
|
|
392
|
+
node_path.resolve(rootDir, 'src/main.jsx'),
|
|
393
|
+
node_path.resolve(rootDir, 'src/main.js'),
|
|
394
|
+
node_path.resolve(rootDir, 'src/index.ts'),
|
|
395
|
+
node_path.resolve(rootDir, 'src/index.tsx'),
|
|
396
|
+
node_path.resolve(rootDir, 'src/index.jsx'),
|
|
397
|
+
node_path.resolve(rootDir, 'src/index.js')
|
|
398
|
+
];
|
|
399
|
+
const foundMain = mainCandidates.find((p)=>node_fs.existsSync(p));
|
|
400
|
+
if (foundMain) return foundMain;
|
|
401
|
+
return appCandidates[0];
|
|
402
|
+
}
|
|
403
|
+
function buildDevComponentMapFromRecord(rootDir, input, defaultEntryAbs, convertAt = false, fallbackRoot) {
|
|
404
|
+
const out = {};
|
|
405
|
+
for (const [componentName, entry] of Object.entries(input)){
|
|
406
|
+
if (!componentName || !entry) continue;
|
|
407
|
+
if ('/' === entry) {
|
|
408
|
+
out[componentName] = convertAt ? toViteFsPath(defaultEntryAbs) : '/';
|
|
409
|
+
continue;
|
|
410
|
+
}
|
|
411
|
+
if (entry.startsWith('http://') || entry.startsWith('https://') || entry.startsWith('/')) {
|
|
412
|
+
out[componentName] = entry;
|
|
413
|
+
continue;
|
|
414
|
+
}
|
|
415
|
+
const abs = node_path.isAbsolute(entry) ? entry : node_path.resolve(rootDir, entry);
|
|
416
|
+
let resolved = tryResolveWithExtensions(abs);
|
|
417
|
+
if (!resolved && fallbackRoot && fallbackRoot !== rootDir) {
|
|
418
|
+
const fallbackAbs = node_path.isAbsolute(entry) ? entry : node_path.resolve(fallbackRoot, entry);
|
|
419
|
+
resolved = tryResolveWithExtensions(fallbackAbs);
|
|
420
|
+
}
|
|
421
|
+
resolved = resolved || abs;
|
|
422
|
+
out[componentName] = toViteFsPath(resolved);
|
|
423
|
+
}
|
|
424
|
+
return out;
|
|
425
|
+
}
|
|
426
|
+
function getFsPathFromViteEntry(entry) {
|
|
427
|
+
if (!entry.startsWith('/@fs')) return null;
|
|
428
|
+
let p = entry.slice(4);
|
|
429
|
+
if (p.startsWith('/') && /\/[A-Za-z]:\//.test(p)) p = p.slice(1);
|
|
430
|
+
return p;
|
|
431
|
+
}
|
|
432
|
+
function resolveDevComponentConfig(rootDir, devComponentMap, fallbackRoot) {
|
|
433
|
+
const defaultEntryAbs = resolveDefaultEntryAbs(rootDir);
|
|
434
|
+
const defaultEntry = toViteFsPath(defaultEntryAbs);
|
|
435
|
+
let resolvedDevComponentMap = {};
|
|
436
|
+
if ('string' == typeof devComponentMap) {
|
|
437
|
+
const name = devComponentMap.trim();
|
|
438
|
+
resolvedDevComponentMap = name ? buildDevComponentMapFromRecord(rootDir, {
|
|
439
|
+
[name]: '/'
|
|
440
|
+
}, defaultEntryAbs, false, fallbackRoot) : {
|
|
441
|
+
'*': '/'
|
|
442
|
+
};
|
|
443
|
+
} else {
|
|
444
|
+
const input = devComponentMap ?? {};
|
|
445
|
+
resolvedDevComponentMap = 0 === Object.keys(input).length ? {
|
|
446
|
+
'*': '/'
|
|
447
|
+
} : buildDevComponentMapFromRecord(rootDir, input, defaultEntryAbs, false, fallbackRoot);
|
|
448
|
+
}
|
|
449
|
+
const audit = (()=>{
|
|
450
|
+
const missing = [];
|
|
451
|
+
for (const [componentName, entry] of Object.entries(resolvedDevComponentMap)){
|
|
452
|
+
const fsPath = getFsPathFromViteEntry(entry);
|
|
453
|
+
if (fsPath) {
|
|
454
|
+
const resolved = tryResolveWithExtensions(fsPath);
|
|
455
|
+
if (!resolved || !node_fs.existsSync(resolved)) missing.push({
|
|
456
|
+
componentName,
|
|
457
|
+
filePath: fsPath
|
|
458
|
+
});
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
return {
|
|
462
|
+
defaultEntryAbs,
|
|
463
|
+
defaultEntryExists: node_fs.existsSync(defaultEntryAbs),
|
|
464
|
+
componentMapCount: Object.keys(resolvedDevComponentMap).length,
|
|
465
|
+
missingEntries: missing
|
|
466
|
+
};
|
|
467
|
+
})();
|
|
468
|
+
return {
|
|
469
|
+
defaultEntryAbs,
|
|
470
|
+
defaultEntry,
|
|
471
|
+
componentMap: resolvedDevComponentMap,
|
|
472
|
+
audit
|
|
473
|
+
};
|
|
474
|
+
}
|
|
475
|
+
function transformAssetUrl(code, id) {
|
|
476
|
+
if (id.includes('?import') || /\.(svg|png|jpg|jpeg|gif|webp|ico|bmp|tiff|woff|woff2|ttf|eot|otf)$/.test(id)) {
|
|
477
|
+
const relativePathMatch = code.match(/export\s+default\s+["']([^"']+)["']/);
|
|
478
|
+
if (relativePathMatch) {
|
|
479
|
+
const relativePath = relativePathMatch[1];
|
|
480
|
+
if (relativePath.startsWith('/') && !relativePath.startsWith('http')) {
|
|
481
|
+
const transformedCode = code.replace(/export\s+default\s+["']([^"']+)["']/, `export default (() => {
|
|
482
|
+
const path = "${relativePath}";
|
|
483
|
+
if (typeof window !== 'undefined' && window[${JSON.stringify(DEV_TO_VUE_RESOLVE_ASSET_KEY)}]) {
|
|
484
|
+
return window[${JSON.stringify(DEV_TO_VUE_RESOLVE_ASSET_KEY)}](path);
|
|
485
|
+
}
|
|
486
|
+
try {
|
|
487
|
+
const ORIGIN = new URL(import.meta.url).origin;
|
|
488
|
+
return path.startsWith('http') ? path : ORIGIN + path;
|
|
489
|
+
} catch (e) {
|
|
490
|
+
console.warn('${constants_PLUGIN_LOG_PREFIX} Failed to resolve static asset URL:', path, e);
|
|
491
|
+
return path;
|
|
492
|
+
}
|
|
493
|
+
})()`);
|
|
494
|
+
return {
|
|
495
|
+
code: transformedCode,
|
|
496
|
+
map: null
|
|
497
|
+
};
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
return null;
|
|
502
|
+
}
|
|
503
|
+
function transformViteDevCssAssetUrls(code, id) {
|
|
504
|
+
const cleanId = id.split('?')[0];
|
|
505
|
+
if (!/\.(css|less|sass|scss|styl|stylus)$/.test(cleanId)) return null;
|
|
506
|
+
if (!code.includes('__vite__updateStyle') || !code.includes('const __vite__css')) return null;
|
|
507
|
+
if (!/url\(\s*['"]?\//.test(code)) return null;
|
|
508
|
+
if (code.includes('__dev_to__css')) return null;
|
|
509
|
+
const updateCallRE = /__vite__updateStyle\(\s*__vite__id\s*,\s*__vite__css\s*\)/;
|
|
510
|
+
if (!updateCallRE.test(code)) return null;
|
|
511
|
+
const injected = `
|
|
512
|
+
const __dev_to__resolveAsset = (path) => {
|
|
513
|
+
if (!path) return path;
|
|
514
|
+
if (path.startsWith('http://') || path.startsWith('https://') || path.startsWith('data:') || path.startsWith('blob:')) {
|
|
515
|
+
return path;
|
|
516
|
+
}
|
|
517
|
+
try {
|
|
518
|
+
const g = typeof globalThis !== 'undefined' ? globalThis : window;
|
|
519
|
+
const fn = g && g[${JSON.stringify(DEV_TO_VUE_RESOLVE_ASSET_KEY)}];
|
|
520
|
+
if (typeof fn === 'function') return fn(path);
|
|
521
|
+
} catch {
|
|
522
|
+
// ignore
|
|
523
|
+
}
|
|
524
|
+
try {
|
|
525
|
+
const origin = new URL(import.meta.url).origin;
|
|
526
|
+
return path.startsWith('/') ? origin + path : origin + '/' + path;
|
|
527
|
+
} catch (e) {
|
|
528
|
+
console.warn('${constants_PLUGIN_LOG_PREFIX} Failed to resolve CSS asset URL:', path, e);
|
|
529
|
+
return path;
|
|
530
|
+
}
|
|
531
|
+
};
|
|
532
|
+
const __dev_to__css = __vite__css.replace(/url\\(\\s*(['"]?)(\\/(?!\\/)[^'")]+)\\1\\s*\\)/g, (_m, q, p) => {
|
|
533
|
+
const next = __dev_to__resolveAsset(p);
|
|
534
|
+
return 'url(' + q + next + q + ')';
|
|
535
|
+
});
|
|
536
|
+
`;
|
|
537
|
+
const nextCode = code.replace(updateCallRE, `${injected}__vite__updateStyle(__vite__id, __dev_to__css)`);
|
|
538
|
+
return {
|
|
539
|
+
code: nextCode,
|
|
540
|
+
map: null
|
|
541
|
+
};
|
|
542
|
+
}
|
|
543
|
+
function createContractVirtualModuleCode(contract) {
|
|
544
|
+
return `
|
|
545
|
+
const CONTRACT = ${JSON.stringify(contract)};
|
|
546
|
+
const ORIGIN = new URL(import.meta.url).origin;
|
|
547
|
+
const G = typeof globalThis !== 'undefined' ? globalThis : window;
|
|
548
|
+
const DEBUG_KEY = ${JSON.stringify(DEV_TO_VUE_DEBUG_STATE_KEY)};
|
|
549
|
+
const STATE = (G[DEBUG_KEY] ||= { logged: {} });
|
|
550
|
+
if (!STATE.logged.contract) {
|
|
551
|
+
STATE.logged.contract = true;
|
|
552
|
+
console.groupCollapsed('${constants_PLUGIN_LOG_PREFIX} contract loaded');
|
|
553
|
+
console.log('Origin:', ORIGIN);
|
|
554
|
+
console.log('Paths:', CONTRACT.paths);
|
|
555
|
+
console.log('Events:', CONTRACT.events);
|
|
556
|
+
console.log('Components:', Object.keys(CONTRACT?.dev?.componentMap || {}));
|
|
557
|
+
console.log('Tip: open', ORIGIN + '${STABLE_DEBUG_HTML_PATH}');
|
|
558
|
+
console.groupEnd();
|
|
559
|
+
}
|
|
560
|
+
export const DEV_TO_VUE_CONTRACT = CONTRACT;
|
|
561
|
+
export default CONTRACT;
|
|
562
|
+
`;
|
|
563
|
+
}
|
|
564
|
+
function createInitVirtualModuleCode() {
|
|
565
|
+
const contractExportName = 'DEV_TO_VUE_CONTRACT';
|
|
566
|
+
const globalKey = DEV_TO_VUE_CONTRACT_KEY;
|
|
567
|
+
return `
|
|
568
|
+
import "/@vite/client";
|
|
569
|
+
|
|
570
|
+
import CONTRACT, { ${contractExportName} as CONTRACT_NAMED } from "${STABLE_CONTRACT_PATH}";
|
|
571
|
+
|
|
572
|
+
{
|
|
573
|
+
const ORIGIN = new URL(import.meta.url).origin;
|
|
574
|
+
const G = typeof globalThis !== 'undefined' ? globalThis : window;
|
|
575
|
+
const DEBUG_KEY = ${JSON.stringify(DEV_TO_VUE_DEBUG_STATE_KEY)};
|
|
576
|
+
const STATE = (G[DEBUG_KEY] ||= { logged: {} });
|
|
577
|
+
if (!STATE.logged.init) {
|
|
578
|
+
STATE.logged.init = true;
|
|
579
|
+
console.groupCollapsed('${constants_PLUGIN_LOG_PREFIX} init loaded (HMR enabled)');
|
|
580
|
+
console.log('Origin:', ORIGIN);
|
|
581
|
+
console.log('This module imports /@vite/client.');
|
|
582
|
+
console.groupEnd();
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
if (typeof window !== 'undefined') {
|
|
586
|
+
window[${JSON.stringify(DEV_TO_VUE_ORIGIN_KEY)}] = ORIGIN;
|
|
587
|
+
window[${JSON.stringify(DEV_TO_VUE_RESOLVE_ASSET_KEY)}] = (path) => {
|
|
588
|
+
if (!path) return path;
|
|
589
|
+
if (path.startsWith('http://') || path.startsWith('https://') || path.startsWith('data:')) {
|
|
590
|
+
return path;
|
|
591
|
+
}
|
|
592
|
+
const origin = window[${JSON.stringify(DEV_TO_VUE_ORIGIN_KEY)}] || ORIGIN;
|
|
593
|
+
return path.startsWith('/') ? origin + path : origin + '/' + path;
|
|
594
|
+
};
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
if (import.meta.hot) {
|
|
599
|
+
import.meta.hot.accept();
|
|
600
|
+
import.meta.hot.on('vite:beforeFullReload', () => {
|
|
601
|
+
window.dispatchEvent(new CustomEvent(CONTRACT.events.fullReload));
|
|
602
|
+
});
|
|
603
|
+
import.meta.hot.on('vite:afterUpdate', (payload) => {
|
|
604
|
+
payload.updates.forEach(update => {
|
|
605
|
+
window.dispatchEvent(new CustomEvent(CONTRACT.events.hmrUpdate, {
|
|
606
|
+
detail: { file: update.path, timestamp: payload.timestamp }
|
|
607
|
+
}));
|
|
608
|
+
});
|
|
609
|
+
});
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
export const ${contractExportName} = CONTRACT_NAMED || CONTRACT;
|
|
613
|
+
if (typeof window !== 'undefined') {
|
|
614
|
+
window[${JSON.stringify(globalKey)}] = CONTRACT;
|
|
615
|
+
}
|
|
616
|
+
export default CONTRACT;
|
|
617
|
+
`;
|
|
618
|
+
}
|
|
619
|
+
function createVueRuntimeVirtualModuleCode() {
|
|
620
|
+
return `
|
|
621
|
+
import * as Vue from "vue";
|
|
622
|
+
{
|
|
623
|
+
const ORIGIN = new URL(import.meta.url).origin;
|
|
624
|
+
const G = typeof globalThis !== 'undefined' ? globalThis : window;
|
|
625
|
+
const DEBUG_KEY = ${JSON.stringify(DEV_TO_VUE_DEBUG_STATE_KEY)};
|
|
626
|
+
const STATE = (G[DEBUG_KEY] ||= { logged: {} });
|
|
627
|
+
if (!STATE.logged.runtime) {
|
|
628
|
+
STATE.logged.runtime = true;
|
|
629
|
+
console.groupCollapsed('${constants_PLUGIN_LOG_PREFIX} vue-runtime loaded');
|
|
630
|
+
console.log('Origin:', ORIGIN);
|
|
631
|
+
console.log('Vue.version:', Vue?.version);
|
|
632
|
+
console.groupEnd();
|
|
633
|
+
}
|
|
634
|
+
}
|
|
635
|
+
export { Vue };
|
|
636
|
+
export default Vue;
|
|
637
|
+
`;
|
|
638
|
+
}
|
|
639
|
+
function devToVuePlugin(components, options) {
|
|
640
|
+
const componentsMap = components ?? {};
|
|
641
|
+
const opts = options ?? {};
|
|
642
|
+
const stats = {
|
|
643
|
+
contract: {
|
|
644
|
+
count: 0,
|
|
645
|
+
lastAt: 0
|
|
646
|
+
},
|
|
647
|
+
init: {
|
|
648
|
+
count: 0,
|
|
649
|
+
lastAt: 0
|
|
650
|
+
},
|
|
651
|
+
runtime: {
|
|
652
|
+
count: 0,
|
|
653
|
+
lastAt: 0
|
|
654
|
+
}
|
|
655
|
+
};
|
|
656
|
+
const debugState = {
|
|
657
|
+
didPrintStartupDebugUrl: false
|
|
658
|
+
};
|
|
659
|
+
let configDir = process.cwd();
|
|
660
|
+
let currentRootDir = configDir;
|
|
661
|
+
let resolvedConfig = resolveDevComponentConfig(currentRootDir, componentsMap, configDir);
|
|
662
|
+
const createContract = (componentMap, defaultEntryAbs, isDevMode = false)=>{
|
|
663
|
+
const processedComponentMap = {};
|
|
664
|
+
for (const [key, value] of Object.entries(componentMap))if ('/' === value && isDevMode) processedComponentMap[key] = toViteFsPath(defaultEntryAbs);
|
|
665
|
+
else processedComponentMap[key] = value;
|
|
666
|
+
return {
|
|
667
|
+
paths: {
|
|
668
|
+
contract: STABLE_CONTRACT_PATH,
|
|
669
|
+
initClient: STABLE_INIT_PATH,
|
|
670
|
+
vueRuntime: STABLE_VUE_RUNTIME_PATH
|
|
671
|
+
},
|
|
672
|
+
events: {
|
|
673
|
+
fullReload: EVENT_FULL_RELOAD,
|
|
674
|
+
hmrUpdate: EVENT_HMR_UPDATE
|
|
675
|
+
},
|
|
676
|
+
dev: {
|
|
677
|
+
componentMap: processedComponentMap
|
|
678
|
+
}
|
|
679
|
+
};
|
|
680
|
+
};
|
|
681
|
+
let contract = createContract(resolvedConfig.componentMap, resolvedConfig.defaultEntryAbs, true);
|
|
682
|
+
const corePlugin = {
|
|
683
|
+
name: '@dev-to/vue-plugin',
|
|
684
|
+
enforce: 'pre',
|
|
685
|
+
configureServer (server) {
|
|
686
|
+
contract = createContract(resolvedConfig.componentMap, resolvedConfig.defaultEntryAbs, true);
|
|
687
|
+
if (1 === Object.keys(resolvedConfig.componentMap).length && '/' === resolvedConfig.componentMap['*']) {
|
|
688
|
+
const warn = server.config.logger?.warn?.bind(server.config.logger) ?? console.warn;
|
|
689
|
+
warn('');
|
|
690
|
+
warn(`Warning: ${constants_PLUGIN_LOG_PREFIX} No componentName configured. This works in dev mode but should be explicit for production builds.`);
|
|
691
|
+
warn('Use devToVuePlugin({ ComponentName: "src/ComponentName.vue" }) or devToVuePlugin({ ComponentName: "/" }).');
|
|
692
|
+
warn('');
|
|
693
|
+
}
|
|
694
|
+
installDebugTools(server, {
|
|
695
|
+
contract,
|
|
696
|
+
stats,
|
|
697
|
+
audit: resolvedConfig.audit,
|
|
698
|
+
resolvedConfig,
|
|
699
|
+
configDir,
|
|
700
|
+
open: opts.open
|
|
701
|
+
}, debugState);
|
|
702
|
+
},
|
|
703
|
+
config (userConfig, env) {
|
|
704
|
+
const rootDir = configDir;
|
|
705
|
+
if (rootDir !== currentRootDir) {
|
|
706
|
+
currentRootDir = rootDir;
|
|
707
|
+
resolvedConfig = resolveDevComponentConfig(rootDir, componentsMap, configDir);
|
|
708
|
+
const isDev = 'build' !== env.command;
|
|
709
|
+
contract = createContract(resolvedConfig.componentMap, resolvedConfig.defaultEntryAbs, isDev);
|
|
710
|
+
}
|
|
711
|
+
const next = {
|
|
712
|
+
server: {
|
|
713
|
+
host: userConfig.server?.host ?? true,
|
|
714
|
+
cors: userConfig.server?.cors ?? true
|
|
715
|
+
},
|
|
716
|
+
css: {
|
|
717
|
+
modules: {
|
|
718
|
+
generateScopedName: '[name]__[local]___[hash:base64:5]'
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
};
|
|
722
|
+
if (false === opts.css) next.css = void 0;
|
|
723
|
+
else if (opts.css) next.css = mergeConfig({
|
|
724
|
+
css: next.css
|
|
725
|
+
}, {
|
|
726
|
+
css: opts.css
|
|
727
|
+
}).css;
|
|
728
|
+
return next;
|
|
729
|
+
},
|
|
730
|
+
configResolved (resolved) {
|
|
731
|
+
if (resolved.configFile) {
|
|
732
|
+
const nextConfigDir = node_path.dirname(resolved.configFile);
|
|
733
|
+
if (nextConfigDir !== configDir) {
|
|
734
|
+
configDir = nextConfigDir;
|
|
735
|
+
currentRootDir = configDir;
|
|
736
|
+
resolvedConfig = resolveDevComponentConfig(currentRootDir, componentsMap, configDir);
|
|
737
|
+
const isDev = 'serve' === resolved.command;
|
|
738
|
+
contract = createContract(resolvedConfig.componentMap, resolvedConfig.defaultEntryAbs, isDev);
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
},
|
|
742
|
+
resolveId (source) {
|
|
743
|
+
if (source.includes(STABLE_CONTRACT_PATH)) return `\0virtual:${PLUGIN_NAME}-contract`;
|
|
744
|
+
if (source.includes(STABLE_INIT_PATH)) return `\0virtual:${PLUGIN_NAME}-init`;
|
|
745
|
+
if (source.includes(STABLE_VUE_RUNTIME_PATH)) return `\0virtual:${PLUGIN_NAME}-vue-runtime`;
|
|
746
|
+
return null;
|
|
747
|
+
},
|
|
748
|
+
load (id) {
|
|
749
|
+
if (id === `\0virtual:${PLUGIN_NAME}-contract`) return createContractVirtualModuleCode(contract);
|
|
750
|
+
if (id === `\0virtual:${PLUGIN_NAME}-init`) return createInitVirtualModuleCode();
|
|
751
|
+
if (id === `\0virtual:${PLUGIN_NAME}-vue-runtime`) return createVueRuntimeVirtualModuleCode();
|
|
752
|
+
return null;
|
|
753
|
+
},
|
|
754
|
+
transform (code, id) {
|
|
755
|
+
return transformAssetUrl(code, id);
|
|
756
|
+
}
|
|
757
|
+
};
|
|
758
|
+
const devCssAssetPlugin = {
|
|
759
|
+
name: '@dev-to/vue-plugin:dev-css-asset-url',
|
|
760
|
+
enforce: 'post',
|
|
761
|
+
transform (code, id) {
|
|
762
|
+
return transformViteDevCssAssetUrls(code, id);
|
|
763
|
+
}
|
|
764
|
+
};
|
|
765
|
+
return [
|
|
766
|
+
corePlugin,
|
|
767
|
+
devCssAssetPlugin
|
|
768
|
+
];
|
|
769
|
+
}
|
|
770
|
+
export { devToVuePlugin };
|
package/dist/lan.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lan.d.ts","sourceRoot":"","sources":["../src/lan.ts"],"names":[],"mappings":"AAEA,wBAAgB,eAAe,IAAI,MAAM,EAAE,CAc1C"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export declare function toFsPathFromViteEntry(entry: string): string | null;
|
|
2
|
+
export declare function tryResolveWithExtensions(p: string): string | null;
|
|
3
|
+
export declare function resolveEntryAbsPath(rootDir: string, entry: string, defaultEntryAbs?: string, fallbackRoot?: string): string | null;
|
|
4
|
+
//# sourceMappingURL=pathUtils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pathUtils.d.ts","sourceRoot":"","sources":["../src/pathUtils.ts"],"names":[],"mappings":"AAKA,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAOlE;AAED,wBAAgB,wBAAwB,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAkBjE;AAED,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,EACb,eAAe,CAAC,EAAE,MAAM,EACxB,YAAY,CAAC,EAAE,MAAM,GACpB,MAAM,GAAG,IAAI,CA2Bf"}
|
package/dist/plugin.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAsBA,OAAO,KAAK,EAIV,oBAAoB,EACpB,qBAAqB,EACtB,MAAM,YAAY,CAAA;AAEnB,wBAAgB,cAAc,CAC5B,UAAU,CAAC,EAAE,oBAAoB,EACjC,OAAO,CAAC,EAAE,qBAAqB,GAC9B,GAAG,CAwJL"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export declare function transformAssetUrl(code: string, id: string): {
|
|
2
|
+
code: string;
|
|
3
|
+
map: null;
|
|
4
|
+
} | null;
|
|
5
|
+
export declare function transformViteDevCssAssetUrls(code: string, id: string): {
|
|
6
|
+
code: string;
|
|
7
|
+
map: null;
|
|
8
|
+
} | null;
|
|
9
|
+
//# sourceMappingURL=transformUtils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transformUtils.d.ts","sourceRoot":"","sources":["../src/transformUtils.ts"],"names":[],"mappings":"AAIA,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM;;;SA8BzD;AAED,wBAAgB,4BAA4B,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM;;;SA2CpE"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type { BuildOptions, CSSOptions } from 'vite';
|
|
2
|
+
export interface DevToVuePluginOptions {
|
|
3
|
+
css?: CSSOptions | false;
|
|
4
|
+
build?: BuildOptions;
|
|
5
|
+
open?: boolean;
|
|
6
|
+
}
|
|
7
|
+
export type DevComponentMapInput = Record<string, string> | string | undefined | null;
|
|
8
|
+
export interface DevComponentAudit {
|
|
9
|
+
defaultEntryAbs: string;
|
|
10
|
+
defaultEntryExists: boolean;
|
|
11
|
+
componentMapCount: number;
|
|
12
|
+
missingEntries: Array<{
|
|
13
|
+
componentName: string;
|
|
14
|
+
filePath: string;
|
|
15
|
+
}>;
|
|
16
|
+
}
|
|
17
|
+
export interface ResolvedDevComponentConfig {
|
|
18
|
+
defaultEntryAbs: string;
|
|
19
|
+
defaultEntry: string;
|
|
20
|
+
componentMap: Record<string, string>;
|
|
21
|
+
audit: DevComponentAudit;
|
|
22
|
+
}
|
|
23
|
+
export interface BridgeStatsBucket {
|
|
24
|
+
count: number;
|
|
25
|
+
lastAt: number;
|
|
26
|
+
}
|
|
27
|
+
export interface BridgeStats {
|
|
28
|
+
contract: BridgeStatsBucket;
|
|
29
|
+
init: BridgeStatsBucket;
|
|
30
|
+
runtime: BridgeStatsBucket;
|
|
31
|
+
}
|
|
32
|
+
export interface BridgeContract {
|
|
33
|
+
paths: {
|
|
34
|
+
contract: string;
|
|
35
|
+
initClient: string;
|
|
36
|
+
vueRuntime: string;
|
|
37
|
+
};
|
|
38
|
+
events: {
|
|
39
|
+
fullReload: string;
|
|
40
|
+
hmrUpdate: string;
|
|
41
|
+
};
|
|
42
|
+
dev: {
|
|
43
|
+
componentMap: Record<string, string>;
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
export interface DebugStartupState {
|
|
47
|
+
didPrintStartupDebugUrl: boolean;
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,MAAM,CAAA;AAEpD,MAAM,WAAW,qBAAqB;IACpC,GAAG,CAAC,EAAE,UAAU,GAAG,KAAK,CAAA;IACxB,KAAK,CAAC,EAAE,YAAY,CAAA;IACpB,IAAI,CAAC,EAAE,OAAO,CAAA;CACf;AAED,MAAM,MAAM,oBAAoB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,GAAG,SAAS,GAAG,IAAI,CAAA;AAErF,MAAM,WAAW,iBAAiB;IAChC,eAAe,EAAE,MAAM,CAAA;IACvB,kBAAkB,EAAE,OAAO,CAAA;IAC3B,iBAAiB,EAAE,MAAM,CAAA;IACzB,cAAc,EAAE,KAAK,CAAC;QAAE,aAAa,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CACnE;AAED,MAAM,WAAW,0BAA0B;IACzC,eAAe,EAAE,MAAM,CAAA;IACvB,YAAY,EAAE,MAAM,CAAA;IACpB,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACpC,KAAK,EAAE,iBAAiB,CAAA;CACzB;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,iBAAiB,CAAA;IAC3B,IAAI,EAAE,iBAAiB,CAAA;IACvB,OAAO,EAAE,iBAAiB,CAAA;CAC3B;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE;QACL,QAAQ,EAAE,MAAM,CAAA;QAChB,UAAU,EAAE,MAAM,CAAA;QAClB,UAAU,EAAE,MAAM,CAAA;KACnB,CAAA;IACD,MAAM,EAAE;QACN,UAAU,EAAE,MAAM,CAAA;QAClB,SAAS,EAAE,MAAM,CAAA;KAClB,CAAA;IACD,GAAG,EAAE;QACH,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;KACrC,CAAA;CACF;AAED,MAAM,WAAW,iBAAiB;IAChC,uBAAuB,EAAE,OAAO,CAAA;CACjC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { BridgeContract } from './types.js';
|
|
2
|
+
export declare function createContractVirtualModuleCode(contract: BridgeContract): string;
|
|
3
|
+
export declare function createInitVirtualModuleCode(): string;
|
|
4
|
+
export declare function createVueRuntimeVirtualModuleCode(): string;
|
|
5
|
+
//# sourceMappingURL=virtualModules.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"virtualModules.d.ts","sourceRoot":"","sources":["../src/virtualModules.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAEhD,wBAAgB,+BAA+B,CAAC,QAAQ,EAAE,cAAc,UAoBvE;AAED,wBAAgB,2BAA2B,WAuD1C;AAED,wBAAgB,iCAAiC,WAmBhD"}
|
package/package.json
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@dev-to/vue-plugin",
|
|
3
|
+
"version": "0.2.2",
|
|
4
|
+
"private": false,
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.js"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"dist"
|
|
16
|
+
],
|
|
17
|
+
"peerDependencies": {
|
|
18
|
+
"typescript": ">=5.0.0",
|
|
19
|
+
"vite": ">=4.0.0",
|
|
20
|
+
"vue": ">=3.0.0"
|
|
21
|
+
},
|
|
22
|
+
"repository": {
|
|
23
|
+
"type": "git",
|
|
24
|
+
"url": "git+https://github.com/YangYongAn/dev-to.git",
|
|
25
|
+
"directory": "packages/vue-plugin"
|
|
26
|
+
},
|
|
27
|
+
"publishConfig": {
|
|
28
|
+
"access": "public"
|
|
29
|
+
},
|
|
30
|
+
"dependencies": {
|
|
31
|
+
"@dev-to/shared": "1.0.4"
|
|
32
|
+
},
|
|
33
|
+
"scripts": {
|
|
34
|
+
"build": "rslib build",
|
|
35
|
+
"dev": "rslib build --watch",
|
|
36
|
+
"lint": "pnpm -w lint",
|
|
37
|
+
"test": "echo 'test @dev-to/vue-plugin'"
|
|
38
|
+
}
|
|
39
|
+
}
|