@ait-co/devtools 0.1.53 → 0.1.54-beta.0
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.en.md +12 -20
- package/README.md +12 -20
- package/dist/mcp/cli.js +3 -3
- package/dist/mcp/server.js +1 -1
- package/dist/mock/index.d.ts +46 -1
- package/dist/mock/index.d.ts.map +1 -1
- package/dist/mock/index.js +55 -1
- package/dist/mock/index.js.map +1 -1
- package/dist/panel/index.js +2 -2
- package/dist/panel/index.js.map +1 -1
- package/dist/unplugin/index.cjs +2 -1
- package/dist/unplugin/index.cjs.map +1 -1
- package/dist/unplugin/index.d.cts +11 -11
- package/dist/unplugin/index.d.cts.map +1 -1
- package/dist/unplugin/index.d.ts +11 -11
- package/dist/unplugin/index.d.ts.map +1 -1
- package/dist/unplugin/index.js +2 -1
- package/dist/unplugin/index.js.map +1 -1
- package/package.json +20 -18
package/dist/unplugin/index.cjs
CHANGED
|
@@ -48,6 +48,7 @@ const MOCK_PATH = (() => {
|
|
|
48
48
|
const FRAMEWORK_ID = "@apps-in-toss/web-framework";
|
|
49
49
|
const BRIDGE_ID = "@apps-in-toss/web-bridge";
|
|
50
50
|
const ANALYTICS_ID = "@apps-in-toss/web-analytics";
|
|
51
|
+
const WEBVIEW_BRIDGE_ID = "@apps-in-toss/webview-bridge";
|
|
51
52
|
/** MCP state endpoint path — browser panel POSTs here, MCP server GETs here */
|
|
52
53
|
const MCP_STATE_PATH = "/api/ait-devtools/state";
|
|
53
54
|
const aitDevtoolsPlugin = (0, unplugin.createUnplugin)((options) => {
|
|
@@ -65,7 +66,7 @@ const aitDevtoolsPlugin = (0, unplugin.createUnplugin)((options) => {
|
|
|
65
66
|
enforce: "pre",
|
|
66
67
|
resolveId(id) {
|
|
67
68
|
if (!shouldMock) return null;
|
|
68
|
-
if (id === FRAMEWORK_ID || id === BRIDGE_ID || id === ANALYTICS_ID) return MOCK_PATH;
|
|
69
|
+
if (id === FRAMEWORK_ID || id === WEBVIEW_BRIDGE_ID || id === BRIDGE_ID || id === ANALYTICS_ID) return MOCK_PATH;
|
|
69
70
|
return null;
|
|
70
71
|
},
|
|
71
72
|
transformInclude(id) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":[],"sources":["../../src/unplugin/index.ts"],"sourcesContent":["/**\n * @ait-co/devtools unplugin\n *\n * 모든 주요 번들러를 지원하는 단일 플러그인.\n * @apps-in-toss/web-framework → @ait-co/devtools/mock 으로 alias 설정.\n *\n * Usage:\n * import aitDevtools from '@ait-co/devtools/unplugin';\n *\n * // Vite\n * export default { plugins: [aitDevtools.vite()] };\n *\n * // Webpack / Next.js\n * config.plugins.push(aitDevtools.webpack());\n *\n * // Rspack\n * config.plugins.push(aitDevtools.rspack());\n *\n * // esbuild\n * { plugins: [aitDevtools.esbuild()] }\n *\n * // Rollup\n * { plugins: [aitDevtools.rollup()] }\n */\n\nimport { fileURLToPath } from 'node:url';\nimport { createUnplugin } from 'unplugin';\n\n/**\n * Resolve `@ait-co/devtools/mock` to its real file path at plugin-load time.\n *\n * Returning the bare specifier from `resolveId` would stop the bundler from\n * walking node_modules for it — Vite 8+ treats such a non-null string as the\n * final resolved id and serves it via the virtual `/@id/` prefix, which 404s\n * because we don't provide a `load` hook. Resolving to an absolute path here\n * lets every supported bundler load the file the normal way.\n */\nconst MOCK_PATH = (() => {\n try {\n return fileURLToPath(import.meta.resolve('@ait-co/devtools/mock'));\n } catch {\n // Fallback for runtimes where `import.meta.resolve` is unavailable.\n return '@ait-co/devtools/mock';\n }\n})();\n\nexport interface AitDevtoolsOptions {\n /**\n * 패널 자동 주입 여부 (default: true)\n * true이면 진입점에 floating panel import를 자동 추가한다.\n */\n panel?: boolean;\n /**\n * production 환경에서도 devtools를 강제로 활성화 (default: false)\n */\n forceEnable?: boolean;\n /**\n * mock alias 활성화 여부. default: true (development), false (production + forceEnable)\n */\n mock?: boolean;\n /**\n * Vite dev server에 MCP state endpoint를 추가할지 여부 (default: false).\n *\n * `true`로 설정하면:\n * - GET /api/ait-devtools/state — 마지막으로 브라우저가 push한 mock state 스냅샷 반환\n * - POST /api/ait-devtools/state — 브라우저 panel이 상태 변경 시 자동 push (panel 내부 처리)\n *\n * 이 endpoint를 `@ait-co/devtools` MCP stdio server가 읽어 AI 에이전트에 mock state를 노출한다.\n * Vite 전용: webpack/rspack/esbuild/rollup 환경에서는 무시된다.\n */\n mcp?: boolean;\n /**\n * Vite dev 서버를 Cloudflare quick tunnel(`*.trycloudflare.com`, 계정 불필요)로\n * 외부 노출해 실제 폰에서 미리보기. **Vite dev 모드 전용** — production은\n * `forceEnable`이어도 터널을 띄우지 않는다 (의도치 않은 노출 방지). 다른 번들러는\n * 무시. `true`면 기본 동작, 객체로 세부 설정 가능.\n */\n tunnel?:\n | boolean\n | {\n /** 노출할 포트 (미지정 시 dev 서버가 실제 listen한 포트 자동 감지). */\n port?: number;\n /** 터미널 ASCII QR 출력 (default: true). */\n qr?: boolean;\n };\n}\n\nconst FRAMEWORK_ID = '@apps-in-toss/web-framework';\nconst BRIDGE_ID = '@apps-in-toss/web-bridge';\nconst ANALYTICS_ID = '@apps-in-toss/web-analytics';\n\n/** MCP state endpoint path — browser panel POSTs here, MCP server GETs here */\nconst MCP_STATE_PATH = '/api/ait-devtools/state';\n\nconst aitDevtoolsPlugin = createUnplugin((options?: AitDevtoolsOptions) => {\n const isDev = process.env.NODE_ENV !== 'production';\n const shouldEnable = isDev || (options?.forceEnable ?? false);\n const shouldMock = shouldEnable && (options?.mock ?? isDev);\n const shouldPanel = shouldEnable && (options?.panel ?? true);\n const shouldMcp = shouldEnable && (options?.mcp ?? false);\n\n // In-memory store for the last state snapshot pushed by the browser panel.\n // Only allocated when mcp: true to avoid any overhead in the common case.\n let lastState: string | null = null;\n\n // Tunnel is dev-only and Vite-only. Never under production — even with\n // forceEnable — so a production build can't accidentally expose itself.\n const tunnelOpt = options?.tunnel;\n const shouldTunnel = isDev && !!tunnelOpt;\n const tunnelConfig = typeof tunnelOpt === 'object' ? tunnelOpt : {};\n\n return {\n name: 'ait-co-devtools',\n enforce: 'pre' as const,\n\n resolveId(id: string) {\n if (!shouldMock) return null;\n // @apps-in-toss/web-framework → @ait-co/devtools/mock (absolute path)\n if (id === FRAMEWORK_ID || id === BRIDGE_ID || id === ANALYTICS_ID) {\n return MOCK_PATH;\n }\n return null;\n },\n\n transformInclude(id: string) {\n if (!shouldPanel) return false;\n // 진입점 파일에만 패널 import를 주입\n return (\n /\\.(tsx?|jsx?)$/.test(id) &&\n /\\/(main|index|entry|app)\\.[tj]sx?$/i.test(id) &&\n !id.includes('node_modules')\n );\n },\n\n transform(code: string) {\n // transformInclude가 이미 shouldPanel을 확인하지만, 안전망으로 유지\n if (!shouldPanel) return null;\n // 이미 패널이 import 되어있으면 스킵\n if (code.includes('@ait-co/devtools/panel')) return null;\n // transformInclude가 진입점 파일만 통과시키므로 바로 prepend\n return `import '@ait-co/devtools/panel';\\n${code}`;\n },\n\n // Vite-only: register the MCP state HTTP endpoint on the dev server, and\n // optionally start a Cloudflare quick tunnel once the dev server is listening.\n // Non-Vite bundlers do not have a dev server concept so this is silently\n // skipped (unplugin passes `vite` key only when building for Vite).\n vite: {\n config() {\n if (!shouldTunnel) return;\n // Vite blocks requests whose Host header isn't in `server.allowedHosts`\n // (defaults to localhost only). The quick-tunnel hostname is random per\n // run, so allow the whole `.trycloudflare.com` suffix while the tunnel\n // is on. (A leading `.` makes Vite match the domain and its subdomains.)\n return { server: { allowedHosts: ['.trycloudflare.com'] } };\n },\n\n configureServer(server: import('vite').ViteDevServer) {\n // MCP state endpoint: browser panel POSTs state here, MCP stdio server GETs it.\n if (shouldMcp) {\n server.middlewares.use(MCP_STATE_PATH, (req, res) => {\n // Allow Claude Code / AI agents (running locally) to read state\n res.setHeader('Access-Control-Allow-Origin', '*');\n res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');\n res.setHeader('Access-Control-Allow-Headers', 'Content-Type');\n\n if (req.method === 'OPTIONS') {\n res.writeHead(204);\n res.end();\n return;\n }\n\n if (req.method === 'GET') {\n if (lastState === null) {\n res.writeHead(503, { 'Content-Type': 'application/json' });\n res.end(\n JSON.stringify({\n error: 'No state received yet. Open the app in a browser first.',\n }),\n );\n return;\n }\n res.writeHead(200, { 'Content-Type': 'application/json' });\n res.end(lastState);\n return;\n }\n\n if (req.method === 'POST') {\n const chunks: Buffer[] = [];\n req.on('data', (chunk: Buffer) => chunks.push(chunk));\n req.on('end', () => {\n try {\n const body = Buffer.concat(chunks).toString('utf-8');\n // Validate it's parseable JSON before caching\n JSON.parse(body);\n lastState = body;\n res.writeHead(204);\n res.end();\n } catch {\n res.writeHead(400, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: 'Invalid JSON' }));\n }\n });\n return;\n }\n\n res.writeHead(405, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: 'Method not allowed' }));\n });\n }\n\n // Tunnel: start a Cloudflare quick tunnel once the dev server is listening.\n if (shouldTunnel) {\n let tunnel: { stop: () => void } | null = null;\n const httpServer = server.httpServer;\n\n httpServer?.once('listening', () => {\n const address = httpServer?.address();\n const port =\n tunnelConfig.port ??\n (address && typeof address === 'object' ? address.port : undefined);\n if (!port) {\n console.warn(\n '[@ait-co/devtools] tunnel: could not determine the dev server port; skipping.',\n );\n return;\n }\n // Dynamic import keeps `cloudflared` / `qrcode-terminal` off the\n // module graph unless the tunnel is actually used.\n import('./tunnel.js')\n .then(async ({ startQuickTunnel, printTunnelBanner }) => {\n const t = await startQuickTunnel(port);\n tunnel = t;\n await printTunnelBanner(t.url, { qr: tunnelConfig.qr });\n })\n .catch((err: unknown) => {\n console.warn(\n `[@ait-co/devtools] tunnel failed to start: ${\n err instanceof Error ? err.message : String(err)\n }`,\n );\n });\n });\n\n const cleanup = () => tunnel?.stop();\n httpServer?.once('close', cleanup);\n process.once('SIGINT', cleanup);\n process.once('SIGTERM', cleanup);\n process.once('exit', cleanup);\n }\n },\n },\n };\n});\n\nexport const vite = aitDevtoolsPlugin.vite;\nexport const webpack = aitDevtoolsPlugin.webpack;\nexport const rollup = aitDevtoolsPlugin.rollup;\nexport const esbuild = aitDevtoolsPlugin.esbuild;\nexport const rspack = aitDevtoolsPlugin.rspack;\n\nexport default aitDevtoolsPlugin;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","names":[],"sources":["../../src/unplugin/index.ts"],"sourcesContent":["/**\n * @ait-co/devtools unplugin\n *\n * 모든 주요 번들러를 지원하는 단일 플러그인.\n * @apps-in-toss/web-framework → @ait-co/devtools/mock 으로 alias 설정.\n *\n * Usage:\n * import aitDevtools from '@ait-co/devtools/unplugin';\n *\n * // Vite\n * export default { plugins: [aitDevtools.vite()] };\n *\n * // Webpack / Next.js\n * config.plugins.push(aitDevtools.webpack());\n *\n * // Rspack\n * config.plugins.push(aitDevtools.rspack());\n *\n * // esbuild\n * { plugins: [aitDevtools.esbuild()] }\n *\n * // Rollup\n * { plugins: [aitDevtools.rollup()] }\n */\n\nimport { fileURLToPath } from 'node:url';\nimport { createUnplugin } from 'unplugin';\n\n/**\n * Resolve `@ait-co/devtools/mock` to its real file path at plugin-load time.\n *\n * Returning the bare specifier from `resolveId` would stop the bundler from\n * walking node_modules for it — Vite 8+ treats such a non-null string as the\n * final resolved id and serves it via the virtual `/@id/` prefix, which 404s\n * because we don't provide a `load` hook. Resolving to an absolute path here\n * lets every supported bundler load the file the normal way.\n */\nconst MOCK_PATH = (() => {\n try {\n return fileURLToPath(import.meta.resolve('@ait-co/devtools/mock'));\n } catch {\n // Fallback for runtimes where `import.meta.resolve` is unavailable.\n return '@ait-co/devtools/mock';\n }\n})();\n\nexport interface AitDevtoolsOptions {\n /**\n * 패널 자동 주입 여부 (default: true)\n * true이면 진입점에 floating panel import를 자동 추가한다.\n */\n panel?: boolean;\n /**\n * production 환경에서도 devtools를 강제로 활성화 (default: false)\n */\n forceEnable?: boolean;\n /**\n * mock alias 활성화 여부. default: true (development), false (production + forceEnable)\n */\n mock?: boolean;\n /**\n * Vite dev server에 MCP state endpoint를 추가할지 여부 (default: false).\n *\n * `true`로 설정하면:\n * - GET /api/ait-devtools/state — 마지막으로 브라우저가 push한 mock state 스냅샷 반환\n * - POST /api/ait-devtools/state — 브라우저 panel이 상태 변경 시 자동 push (panel 내부 처리)\n *\n * 이 endpoint를 `@ait-co/devtools` MCP stdio server가 읽어 AI 에이전트에 mock state를 노출한다.\n * Vite 전용: webpack/rspack/esbuild/rollup 환경에서는 무시된다.\n */\n mcp?: boolean;\n /**\n * Vite dev 서버를 Cloudflare quick tunnel(`*.trycloudflare.com`, 계정 불필요)로\n * 외부 노출해 실제 폰에서 미리보기. **Vite dev 모드 전용** — production은\n * `forceEnable`이어도 터널을 띄우지 않는다 (의도치 않은 노출 방지). 다른 번들러는\n * 무시. `true`면 기본 동작, 객체로 세부 설정 가능.\n */\n tunnel?:\n | boolean\n | {\n /** 노출할 포트 (미지정 시 dev 서버가 실제 listen한 포트 자동 감지). */\n port?: number;\n /** 터미널 ASCII QR 출력 (default: true). */\n qr?: boolean;\n };\n}\n\nconst FRAMEWORK_ID = '@apps-in-toss/web-framework';\nconst BRIDGE_ID = '@apps-in-toss/web-bridge'; // back-compat (2.x)\nconst ANALYTICS_ID = '@apps-in-toss/web-analytics'; // back-compat (2.x)\nconst WEBVIEW_BRIDGE_ID = '@apps-in-toss/webview-bridge'; // 3.0+\n\n/** MCP state endpoint path — browser panel POSTs here, MCP server GETs here */\nconst MCP_STATE_PATH = '/api/ait-devtools/state';\n\nconst aitDevtoolsPlugin = createUnplugin((options?: AitDevtoolsOptions) => {\n const isDev = process.env.NODE_ENV !== 'production';\n const shouldEnable = isDev || (options?.forceEnable ?? false);\n const shouldMock = shouldEnable && (options?.mock ?? isDev);\n const shouldPanel = shouldEnable && (options?.panel ?? true);\n const shouldMcp = shouldEnable && (options?.mcp ?? false);\n\n // In-memory store for the last state snapshot pushed by the browser panel.\n // Only allocated when mcp: true to avoid any overhead in the common case.\n let lastState: string | null = null;\n\n // Tunnel is dev-only and Vite-only. Never under production — even with\n // forceEnable — so a production build can't accidentally expose itself.\n const tunnelOpt = options?.tunnel;\n const shouldTunnel = isDev && !!tunnelOpt;\n const tunnelConfig = typeof tunnelOpt === 'object' ? tunnelOpt : {};\n\n return {\n name: 'ait-co-devtools',\n enforce: 'pre' as const,\n\n resolveId(id: string) {\n if (!shouldMock) return null;\n // @apps-in-toss/web-framework → @ait-co/devtools/mock (absolute path)\n if (\n id === FRAMEWORK_ID ||\n id === WEBVIEW_BRIDGE_ID ||\n id === BRIDGE_ID ||\n id === ANALYTICS_ID\n ) {\n return MOCK_PATH;\n }\n return null;\n },\n\n transformInclude(id: string) {\n if (!shouldPanel) return false;\n // 진입점 파일에만 패널 import를 주입\n return (\n /\\.(tsx?|jsx?)$/.test(id) &&\n /\\/(main|index|entry|app)\\.[tj]sx?$/i.test(id) &&\n !id.includes('node_modules')\n );\n },\n\n transform(code: string) {\n // transformInclude가 이미 shouldPanel을 확인하지만, 안전망으로 유지\n if (!shouldPanel) return null;\n // 이미 패널이 import 되어있으면 스킵\n if (code.includes('@ait-co/devtools/panel')) return null;\n // transformInclude가 진입점 파일만 통과시키므로 바로 prepend\n return `import '@ait-co/devtools/panel';\\n${code}`;\n },\n\n // Vite-only: register the MCP state HTTP endpoint on the dev server, and\n // optionally start a Cloudflare quick tunnel once the dev server is listening.\n // Non-Vite bundlers do not have a dev server concept so this is silently\n // skipped (unplugin passes `vite` key only when building for Vite).\n vite: {\n config() {\n if (!shouldTunnel) return;\n // Vite blocks requests whose Host header isn't in `server.allowedHosts`\n // (defaults to localhost only). The quick-tunnel hostname is random per\n // run, so allow the whole `.trycloudflare.com` suffix while the tunnel\n // is on. (A leading `.` makes Vite match the domain and its subdomains.)\n return { server: { allowedHosts: ['.trycloudflare.com'] } };\n },\n\n configureServer(server: import('vite').ViteDevServer) {\n // MCP state endpoint: browser panel POSTs state here, MCP stdio server GETs it.\n if (shouldMcp) {\n server.middlewares.use(MCP_STATE_PATH, (req, res) => {\n // Allow Claude Code / AI agents (running locally) to read state\n res.setHeader('Access-Control-Allow-Origin', '*');\n res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');\n res.setHeader('Access-Control-Allow-Headers', 'Content-Type');\n\n if (req.method === 'OPTIONS') {\n res.writeHead(204);\n res.end();\n return;\n }\n\n if (req.method === 'GET') {\n if (lastState === null) {\n res.writeHead(503, { 'Content-Type': 'application/json' });\n res.end(\n JSON.stringify({\n error: 'No state received yet. Open the app in a browser first.',\n }),\n );\n return;\n }\n res.writeHead(200, { 'Content-Type': 'application/json' });\n res.end(lastState);\n return;\n }\n\n if (req.method === 'POST') {\n const chunks: Buffer[] = [];\n req.on('data', (chunk: Buffer) => chunks.push(chunk));\n req.on('end', () => {\n try {\n const body = Buffer.concat(chunks).toString('utf-8');\n // Validate it's parseable JSON before caching\n JSON.parse(body);\n lastState = body;\n res.writeHead(204);\n res.end();\n } catch {\n res.writeHead(400, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: 'Invalid JSON' }));\n }\n });\n return;\n }\n\n res.writeHead(405, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: 'Method not allowed' }));\n });\n }\n\n // Tunnel: start a Cloudflare quick tunnel once the dev server is listening.\n if (shouldTunnel) {\n let tunnel: { stop: () => void } | null = null;\n const httpServer = server.httpServer;\n\n httpServer?.once('listening', () => {\n const address = httpServer?.address();\n const port =\n tunnelConfig.port ??\n (address && typeof address === 'object' ? address.port : undefined);\n if (!port) {\n console.warn(\n '[@ait-co/devtools] tunnel: could not determine the dev server port; skipping.',\n );\n return;\n }\n // Dynamic import keeps `cloudflared` / `qrcode-terminal` off the\n // module graph unless the tunnel is actually used.\n import('./tunnel.js')\n .then(async ({ startQuickTunnel, printTunnelBanner }) => {\n const t = await startQuickTunnel(port);\n tunnel = t;\n await printTunnelBanner(t.url, { qr: tunnelConfig.qr });\n })\n .catch((err: unknown) => {\n console.warn(\n `[@ait-co/devtools] tunnel failed to start: ${\n err instanceof Error ? err.message : String(err)\n }`,\n );\n });\n });\n\n const cleanup = () => tunnel?.stop();\n httpServer?.once('close', cleanup);\n process.once('SIGINT', cleanup);\n process.once('SIGTERM', cleanup);\n process.once('exit', cleanup);\n }\n },\n },\n };\n});\n\nexport const vite = aitDevtoolsPlugin.vite;\nexport const webpack = aitDevtoolsPlugin.webpack;\nexport const rollup = aitDevtoolsPlugin.rollup;\nexport const esbuild = aitDevtoolsPlugin.esbuild;\nexport const rspack = aitDevtoolsPlugin.rspack;\n\nexport default aitDevtoolsPlugin;\n"],"mappings":"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"}
|
|
@@ -16,7 +16,7 @@ import SassEmbedded from "sass-embedded";
|
|
|
16
16
|
import Less from "less";
|
|
17
17
|
import Stylus from "stylus";
|
|
18
18
|
|
|
19
|
-
//#region node_modules/.pnpm/vite@8.0.8_@types+node@25.6.0_esbuild@0.27.7_jiti@
|
|
19
|
+
//#region node_modules/.pnpm/vite@8.0.8_@types+node@25.6.0_esbuild@0.27.7_jiti@2.6.1_terser@5.46.1_tsx@4.21.0_yaml@2.8.3/node_modules/vite/types/hmrPayload.d.ts
|
|
20
20
|
type HotPayload = ConnectedPayload | PingPayload | UpdatePayload | FullReloadPayload | CustomPayload | ErrorPayload | PrunePayload;
|
|
21
21
|
interface ConnectedPayload {
|
|
22
22
|
type: 'connected';
|
|
@@ -81,7 +81,7 @@ interface ErrorPayload {
|
|
|
81
81
|
};
|
|
82
82
|
}
|
|
83
83
|
//#endregion
|
|
84
|
-
//#region node_modules/.pnpm/vite@8.0.8_@types+node@25.6.0_esbuild@0.27.7_jiti@
|
|
84
|
+
//#region node_modules/.pnpm/vite@8.0.8_@types+node@25.6.0_esbuild@0.27.7_jiti@2.6.1_terser@5.46.1_tsx@4.21.0_yaml@2.8.3/node_modules/vite/dist/node/chunks/moduleRunnerTransport.d.ts
|
|
85
85
|
//#region src/shared/invokeMethods.d.ts
|
|
86
86
|
interface FetchFunctionOptions {
|
|
87
87
|
cached?: boolean;
|
|
@@ -134,7 +134,7 @@ interface ViteFetchResult {
|
|
|
134
134
|
invalidate: boolean;
|
|
135
135
|
}
|
|
136
136
|
//#endregion
|
|
137
|
-
//#region node_modules/.pnpm/vite@8.0.8_@types+node@25.6.0_esbuild@0.27.7_jiti@
|
|
137
|
+
//#region node_modules/.pnpm/vite@8.0.8_@types+node@25.6.0_esbuild@0.27.7_jiti@2.6.1_terser@5.46.1_tsx@4.21.0_yaml@2.8.3/node_modules/vite/types/customEvent.d.ts
|
|
138
138
|
interface CustomEventMap {
|
|
139
139
|
// client events
|
|
140
140
|
'vite:beforeUpdate': UpdatePayload;
|
|
@@ -6202,13 +6202,13 @@ declare global {
|
|
|
6202
6202
|
interface URL {}
|
|
6203
6203
|
}
|
|
6204
6204
|
//#endregion
|
|
6205
|
-
//#region node_modules/.pnpm/vite@8.0.8_@types+node@25.6.0_esbuild@0.27.7_jiti@
|
|
6205
|
+
//#region node_modules/.pnpm/vite@8.0.8_@types+node@25.6.0_esbuild@0.27.7_jiti@2.6.1_terser@5.46.1_tsx@4.21.0_yaml@2.8.3/node_modules/vite/types/internal/esbuildOptions.d.ts
|
|
6206
6206
|
/* eslint-enable @typescript-eslint/ban-ts-comment */
|
|
6207
6207
|
type EsbuildTarget = string | string[];
|
|
6208
6208
|
type EsbuildTransformOptions = esbuild$1.TransformOptions;
|
|
6209
6209
|
type DepsOptimizerEsbuildOptions = Omit<esbuild$1.BuildOptions, 'bundle' | 'entryPoints' | 'external' | 'write' | 'watch' | 'outdir' | 'outfile' | 'outbase' | 'outExtension' | 'metafile'>;
|
|
6210
6210
|
//#endregion
|
|
6211
|
-
//#region node_modules/.pnpm/vite@8.0.8_@types+node@25.6.0_esbuild@0.27.7_jiti@
|
|
6211
|
+
//#region node_modules/.pnpm/vite@8.0.8_@types+node@25.6.0_esbuild@0.27.7_jiti@2.6.1_terser@5.46.1_tsx@4.21.0_yaml@2.8.3/node_modules/vite/types/metadata.d.ts
|
|
6212
6212
|
interface AssetMetadata {
|
|
6213
6213
|
importedAssets: Set<string>;
|
|
6214
6214
|
importedCss: Set<string>;
|
|
@@ -6526,16 +6526,16 @@ interface SourceMapOptions$1 {
|
|
|
6526
6526
|
url?: string | 'inline';
|
|
6527
6527
|
}
|
|
6528
6528
|
//#endregion
|
|
6529
|
-
//#region node_modules/.pnpm/vite@8.0.8_@types+node@25.6.0_esbuild@0.27.7_jiti@
|
|
6529
|
+
//#region node_modules/.pnpm/vite@8.0.8_@types+node@25.6.0_esbuild@0.27.7_jiti@2.6.1_terser@5.46.1_tsx@4.21.0_yaml@2.8.3/node_modules/vite/types/internal/terserOptions.d.ts
|
|
6530
6530
|
/* eslint-enable @typescript-eslint/ban-ts-comment */
|
|
6531
6531
|
type TerserMinifyOptions = MinifyOptions;
|
|
6532
6532
|
//#endregion
|
|
6533
|
-
//#region node_modules/.pnpm/vite@8.0.8_@types+node@25.6.0_esbuild@0.27.7_jiti@
|
|
6533
|
+
//#region node_modules/.pnpm/vite@8.0.8_@types+node@25.6.0_esbuild@0.27.7_jiti@2.6.1_terser@5.46.1_tsx@4.21.0_yaml@2.8.3/node_modules/vite/types/internal/lightningcssOptions.d.ts
|
|
6534
6534
|
/* eslint-enable @typescript-eslint/ban-ts-comment */
|
|
6535
6535
|
type LightningCSSOptions = Omit<Lightningcss.BundleAsyncOptions<Lightningcss.CustomAtRules>, 'filename' | 'resolver' | 'minify' | 'sourceMap' | 'analyzeDependencies' // properties not overridden by Vite, but does not make sense to set by end users
|
|
6536
6536
|
| 'inputSourceMap' | 'projectRoot'>;
|
|
6537
6537
|
//#endregion
|
|
6538
|
-
//#region node_modules/.pnpm/vite@8.0.8_@types+node@25.6.0_esbuild@0.27.7_jiti@
|
|
6538
|
+
//#region node_modules/.pnpm/vite@8.0.8_@types+node@25.6.0_esbuild@0.27.7_jiti@2.6.1_terser@5.46.1_tsx@4.21.0_yaml@2.8.3/node_modules/vite/types/internal/cssPreprocessorOptions.d.ts
|
|
6539
6539
|
/* eslint-enable @typescript-eslint/ban-ts-comment */
|
|
6540
6540
|
// https://github.com/type-challenges/type-challenges/issues/29285
|
|
6541
6541
|
type IsAny<T> = boolean extends (T extends never ? true : false) ? true : false;
|
|
@@ -6554,7 +6554,7 @@ declare global {
|
|
|
6554
6554
|
interface HTMLLinkElement {}
|
|
6555
6555
|
}
|
|
6556
6556
|
//#endregion
|
|
6557
|
-
//#region node_modules/.pnpm/vite@8.0.8_@types+node@25.6.0_esbuild@0.27.7_jiti@
|
|
6557
|
+
//#region node_modules/.pnpm/vite@8.0.8_@types+node@25.6.0_esbuild@0.27.7_jiti@2.6.1_terser@5.46.1_tsx@4.21.0_yaml@2.8.3/node_modules/vite/types/importGlob.d.ts
|
|
6558
6558
|
/**
|
|
6559
6559
|
* Declare Worker in case DOM is not added to the tsconfig lib causing
|
|
6560
6560
|
* Worker interface is not defined. For developers with DOM lib added,
|
|
@@ -6565,7 +6565,7 @@ declare global {
|
|
|
6565
6565
|
interface Worker {}
|
|
6566
6566
|
}
|
|
6567
6567
|
//#endregion
|
|
6568
|
-
//#region node_modules/.pnpm/vite@8.0.8_@types+node@25.6.0_esbuild@0.27.7_jiti@
|
|
6568
|
+
//#region node_modules/.pnpm/vite@8.0.8_@types+node@25.6.0_esbuild@0.27.7_jiti@2.6.1_terser@5.46.1_tsx@4.21.0_yaml@2.8.3/node_modules/vite/dist/node/index.d.ts
|
|
6569
6569
|
//#region \0rolldown/runtime.js
|
|
6570
6570
|
//#endregion
|
|
6571
6571
|
//#region ../../node_modules/.pnpm/@vitejs+devtools@0.1.13_typescript@6.0.2_vite@packages+vite/node_modules/@vitejs/devtools/dist/cli-commands.d.ts
|
|
@@ -10142,7 +10142,7 @@ interface AitDevtoolsOptions {
|
|
|
10142
10142
|
declare const aitDevtoolsPlugin: _$unplugin.UnpluginInstance<AitDevtoolsOptions | undefined, boolean>;
|
|
10143
10143
|
declare const vite: (options?: AitDevtoolsOptions | undefined) => Plugin<any> | Plugin<any>[];
|
|
10144
10144
|
declare const webpack: (options?: AitDevtoolsOptions | undefined) => WebpackPluginInstance;
|
|
10145
|
-
declare const rollup: (options?: AitDevtoolsOptions | undefined) =>
|
|
10145
|
+
declare const rollup: (options?: AitDevtoolsOptions | undefined) => any;
|
|
10146
10146
|
declare const esbuild: (options?: AitDevtoolsOptions | undefined) => _$unplugin.EsbuildPlugin;
|
|
10147
10147
|
declare const rspack: (options?: AitDevtoolsOptions | undefined) => RspackPluginInstance;
|
|
10148
10148
|
//#endregion
|