@pyreon/vite-plugin 0.4.0 → 0.5.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.
@@ -5386,7 +5386,7 @@ var drawChart = (function (exports) {
5386
5386
  </script>
5387
5387
  <script>
5388
5388
  /*<!--*/
5389
- const data = {"version":2,"tree":{"name":"root","children":[{"name":"index.js","children":[{"name":"src/index.ts","uid":"1cff14ac-1"}]}],"isRoot":true},"nodeParts":{"1cff14ac-1":{"renderedLength":11698,"gzipLength":4255,"brotliLength":0,"metaUid":"1cff14ac-0"}},"nodeMetas":{"1cff14ac-0":{"id":"/src/index.ts","moduleParts":{"index.js":"1cff14ac-1"},"imported":[{"uid":"1cff14ac-2"},{"uid":"1cff14ac-3"},{"uid":"1cff14ac-4"}],"importedBy":[],"isEntry":true},"1cff14ac-2":{"id":"node:fs","moduleParts":{},"imported":[],"importedBy":[{"uid":"1cff14ac-0"}]},"1cff14ac-3":{"id":"node:path","moduleParts":{},"imported":[],"importedBy":[{"uid":"1cff14ac-0"}]},"1cff14ac-4":{"id":"@pyreon/compiler","moduleParts":{},"imported":[],"importedBy":[{"uid":"1cff14ac-0"}]}},"env":{"rollup":"4.23.0"},"options":{"gzip":true,"brotli":false,"sourcemap":false}};
5389
+ const data = {"version":2,"tree":{"name":"root","children":[{"name":"index.js","children":[{"name":"src/index.ts","uid":"918e04ec-1"}]}],"isRoot":true},"nodeParts":{"918e04ec-1":{"renderedLength":15543,"gzipLength":5566,"brotliLength":0,"metaUid":"918e04ec-0"}},"nodeMetas":{"918e04ec-0":{"id":"/src/index.ts","moduleParts":{"index.js":"918e04ec-1"},"imported":[{"uid":"918e04ec-2"},{"uid":"918e04ec-3"},{"uid":"918e04ec-4"}],"importedBy":[],"isEntry":true},"918e04ec-2":{"id":"node:fs","moduleParts":{},"imported":[],"importedBy":[{"uid":"918e04ec-0"}]},"918e04ec-3":{"id":"node:path","moduleParts":{},"imported":[],"importedBy":[{"uid":"918e04ec-0"}]},"918e04ec-4":{"id":"@pyreon/compiler","moduleParts":{},"imported":[],"importedBy":[{"uid":"918e04ec-0"}]}},"env":{"rollup":"4.23.0"},"options":{"gzip":true,"brotli":false,"sourcemap":false}};
5390
5390
 
5391
5391
  const run = () => {
5392
5392
  const width = window.innerWidth;
package/lib/index.js CHANGED
@@ -1,5 +1,5 @@
1
- import { readFileSync } from "node:fs";
2
- import { resolve } from "node:path";
1
+ import { existsSync, lstatSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from "node:fs";
2
+ import { extname, join, relative, resolve } from "node:path";
3
3
  import { transformJSX } from "@pyreon/compiler";
4
4
 
5
5
  //#region src/index.ts
@@ -162,6 +162,14 @@ function pyreonPlugin(options) {
162
162
  };
163
163
  },
164
164
  configureServer(server) {
165
+ generateProjectContext(projectRoot);
166
+ let contextTimer = null;
167
+ server.watcher.on("change", (file) => {
168
+ if (/\.(tsx|jsx|ts|js)$/.test(file) && !file.includes("node_modules")) {
169
+ if (contextTimer) clearTimeout(contextTimer);
170
+ contextTimer = setTimeout(() => generateProjectContext(projectRoot), 500);
171
+ }
172
+ });
165
173
  if (!ssrConfig) return;
166
174
  return () => {
167
175
  server.middlewares.use(async (req, res, next) => {
@@ -204,6 +212,122 @@ async function handleSsrRequest(server, entry, url, req, res, next) {
204
212
  res.end(html);
205
213
  }
206
214
  /**
215
+ * Generate .pyreon/context.json — project map for AI coding assistants.
216
+ * Extracts routes, components (with props/signals), and island declarations.
217
+ */
218
+ function generateProjectContext(root) {
219
+ try {
220
+ const srcDir = resolve(root, "src");
221
+ if (!existsSync(srcDir)) return;
222
+ const files = collectTsxFiles(srcDir);
223
+ const routes = [];
224
+ const components = [];
225
+ const islands = [];
226
+ for (const file of files) {
227
+ let code;
228
+ try {
229
+ code = readFileSync(file, "utf-8");
230
+ } catch {
231
+ continue;
232
+ }
233
+ const relFile = relative(root, file);
234
+ const routeRe = /path\s*:\s*["']([^"']+)["']/g;
235
+ let m;
236
+ for (m = routeRe.exec(code); m; m = routeRe.exec(code)) {
237
+ const routePath = m[1] ?? "";
238
+ const ctx = code.slice(Math.max(0, m.index - 50), Math.min(code.length, m.index + 200));
239
+ routes.push({
240
+ path: routePath,
241
+ name: ctx.match(/name\s*:\s*["']([^"']+)["']/)?.[1],
242
+ hasLoader: /loader\s*:/.test(ctx),
243
+ params: [...routePath.matchAll(/:(\w+)\??/g)].map((p) => p[1] ?? "")
244
+ });
245
+ }
246
+ const compRe = /(?:export\s+)?(?:const|function)\s+([A-Z]\w*)\s*(?::\s*\w+<[^>]*>\s*)?=?\s*\(?\s*\{?\s*([^)]*?)\s*\}?\s*\)?\s*(?:=>|{)/g;
247
+ for (m = compRe.exec(code); m; m = compRe.exec(code)) {
248
+ const name = m[1] ?? "Unknown";
249
+ const props = (m[2] ?? "").split(",").map((p) => p.trim().split(":")[0]?.split("=")[0]?.trim() ?? "").filter((p) => p && p !== "props" && !p.startsWith("{"));
250
+ const body = code.slice(m.index + m[0].length, Math.min(code.length, m.index + m[0].length + 2e3));
251
+ const signals = [];
252
+ const sigRe = /(?:const|let)\s+(\w+)\s*=\s*signal\s*[<(]/g;
253
+ let sm;
254
+ for (sm = sigRe.exec(body); sm; sm = sigRe.exec(body)) if (sm[1]) signals.push(sm[1]);
255
+ components.push({
256
+ name,
257
+ file: relFile,
258
+ signals,
259
+ props
260
+ });
261
+ }
262
+ const islandRe = /island\s*\([^,]+,\s*\{[^}]*name\s*:\s*["']([^"']+)["'][^}]*?(?:hydrate\s*:\s*["']([^"']+)["'])?[^}]*\}/g;
263
+ for (m = islandRe.exec(code); m; m = islandRe.exec(code)) if (m[1]) islands.push({
264
+ name: m[1],
265
+ file: relFile,
266
+ hydrate: m[2] ?? "load"
267
+ });
268
+ }
269
+ const context = {
270
+ framework: "pyreon",
271
+ version: readProjectVersion(root),
272
+ generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
273
+ routes,
274
+ components,
275
+ islands
276
+ };
277
+ const outDir = join(root, ".pyreon");
278
+ if (!existsSync(outDir)) mkdirSync(outDir, { recursive: true });
279
+ writeFileSync(join(outDir, "context.json"), JSON.stringify(context, null, 2), "utf-8");
280
+ } catch {}
281
+ }
282
+ function collectTsxFiles(dir) {
283
+ const results = [];
284
+ const exts = new Set([
285
+ ".tsx",
286
+ ".jsx",
287
+ ".ts",
288
+ ".js"
289
+ ]);
290
+ const skip = new Set([
291
+ "node_modules",
292
+ "dist",
293
+ "lib",
294
+ ".pyreon",
295
+ ".git"
296
+ ]);
297
+ function walk(d) {
298
+ let entries;
299
+ try {
300
+ entries = readdirSync(d);
301
+ } catch {
302
+ return;
303
+ }
304
+ for (const name of entries) {
305
+ if (skip.has(name)) continue;
306
+ const full = join(d, name);
307
+ try {
308
+ const stat = lstatSync(full);
309
+ if (stat.isDirectory()) walk(full);
310
+ else if (stat.isFile() && exts.has(extname(name))) results.push(full);
311
+ } catch {}
312
+ }
313
+ }
314
+ walk(dir);
315
+ return results;
316
+ }
317
+ function readProjectVersion(root) {
318
+ try {
319
+ const pkg = JSON.parse(readFileSync(join(root, "package.json"), "utf-8"));
320
+ const deps = {
321
+ ...pkg.dependencies,
322
+ ...pkg.devDependencies
323
+ };
324
+ for (const [name, ver] of Object.entries(deps)) if (name.startsWith("@pyreon/") && typeof ver === "string") return ver.replace(/^[\^~]/, "");
325
+ return pkg.version || "unknown";
326
+ } catch {
327
+ return "unknown";
328
+ }
329
+ }
330
+ /**
207
331
  * Regex that detects signal declarations (prefix + variable name).
208
332
  * The arguments are extracted via balanced-paren matching in `injectHmr`.
209
333
  * A brace-depth check filters out matches inside functions/blocks — only
package/lib/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["pathResolve"],"sources":["../src/index.ts"],"sourcesContent":["/**\n * @pyreon/vite-plugin — Vite integration for Pyreon framework.\n *\n * Applies Pyreon's JSX reactive transform to .tsx, .jsx, and .pyreon files,\n * and configures Vite to use Pyreon's JSX runtime.\n *\n * ## Basic usage (SPA)\n *\n * import pyreon from \"@pyreon/vite-plugin\"\n * export default { plugins: [pyreon()] }\n *\n * ## Drop-in compat mode (zero code changes)\n *\n * import pyreon from \"@pyreon/vite-plugin\"\n * export default { plugins: [pyreon({ compat: \"react\" })] }\n *\n * Aliases `react`, `react-dom`, `vue`, `solid-js`, or `preact` imports to\n * Pyreon's compat packages — existing code works without changing imports.\n *\n * ## SSR mode\n *\n * import pyreon from \"@pyreon/vite-plugin\"\n * export default { plugins: [pyreon({ ssr: { entry: \"./src/entry-server.ts\" } })] }\n *\n * In SSR mode, the plugin adds dev server middleware that:\n * 1. Loads your server entry via Vite's `ssrLoadModule`\n * 2. Calls the exported `handler` or default export (Request → Response)\n * 3. Returns the SSR'd HTML for every non-asset request\n *\n * For production, build separately:\n * vite build # client bundle\n * vite build --ssr src/entry-server.ts --outDir dist/server # server bundle\n */\n\nimport { readFileSync } from \"node:fs\"\nimport { resolve as pathResolve } from \"node:path\"\nimport { transformJSX } from \"@pyreon/compiler\"\nimport type { Plugin, ViteDevServer } from \"vite\"\n\n// Virtual module ID for the HMR runtime\nconst HMR_RUNTIME_ID = \"\\0pyreon/hmr-runtime\"\nconst HMR_RUNTIME_IMPORT = \"virtual:pyreon/hmr-runtime\"\n\nexport type CompatFramework = \"react\" | \"preact\" | \"vue\" | \"solid\"\n\nexport interface PyreonPluginOptions {\n /**\n * Alias imports from an existing framework to Pyreon's compat layer.\n *\n * This lets you drop Pyreon into an existing project with zero code changes —\n * `import { useState } from \"react\"` will resolve to `@pyreon/react-compat`.\n *\n * @example\n * pyreon({ compat: \"react\" }) // react + react-dom → @pyreon/react-compat\n * pyreon({ compat: \"vue\" }) // vue → @pyreon/vue-compat\n * pyreon({ compat: \"solid\" }) // solid-js → @pyreon/solid-compat\n * pyreon({ compat: \"preact\" }) // preact + hooks + signals → @pyreon/preact-compat\n */\n compat?: CompatFramework\n\n /**\n * Enable SSR dev middleware.\n *\n * Pass an object with `entry` pointing to your server entry file.\n * The entry must export a `handler` function: `(req: Request) => Promise<Response>`\n * or a default export of the same type.\n *\n * @example\n * pyreonPlugin({ ssr: { entry: \"./src/entry-server.ts\" } })\n */\n ssr?: {\n /** Server entry file path (e.g. \"./src/entry-server.ts\") */\n entry: string\n }\n}\n\n// ── Compat JSX import sources ─────────────────────────────────────────────────\n\nconst COMPAT_JSX_SOURCE: Record<CompatFramework, string> = {\n react: \"@pyreon/react-compat\",\n preact: \"@pyreon/preact-compat\",\n vue: \"@pyreon/vue-compat\",\n solid: \"@pyreon/solid-compat\",\n}\n\n// ── Compat alias maps ─────────────────────────────────────────────────────────\n\nconst COMPAT_ALIASES: Record<CompatFramework, Record<string, string>> = {\n react: {\n react: \"@pyreon/react-compat\",\n \"react/jsx-runtime\": \"@pyreon/react-compat/jsx-runtime\",\n \"react/jsx-dev-runtime\": \"@pyreon/react-compat/jsx-runtime\",\n \"react-dom\": \"@pyreon/react-compat/dom\",\n \"react-dom/client\": \"@pyreon/react-compat/dom\",\n },\n preact: {\n preact: \"@pyreon/preact-compat\",\n \"preact/hooks\": \"@pyreon/preact-compat/hooks\",\n \"preact/jsx-runtime\": \"@pyreon/preact-compat/jsx-runtime\",\n \"preact/jsx-dev-runtime\": \"@pyreon/preact-compat/jsx-runtime\",\n \"@preact/signals\": \"@pyreon/preact-compat/signals\",\n },\n vue: {\n vue: \"@pyreon/vue-compat\",\n \"vue/jsx-runtime\": \"@pyreon/vue-compat/jsx-runtime\",\n \"vue/jsx-dev-runtime\": \"@pyreon/vue-compat/jsx-runtime\",\n },\n solid: {\n \"solid-js\": \"@pyreon/solid-compat\",\n \"solid-js/jsx-runtime\": \"@pyreon/solid-compat/jsx-runtime\",\n \"solid-js/jsx-dev-runtime\": \"@pyreon/solid-compat/jsx-runtime\",\n },\n}\n\n/**\n * Resolve a package specifier to an absolute source path, respecting the \"bun\"\n * export condition. Falls back to the \"import\" condition.\n *\n * This is needed because Vite 8's resolve pipeline doesn't consistently apply\n * custom conditions from `resolve.conditions` during the `vite:import-analysis`\n * phase for aliased workspace packages.\n */\nfunction resolveWithBunCondition(specifier: string, projectRoot: string): string | undefined {\n // Split specifier: \"@pyreon/react-compat/dom\" → pkg=\"@pyreon/react-compat\", subpath=\"./dom\"\n const parts = specifier.startsWith(\"@\")\n ? specifier.split(\"/\").slice(0, 2)\n : specifier.split(\"/\").slice(0, 1)\n const pkgName = parts.join(\"/\")\n const subpath = specifier.slice(pkgName.length) || \".\"\n const exportKey = subpath === \".\" ? \".\" : `.${subpath}`\n\n try {\n // Walk up from project root to find node_modules containing the package\n const pkgDir = pathResolve(projectRoot, \"node_modules\", pkgName)\n const pkgJsonPath = pathResolve(pkgDir, \"package.json\")\n const pkgJson = JSON.parse(readFileSync(pkgJsonPath, \"utf-8\")) as {\n exports?: Record<string, Record<string, string> | string>\n }\n\n const exp = pkgJson.exports?.[exportKey]\n if (!exp) return undefined\n\n if (typeof exp === \"string\") return pathResolve(pkgDir, exp)\n // Prefer bun → import → default\n const target = exp.bun ?? exp.import ?? exp.default\n return target ? pathResolve(pkgDir, target) : undefined\n } catch {\n return undefined\n }\n}\n\n/**\n * Return the Pyreon compat target for an import specifier, or undefined if\n * the import should not be redirected.\n */\nfunction getCompatTarget(compat: CompatFramework | undefined, id: string): string | undefined {\n if (!compat) return undefined\n const aliased = COMPAT_ALIASES[compat][id]\n if (aliased) return aliased\n // OXC's JSX transform reads jsxImportSource from tsconfig (@pyreon/core),\n // not from our plugin config. Redirect JSX runtime imports in compat mode.\n if (id === \"@pyreon/core/jsx-runtime\" || id === \"@pyreon/core/jsx-dev-runtime\") {\n if (compat === \"react\") return \"@pyreon/react-compat/jsx-runtime\"\n if (compat === \"preact\") return \"@pyreon/preact-compat/jsx-runtime\"\n if (compat === \"vue\") return \"@pyreon/vue-compat/jsx-runtime\"\n if (compat === \"solid\") return \"@pyreon/solid-compat/jsx-runtime\"\n }\n return undefined\n}\n\nexport default function pyreonPlugin(options?: PyreonPluginOptions): Plugin {\n const ssrConfig = options?.ssr\n const compat = options?.compat\n let isBuild = false\n let projectRoot = \"\"\n // Cache resolved absolute paths for compat aliases\n const resolvedAliases = new Map<string, string>()\n\n return {\n name: \"pyreon\",\n enforce: \"pre\",\n\n config(userConfig, env) {\n isBuild = env.command === \"build\"\n // Capture the project root for package resolution in resolveId\n projectRoot = userConfig.root ?? process.cwd()\n\n // Tell Vite's dep scanner not to pre-bundle the aliased framework imports —\n // they resolve to workspace packages via our resolveId hook, not node_modules.\n const optimizeDepsExclude = compat ? Object.keys(COMPAT_ALIASES[compat]) : []\n\n return {\n resolve: {\n conditions: [\"bun\"],\n },\n optimizeDeps: {\n exclude: optimizeDepsExclude,\n },\n oxc: {\n jsx: {\n runtime: \"automatic\",\n importSource: compat ? COMPAT_JSX_SOURCE[compat] : \"@pyreon/core\",\n },\n },\n // In SSR build mode, configure the entry\n ...(env.isSsrBuild && ssrConfig\n ? {\n build: {\n ssr: true,\n rollupOptions: {\n input: ssrConfig.entry,\n },\n },\n }\n : {}),\n }\n },\n\n // ── Virtual module + compat alias resolution ─────────────────────────────\n resolveId(id) {\n if (id === HMR_RUNTIME_IMPORT) return HMR_RUNTIME_ID\n const target = getCompatTarget(compat, id)\n if (!target) return\n\n // Use cached resolution or resolve with bun condition\n let resolved = resolvedAliases.get(target)\n if (!resolved) {\n resolved = resolveWithBunCondition(target, projectRoot)\n if (resolved) resolvedAliases.set(target, resolved)\n }\n return resolved\n },\n\n load(id) {\n if (id === HMR_RUNTIME_ID) {\n return HMR_RUNTIME_SOURCE\n }\n },\n\n transform(code, id) {\n const ext = getExt(id)\n if (ext !== \".tsx\" && ext !== \".jsx\" && ext !== \".pyreon\") return\n\n // In compat mode, skip Pyreon's reactive JSX transform.\n // OXC's built-in JSX transform handles jsx() calls; the compat\n // JSX runtime wraps components for re-render support.\n if (compat === \"react\" || compat === \"preact\" || compat === \"vue\" || compat === \"solid\")\n return\n\n const result = transformJSX(code, id)\n // Surface compiler warnings in the terminal\n for (const w of result.warnings) {\n this.warn(`${w.message} (${id}:${w.line}:${w.column})`)\n }\n\n let output = result.code\n\n // ── HMR injection (dev only) ────────────────────────────────────────\n if (!isBuild) {\n output = injectHmr(output, id)\n }\n\n return { code: output, map: null }\n },\n\n // ── SSR dev middleware ───────────────────────────────────────────────────\n configureServer(server: ViteDevServer) {\n if (!ssrConfig) return\n\n // Return a function so the middleware runs AFTER Vite's built-in middleware\n // (static files, HMR, etc.) — only handle requests that Vite doesn't serve.\n return () => {\n server.middlewares.use(async (req, res, next) => {\n if (req.method !== \"GET\") return next()\n const url = req.url ?? \"/\"\n if (isAssetRequest(url)) return next()\n\n try {\n await handleSsrRequest(server, ssrConfig.entry, url, req, res, next)\n } catch (err) {\n server.ssrFixStacktrace(err as Error)\n next(err)\n }\n })\n }\n },\n }\n}\n\nasync function handleSsrRequest(\n server: ViteDevServer,\n entry: string,\n url: string,\n req: import(\"node:http\").IncomingMessage,\n res: import(\"node:http\").ServerResponse,\n next: (err?: unknown) => void,\n): Promise<void> {\n const mod = await server.ssrLoadModule(entry)\n const handler = mod.handler ?? mod.default\n\n if (typeof handler !== \"function\") {\n next()\n return\n }\n\n const origin = `http://${req.headers.host ?? \"localhost\"}`\n const fullUrl = new URL(url, origin)\n const request = new Request(fullUrl.href, {\n method: req.method ?? \"GET\",\n headers: Object.entries(req.headers).reduce((h, [k, v]) => {\n if (v) h.set(k, Array.isArray(v) ? v.join(\", \") : v)\n return h\n }, new Headers()),\n })\n\n const response: Response = await handler(request)\n let html = await response.text()\n\n html = await server.transformIndexHtml(url, html)\n\n res.statusCode = response.status\n response.headers.forEach((v, k) => {\n res.setHeader(k, v)\n })\n res.end(html)\n}\n\n// ── HMR injection ─────────────────────────────────────────────────────────────\n\n/**\n * Regex that detects signal declarations (prefix + variable name).\n * The arguments are extracted via balanced-paren matching in `injectHmr`.\n * A brace-depth check filters out matches inside functions/blocks — only\n * module-scope (depth 0) signals are rewritten for HMR state preservation.\n */\nconst SIGNAL_PREFIX_RE = /^((?:export\\s+)?(?:const|let)\\s+(\\w+)\\s*=\\s*)signal\\(/gm\n\n/**\n * Detect whether the module exports any component-like functions\n * (uppercase first letter — standard convention for JSX components).\n */\nconst EXPORT_COMPONENT_RE =\n /export\\s+(?:default\\s+)?(?:function\\s+([A-Z]\\w*)|const\\s+([A-Z]\\w*)\\s*[=:])/\n\nfunction skipStringLiteral(code: string, start: number, quote: string): number {\n let j = start + 1\n while (j < code.length) {\n if (code[j] === \"\\\\\") {\n j += 2\n continue\n }\n if (code[j] === quote) break\n j++\n }\n return j\n}\n\nfunction extractBalancedArgs(code: string, start: number): string | null {\n let depth = 1\n for (let i = start; i < code.length; i++) {\n const ch = code[i]\n if (ch === \"(\") depth++\n else if (ch === \")\") {\n depth--\n if (depth === 0) return code.slice(start, i)\n } else if (ch === '\"' || ch === \"'\" || ch === \"`\") {\n i = skipStringLiteral(code, i, ch)\n }\n }\n return null\n}\n\n/**\n * Compute brace depth at position `pos` — returns 0 for module scope.\n * Skips string literals to avoid counting braces inside strings.\n */\nfunction braceDepthAt(code: string, pos: number): number {\n let depth = 0\n for (let i = 0; i < pos; i++) {\n const ch = code[i]\n if (ch === \"{\") depth++\n else if (ch === \"}\") depth--\n else if (ch === '\"' || ch === \"'\" || ch === \"`\") {\n i = skipStringLiteral(code, i, ch)\n }\n }\n return depth\n}\n\n/** Rewrite module-scope `signal()` calls to `__hmr_signal()` for state preservation. */\nfunction rewriteSignals(code: string, moduleId: string): string {\n const escapedId = JSON.stringify(moduleId)\n const matches: {\n start: number\n end: number\n prefix: string\n name: string\n args: string\n }[] = []\n let m: RegExpExecArray | null = SIGNAL_PREFIX_RE.exec(code)\n while (m !== null) {\n const argsStart = m.index + m[0].length\n const args = extractBalancedArgs(code, argsStart)\n if (args === null) {\n m = SIGNAL_PREFIX_RE.exec(code)\n continue // unbalanced — skip\n }\n // Only rewrite module-scope signals (brace depth 0).\n if (braceDepthAt(code, m.index) === 0) {\n matches.push({\n start: m.index,\n end: argsStart + args.length + 1, // +1 for closing paren\n prefix: m[1] ?? \"\",\n name: m[2] ?? \"\",\n args,\n })\n }\n m = SIGNAL_PREFIX_RE.exec(code)\n }\n SIGNAL_PREFIX_RE.lastIndex = 0\n\n // Replace in reverse to preserve offsets\n let output = code\n for (let i = matches.length - 1; i >= 0; i--) {\n const { start, end, prefix, name, args } = matches[i] as (typeof matches)[number]\n const replacement = `${prefix}__hmr_signal(${escapedId}, ${JSON.stringify(name)}, signal, ${args})`\n output = output.slice(0, start) + replacement + output.slice(end)\n }\n return output\n}\n\nfunction injectHmr(code: string, moduleId: string): string {\n const hasSignals = SIGNAL_PREFIX_RE.test(code)\n SIGNAL_PREFIX_RE.lastIndex = 0\n\n const hasComponentExport = EXPORT_COMPONENT_RE.test(code)\n\n // Only inject HMR if the module exports components or has module-scope signals\n if (!hasComponentExport && !hasSignals) return code\n\n let output = hasSignals ? rewriteSignals(code, moduleId) : code\n\n // Build the HMR footer\n const escapedId = JSON.stringify(moduleId)\n const lines: string[] = []\n\n if (hasSignals) {\n lines.push(`import { __hmr_signal, __hmr_dispose } from \"${HMR_RUNTIME_IMPORT}\";`)\n }\n\n lines.push(`if (import.meta.hot) {`)\n\n if (hasSignals) {\n lines.push(` import.meta.hot.dispose(() => __hmr_dispose(${escapedId}));`)\n }\n\n lines.push(` import.meta.hot.accept();`)\n lines.push(`}`)\n\n output = `${output}\\n\\n${lines.join(\"\\n\")}\\n`\n\n return output\n}\n\n// ── Helpers ───────────────────────────────────────────────────────────────────\n\nfunction getExt(id: string): string {\n const clean = id.split(\"?\")[0] ?? id\n const dot = clean.lastIndexOf(\".\")\n return dot >= 0 ? clean.slice(dot) : \"\"\n}\n\n/** Skip Vite-handled asset requests (CSS, images, HMR, etc.) */\nfunction isAssetRequest(url: string): boolean {\n return (\n url.startsWith(\"/@\") || // @vite/client, @id, @fs, etc.\n url.startsWith(\"/__\") || // __open-in-editor, etc.\n url.includes(\"/node_modules/\") ||\n /\\.(css|js|ts|tsx|jsx|json|ico|png|jpg|jpeg|gif|svg|woff2?|ttf|eot|map)(\\?|$)/.test(url)\n )\n}\n\n// ── HMR runtime source (served as virtual module) ─────────────────────────────\n//\n// Inlined here so it's available without a filesystem read. This is the\n// compiled-to-JS version of hmr-runtime.ts — kept in sync manually.\n\nconst HMR_RUNTIME_SOURCE = `\nconst REGISTRY_KEY = \"__pyreon_hmr_registry__\";\n\nfunction getRegistry() {\n if (!globalThis[REGISTRY_KEY]) {\n globalThis[REGISTRY_KEY] = new Map();\n }\n return globalThis[REGISTRY_KEY];\n}\n\nconst moduleSignals = new Map();\n\nexport function __hmr_signal(moduleId, name, signalFn, initialValue) {\n const registry = getRegistry();\n const saved = registry.get(moduleId);\n const value = saved?.has(name) ? saved.get(name) : initialValue;\n const s = signalFn(value);\n\n let mod = moduleSignals.get(moduleId);\n if (!mod) {\n mod = { entries: new Map() };\n moduleSignals.set(moduleId, mod);\n }\n mod.entries.set(name, s);\n\n return s;\n}\n\nexport function __hmr_dispose(moduleId) {\n const mod = moduleSignals.get(moduleId);\n if (!mod) return;\n\n const registry = getRegistry();\n const saved = new Map();\n for (const [name, s] of mod.entries) {\n saved.set(name, s.peek());\n }\n registry.set(moduleId, saved);\n moduleSignals.delete(moduleId);\n}\n`\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["pathResolve","pathJoin"],"sources":["../src/index.ts"],"sourcesContent":["/**\n * @pyreon/vite-plugin — Vite integration for Pyreon framework.\n *\n * Applies Pyreon's JSX reactive transform to .tsx, .jsx, and .pyreon files,\n * and configures Vite to use Pyreon's JSX runtime.\n *\n * ## Basic usage (SPA)\n *\n * import pyreon from \"@pyreon/vite-plugin\"\n * export default { plugins: [pyreon()] }\n *\n * ## Drop-in compat mode (zero code changes)\n *\n * import pyreon from \"@pyreon/vite-plugin\"\n * export default { plugins: [pyreon({ compat: \"react\" })] }\n *\n * Aliases `react`, `react-dom`, `vue`, `solid-js`, or `preact` imports to\n * Pyreon's compat packages — existing code works without changing imports.\n *\n * ## SSR mode\n *\n * import pyreon from \"@pyreon/vite-plugin\"\n * export default { plugins: [pyreon({ ssr: { entry: \"./src/entry-server.ts\" } })] }\n *\n * In SSR mode, the plugin adds dev server middleware that:\n * 1. Loads your server entry via Vite's `ssrLoadModule`\n * 2. Calls the exported `handler` or default export (Request → Response)\n * 3. Returns the SSR'd HTML for every non-asset request\n *\n * For production, build separately:\n * vite build # client bundle\n * vite build --ssr src/entry-server.ts --outDir dist/server # server bundle\n */\n\nimport { existsSync, lstatSync, mkdirSync, readdirSync, readFileSync, writeFileSync } from \"node:fs\"\nimport { extname, join as pathJoin, resolve as pathResolve, relative } from \"node:path\"\nimport { transformJSX } from \"@pyreon/compiler\"\nimport type { Plugin, ViteDevServer } from \"vite\"\n\n// Virtual module ID for the HMR runtime\nconst HMR_RUNTIME_ID = \"\\0pyreon/hmr-runtime\"\nconst HMR_RUNTIME_IMPORT = \"virtual:pyreon/hmr-runtime\"\n\nexport type CompatFramework = \"react\" | \"preact\" | \"vue\" | \"solid\"\n\nexport interface PyreonPluginOptions {\n /**\n * Alias imports from an existing framework to Pyreon's compat layer.\n *\n * This lets you drop Pyreon into an existing project with zero code changes —\n * `import { useState } from \"react\"` will resolve to `@pyreon/react-compat`.\n *\n * @example\n * pyreon({ compat: \"react\" }) // react + react-dom → @pyreon/react-compat\n * pyreon({ compat: \"vue\" }) // vue → @pyreon/vue-compat\n * pyreon({ compat: \"solid\" }) // solid-js → @pyreon/solid-compat\n * pyreon({ compat: \"preact\" }) // preact + hooks + signals → @pyreon/preact-compat\n */\n compat?: CompatFramework\n\n /**\n * Enable SSR dev middleware.\n *\n * Pass an object with `entry` pointing to your server entry file.\n * The entry must export a `handler` function: `(req: Request) => Promise<Response>`\n * or a default export of the same type.\n *\n * @example\n * pyreonPlugin({ ssr: { entry: \"./src/entry-server.ts\" } })\n */\n ssr?: {\n /** Server entry file path (e.g. \"./src/entry-server.ts\") */\n entry: string\n }\n}\n\n// ── Compat JSX import sources ─────────────────────────────────────────────────\n\nconst COMPAT_JSX_SOURCE: Record<CompatFramework, string> = {\n react: \"@pyreon/react-compat\",\n preact: \"@pyreon/preact-compat\",\n vue: \"@pyreon/vue-compat\",\n solid: \"@pyreon/solid-compat\",\n}\n\n// ── Compat alias maps ─────────────────────────────────────────────────────────\n\nconst COMPAT_ALIASES: Record<CompatFramework, Record<string, string>> = {\n react: {\n react: \"@pyreon/react-compat\",\n \"react/jsx-runtime\": \"@pyreon/react-compat/jsx-runtime\",\n \"react/jsx-dev-runtime\": \"@pyreon/react-compat/jsx-runtime\",\n \"react-dom\": \"@pyreon/react-compat/dom\",\n \"react-dom/client\": \"@pyreon/react-compat/dom\",\n },\n preact: {\n preact: \"@pyreon/preact-compat\",\n \"preact/hooks\": \"@pyreon/preact-compat/hooks\",\n \"preact/jsx-runtime\": \"@pyreon/preact-compat/jsx-runtime\",\n \"preact/jsx-dev-runtime\": \"@pyreon/preact-compat/jsx-runtime\",\n \"@preact/signals\": \"@pyreon/preact-compat/signals\",\n },\n vue: {\n vue: \"@pyreon/vue-compat\",\n \"vue/jsx-runtime\": \"@pyreon/vue-compat/jsx-runtime\",\n \"vue/jsx-dev-runtime\": \"@pyreon/vue-compat/jsx-runtime\",\n },\n solid: {\n \"solid-js\": \"@pyreon/solid-compat\",\n \"solid-js/jsx-runtime\": \"@pyreon/solid-compat/jsx-runtime\",\n \"solid-js/jsx-dev-runtime\": \"@pyreon/solid-compat/jsx-runtime\",\n },\n}\n\n/**\n * Resolve a package specifier to an absolute source path, respecting the \"bun\"\n * export condition. Falls back to the \"import\" condition.\n *\n * This is needed because Vite 8's resolve pipeline doesn't consistently apply\n * custom conditions from `resolve.conditions` during the `vite:import-analysis`\n * phase for aliased workspace packages.\n */\nfunction resolveWithBunCondition(specifier: string, projectRoot: string): string | undefined {\n // Split specifier: \"@pyreon/react-compat/dom\" → pkg=\"@pyreon/react-compat\", subpath=\"./dom\"\n const parts = specifier.startsWith(\"@\")\n ? specifier.split(\"/\").slice(0, 2)\n : specifier.split(\"/\").slice(0, 1)\n const pkgName = parts.join(\"/\")\n const subpath = specifier.slice(pkgName.length) || \".\"\n const exportKey = subpath === \".\" ? \".\" : `.${subpath}`\n\n try {\n // Walk up from project root to find node_modules containing the package\n const pkgDir = pathResolve(projectRoot, \"node_modules\", pkgName)\n const pkgJsonPath = pathResolve(pkgDir, \"package.json\")\n const pkgJson = JSON.parse(readFileSync(pkgJsonPath, \"utf-8\")) as {\n exports?: Record<string, Record<string, string> | string>\n }\n\n const exp = pkgJson.exports?.[exportKey]\n if (!exp) return undefined\n\n if (typeof exp === \"string\") return pathResolve(pkgDir, exp)\n // Prefer bun → import → default\n const target = exp.bun ?? exp.import ?? exp.default\n return target ? pathResolve(pkgDir, target) : undefined\n } catch {\n return undefined\n }\n}\n\n/**\n * Return the Pyreon compat target for an import specifier, or undefined if\n * the import should not be redirected.\n */\nfunction getCompatTarget(compat: CompatFramework | undefined, id: string): string | undefined {\n if (!compat) return undefined\n const aliased = COMPAT_ALIASES[compat][id]\n if (aliased) return aliased\n // OXC's JSX transform reads jsxImportSource from tsconfig (@pyreon/core),\n // not from our plugin config. Redirect JSX runtime imports in compat mode.\n if (id === \"@pyreon/core/jsx-runtime\" || id === \"@pyreon/core/jsx-dev-runtime\") {\n if (compat === \"react\") return \"@pyreon/react-compat/jsx-runtime\"\n if (compat === \"preact\") return \"@pyreon/preact-compat/jsx-runtime\"\n if (compat === \"vue\") return \"@pyreon/vue-compat/jsx-runtime\"\n if (compat === \"solid\") return \"@pyreon/solid-compat/jsx-runtime\"\n }\n return undefined\n}\n\nexport default function pyreonPlugin(options?: PyreonPluginOptions): Plugin {\n const ssrConfig = options?.ssr\n const compat = options?.compat\n let isBuild = false\n let projectRoot = \"\"\n // Cache resolved absolute paths for compat aliases\n const resolvedAliases = new Map<string, string>()\n\n return {\n name: \"pyreon\",\n enforce: \"pre\",\n\n config(userConfig, env) {\n isBuild = env.command === \"build\"\n // Capture the project root for package resolution in resolveId\n projectRoot = userConfig.root ?? process.cwd()\n\n // Tell Vite's dep scanner not to pre-bundle the aliased framework imports —\n // they resolve to workspace packages via our resolveId hook, not node_modules.\n const optimizeDepsExclude = compat ? Object.keys(COMPAT_ALIASES[compat]) : []\n\n return {\n resolve: {\n conditions: [\"bun\"],\n },\n optimizeDeps: {\n exclude: optimizeDepsExclude,\n },\n oxc: {\n jsx: {\n runtime: \"automatic\",\n importSource: compat ? COMPAT_JSX_SOURCE[compat] : \"@pyreon/core\",\n },\n },\n // In SSR build mode, configure the entry\n ...(env.isSsrBuild && ssrConfig\n ? {\n build: {\n ssr: true,\n rollupOptions: {\n input: ssrConfig.entry,\n },\n },\n }\n : {}),\n }\n },\n\n // ── Virtual module + compat alias resolution ─────────────────────────────\n resolveId(id) {\n if (id === HMR_RUNTIME_IMPORT) return HMR_RUNTIME_ID\n const target = getCompatTarget(compat, id)\n if (!target) return\n\n // Use cached resolution or resolve with bun condition\n let resolved = resolvedAliases.get(target)\n if (!resolved) {\n resolved = resolveWithBunCondition(target, projectRoot)\n if (resolved) resolvedAliases.set(target, resolved)\n }\n return resolved\n },\n\n load(id) {\n if (id === HMR_RUNTIME_ID) {\n return HMR_RUNTIME_SOURCE\n }\n },\n\n transform(code, id) {\n const ext = getExt(id)\n if (ext !== \".tsx\" && ext !== \".jsx\" && ext !== \".pyreon\") return\n\n // In compat mode, skip Pyreon's reactive JSX transform.\n // OXC's built-in JSX transform handles jsx() calls; the compat\n // JSX runtime wraps components for re-render support.\n if (compat === \"react\" || compat === \"preact\" || compat === \"vue\" || compat === \"solid\")\n return\n\n const result = transformJSX(code, id)\n // Surface compiler warnings in the terminal\n for (const w of result.warnings) {\n this.warn(`${w.message} (${id}:${w.line}:${w.column})`)\n }\n\n let output = result.code\n\n // ── HMR injection (dev only) ────────────────────────────────────────\n if (!isBuild) {\n output = injectHmr(output, id)\n }\n\n return { code: output, map: null }\n },\n\n // ── SSR dev middleware ───────────────────────────────────────────────────\n configureServer(server: ViteDevServer) {\n // Generate .pyreon/context.json for AI tools on dev server start\n generateProjectContext(projectRoot)\n\n // Debounced regeneration on file changes\n let contextTimer: ReturnType<typeof setTimeout> | null = null\n server.watcher.on(\"change\", (file) => {\n if (/\\.(tsx|jsx|ts|js)$/.test(file) && !file.includes(\"node_modules\")) {\n if (contextTimer) clearTimeout(contextTimer)\n contextTimer = setTimeout(() => generateProjectContext(projectRoot), 500)\n }\n })\n\n if (!ssrConfig) return\n\n // Return a function so the middleware runs AFTER Vite's built-in middleware\n // (static files, HMR, etc.) — only handle requests that Vite doesn't serve.\n return () => {\n server.middlewares.use(async (req, res, next) => {\n if (req.method !== \"GET\") return next()\n const url = req.url ?? \"/\"\n if (isAssetRequest(url)) return next()\n\n try {\n await handleSsrRequest(server, ssrConfig.entry, url, req, res, next)\n } catch (err) {\n server.ssrFixStacktrace(err as Error)\n next(err)\n }\n })\n }\n },\n }\n}\n\nasync function handleSsrRequest(\n server: ViteDevServer,\n entry: string,\n url: string,\n req: import(\"node:http\").IncomingMessage,\n res: import(\"node:http\").ServerResponse,\n next: (err?: unknown) => void,\n): Promise<void> {\n const mod = await server.ssrLoadModule(entry)\n const handler = mod.handler ?? mod.default\n\n if (typeof handler !== \"function\") {\n next()\n return\n }\n\n const origin = `http://${req.headers.host ?? \"localhost\"}`\n const fullUrl = new URL(url, origin)\n const request = new Request(fullUrl.href, {\n method: req.method ?? \"GET\",\n headers: Object.entries(req.headers).reduce((h, [k, v]) => {\n if (v) h.set(k, Array.isArray(v) ? v.join(\", \") : v)\n return h\n }, new Headers()),\n })\n\n const response: Response = await handler(request)\n let html = await response.text()\n\n html = await server.transformIndexHtml(url, html)\n\n res.statusCode = response.status\n response.headers.forEach((v, k) => {\n res.setHeader(k, v)\n })\n res.end(html)\n}\n\n// ── AI context generation ─────────────────────────────────────────────────────\n\n/**\n * Generate .pyreon/context.json — project map for AI coding assistants.\n * Extracts routes, components (with props/signals), and island declarations.\n */\n// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: single-pass file scanner, splitting hurts perf\nfunction generateProjectContext(root: string): void {\n try {\n const srcDir = pathResolve(root, \"src\")\n if (!existsSync(srcDir)) return\n\n const files = collectTsxFiles(srcDir)\n const routes: Array<{\n path: string\n name?: string | undefined\n hasLoader: boolean\n params: string[]\n }> = []\n const components: Array<{\n name: string\n file: string\n signals: string[]\n props: string[]\n }> = []\n const islands: Array<{ name: string; file: string; hydrate: string }> = []\n\n for (const file of files) {\n let code: string\n try {\n code = readFileSync(file, \"utf-8\")\n } catch {\n continue\n }\n const relFile = relative(root, file)\n\n // Extract routes\n const routeRe = /path\\s*:\\s*[\"']([^\"']+)[\"']/g\n let m: RegExpExecArray | null\n for (m = routeRe.exec(code); m; m = routeRe.exec(code)) {\n const routePath = m[1] ?? \"\"\n const ctx = code.slice(Math.max(0, m.index - 50), Math.min(code.length, m.index + 200))\n routes.push({\n path: routePath,\n name: ctx.match(/name\\s*:\\s*[\"']([^\"']+)[\"']/)?.[1],\n hasLoader: /loader\\s*:/.test(ctx),\n params: [...routePath.matchAll(/:(\\w+)\\??/g)].map((p) => p[1] ?? \"\"),\n })\n }\n\n // Extract components\n const compRe =\n /(?:export\\s+)?(?:const|function)\\s+([A-Z]\\w*)\\s*(?::\\s*\\w+<[^>]*>\\s*)?=?\\s*\\(?\\s*\\{?\\s*([^)]*?)\\s*\\}?\\s*\\)?\\s*(?:=>|{)/g\n for (m = compRe.exec(code); m; m = compRe.exec(code)) {\n const name = m[1] ?? \"Unknown\"\n const propsStr = m[2] ?? \"\"\n const props = propsStr\n .split(\",\")\n .map((p) => p.trim().split(\":\")[0]?.split(\"=\")[0]?.trim() ?? \"\")\n .filter((p) => p && p !== \"props\" && !p.startsWith(\"{\"))\n\n const body = code.slice(\n m.index + m[0].length,\n Math.min(code.length, m.index + m[0].length + 2000),\n )\n const signals: string[] = []\n const sigRe = /(?:const|let)\\s+(\\w+)\\s*=\\s*signal\\s*[<(]/g\n let sm: RegExpExecArray | null\n for (sm = sigRe.exec(body); sm; sm = sigRe.exec(body)) {\n if (sm[1]) signals.push(sm[1])\n }\n\n components.push({ name, file: relFile, signals, props })\n }\n\n // Extract islands\n const islandRe =\n /island\\s*\\([^,]+,\\s*\\{[^}]*name\\s*:\\s*[\"']([^\"']+)[\"'][^}]*?(?:hydrate\\s*:\\s*[\"']([^\"']+)[\"'])?[^}]*\\}/g\n for (m = islandRe.exec(code); m; m = islandRe.exec(code)) {\n if (m[1]) {\n islands.push({ name: m[1], file: relFile, hydrate: m[2] ?? \"load\" })\n }\n }\n }\n\n const context = {\n framework: \"pyreon\",\n version: readProjectVersion(root),\n generatedAt: new Date().toISOString(),\n routes,\n components,\n islands,\n }\n\n const outDir = pathJoin(root, \".pyreon\")\n if (!existsSync(outDir)) mkdirSync(outDir, { recursive: true })\n writeFileSync(pathJoin(outDir, \"context.json\"), JSON.stringify(context, null, 2), \"utf-8\")\n } catch {\n // Silently fail — context generation is best-effort\n }\n}\n\nfunction collectTsxFiles(dir: string): string[] {\n const results: string[] = []\n const exts = new Set([\".tsx\", \".jsx\", \".ts\", \".js\"])\n const skip = new Set([\"node_modules\", \"dist\", \"lib\", \".pyreon\", \".git\"])\n\n // biome-ignore lint/complexity/noExcessiveCognitiveComplexity: simple recursive walker\n function walk(d: string): void {\n let entries: string[]\n try {\n entries = readdirSync(d)\n } catch {\n return\n }\n for (const name of entries) {\n if (skip.has(name)) continue\n const full = pathJoin(d, name)\n try {\n const stat = lstatSync(full)\n if (stat.isDirectory()) {\n walk(full)\n } else if (stat.isFile() && exts.has(extname(name))) {\n results.push(full)\n }\n } catch {\n // skip inaccessible files\n }\n }\n }\n\n walk(dir)\n return results\n}\n\nfunction readProjectVersion(root: string): string {\n try {\n const pkg = JSON.parse(readFileSync(pathJoin(root, \"package.json\"), \"utf-8\"))\n const deps: Record<string, unknown> = { ...pkg.dependencies, ...pkg.devDependencies }\n for (const [name, ver] of Object.entries(deps)) {\n if (name.startsWith(\"@pyreon/\") && typeof ver === \"string\") return ver.replace(/^[\\^~]/, \"\")\n }\n return pkg.version || \"unknown\"\n } catch {\n return \"unknown\"\n }\n}\n\n// ── HMR injection ─────────────────────────────────────────────────────────────\n\n/**\n * Regex that detects signal declarations (prefix + variable name).\n * The arguments are extracted via balanced-paren matching in `injectHmr`.\n * A brace-depth check filters out matches inside functions/blocks — only\n * module-scope (depth 0) signals are rewritten for HMR state preservation.\n */\nconst SIGNAL_PREFIX_RE = /^((?:export\\s+)?(?:const|let)\\s+(\\w+)\\s*=\\s*)signal\\(/gm\n\n/**\n * Detect whether the module exports any component-like functions\n * (uppercase first letter — standard convention for JSX components).\n */\nconst EXPORT_COMPONENT_RE =\n /export\\s+(?:default\\s+)?(?:function\\s+([A-Z]\\w*)|const\\s+([A-Z]\\w*)\\s*[=:])/\n\nfunction skipStringLiteral(code: string, start: number, quote: string): number {\n let j = start + 1\n while (j < code.length) {\n if (code[j] === \"\\\\\") {\n j += 2\n continue\n }\n if (code[j] === quote) break\n j++\n }\n return j\n}\n\nfunction extractBalancedArgs(code: string, start: number): string | null {\n let depth = 1\n for (let i = start; i < code.length; i++) {\n const ch = code[i]\n if (ch === \"(\") depth++\n else if (ch === \")\") {\n depth--\n if (depth === 0) return code.slice(start, i)\n } else if (ch === '\"' || ch === \"'\" || ch === \"`\") {\n i = skipStringLiteral(code, i, ch)\n }\n }\n return null\n}\n\n/**\n * Compute brace depth at position `pos` — returns 0 for module scope.\n * Skips string literals to avoid counting braces inside strings.\n */\nfunction braceDepthAt(code: string, pos: number): number {\n let depth = 0\n for (let i = 0; i < pos; i++) {\n const ch = code[i]\n if (ch === \"{\") depth++\n else if (ch === \"}\") depth--\n else if (ch === '\"' || ch === \"'\" || ch === \"`\") {\n i = skipStringLiteral(code, i, ch)\n }\n }\n return depth\n}\n\n/** Rewrite module-scope `signal()` calls to `__hmr_signal()` for state preservation. */\nfunction rewriteSignals(code: string, moduleId: string): string {\n const escapedId = JSON.stringify(moduleId)\n const matches: {\n start: number\n end: number\n prefix: string\n name: string\n args: string\n }[] = []\n let m: RegExpExecArray | null = SIGNAL_PREFIX_RE.exec(code)\n while (m !== null) {\n const argsStart = m.index + m[0].length\n const args = extractBalancedArgs(code, argsStart)\n if (args === null) {\n m = SIGNAL_PREFIX_RE.exec(code)\n continue // unbalanced — skip\n }\n // Only rewrite module-scope signals (brace depth 0).\n if (braceDepthAt(code, m.index) === 0) {\n matches.push({\n start: m.index,\n end: argsStart + args.length + 1, // +1 for closing paren\n prefix: m[1] ?? \"\",\n name: m[2] ?? \"\",\n args,\n })\n }\n m = SIGNAL_PREFIX_RE.exec(code)\n }\n SIGNAL_PREFIX_RE.lastIndex = 0\n\n // Replace in reverse to preserve offsets\n let output = code\n for (let i = matches.length - 1; i >= 0; i--) {\n const { start, end, prefix, name, args } = matches[i] as (typeof matches)[number]\n const replacement = `${prefix}__hmr_signal(${escapedId}, ${JSON.stringify(name)}, signal, ${args})`\n output = output.slice(0, start) + replacement + output.slice(end)\n }\n return output\n}\n\nfunction injectHmr(code: string, moduleId: string): string {\n const hasSignals = SIGNAL_PREFIX_RE.test(code)\n SIGNAL_PREFIX_RE.lastIndex = 0\n\n const hasComponentExport = EXPORT_COMPONENT_RE.test(code)\n\n // Only inject HMR if the module exports components or has module-scope signals\n if (!hasComponentExport && !hasSignals) return code\n\n let output = hasSignals ? rewriteSignals(code, moduleId) : code\n\n // Build the HMR footer\n const escapedId = JSON.stringify(moduleId)\n const lines: string[] = []\n\n if (hasSignals) {\n lines.push(`import { __hmr_signal, __hmr_dispose } from \"${HMR_RUNTIME_IMPORT}\";`)\n }\n\n lines.push(`if (import.meta.hot) {`)\n\n if (hasSignals) {\n lines.push(` import.meta.hot.dispose(() => __hmr_dispose(${escapedId}));`)\n }\n\n lines.push(` import.meta.hot.accept();`)\n lines.push(`}`)\n\n output = `${output}\\n\\n${lines.join(\"\\n\")}\\n`\n\n return output\n}\n\n// ── Helpers ───────────────────────────────────────────────────────────────────\n\nfunction getExt(id: string): string {\n const clean = id.split(\"?\")[0] ?? id\n const dot = clean.lastIndexOf(\".\")\n return dot >= 0 ? clean.slice(dot) : \"\"\n}\n\n/** Skip Vite-handled asset requests (CSS, images, HMR, etc.) */\nfunction isAssetRequest(url: string): boolean {\n return (\n url.startsWith(\"/@\") || // @vite/client, @id, @fs, etc.\n url.startsWith(\"/__\") || // __open-in-editor, etc.\n url.includes(\"/node_modules/\") ||\n /\\.(css|js|ts|tsx|jsx|json|ico|png|jpg|jpeg|gif|svg|woff2?|ttf|eot|map)(\\?|$)/.test(url)\n )\n}\n\n// ── HMR runtime source (served as virtual module) ─────────────────────────────\n//\n// Inlined here so it's available without a filesystem read. This is the\n// compiled-to-JS version of hmr-runtime.ts — kept in sync manually.\n\nconst HMR_RUNTIME_SOURCE = `\nconst REGISTRY_KEY = \"__pyreon_hmr_registry__\";\n\nfunction getRegistry() {\n if (!globalThis[REGISTRY_KEY]) {\n globalThis[REGISTRY_KEY] = new Map();\n }\n return globalThis[REGISTRY_KEY];\n}\n\nconst moduleSignals = new Map();\n\nexport function __hmr_signal(moduleId, name, signalFn, initialValue) {\n const registry = getRegistry();\n const saved = registry.get(moduleId);\n const value = saved?.has(name) ? saved.get(name) : initialValue;\n const s = signalFn(value);\n\n let mod = moduleSignals.get(moduleId);\n if (!mod) {\n mod = { entries: new Map() };\n moduleSignals.set(moduleId, mod);\n }\n mod.entries.set(name, s);\n\n return s;\n}\n\nexport function __hmr_dispose(moduleId) {\n const mod = moduleSignals.get(moduleId);\n if (!mod) return;\n\n const registry = getRegistry();\n const saved = new Map();\n for (const [name, s] of mod.entries) {\n saved.set(name, s.peek());\n }\n registry.set(moduleId, saved);\n moduleSignals.delete(moduleId);\n}\n`\n"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
- import { readFileSync } from "node:fs";
2
- import { resolve } from "node:path";
1
+ import { existsSync, lstatSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from "node:fs";
2
+ import { extname, join, relative, resolve } from "node:path";
3
3
  import { transformJSX } from "@pyreon/compiler";
4
4
 
5
5
  //#region src/index.ts
@@ -139,6 +139,14 @@ function pyreonPlugin(options) {
139
139
  };
140
140
  },
141
141
  configureServer(server) {
142
+ generateProjectContext(projectRoot);
143
+ let contextTimer = null;
144
+ server.watcher.on("change", file => {
145
+ if (/\.(tsx|jsx|ts|js)$/.test(file) && !file.includes("node_modules")) {
146
+ if (contextTimer) clearTimeout(contextTimer);
147
+ contextTimer = setTimeout(() => generateProjectContext(projectRoot), 500);
148
+ }
149
+ });
142
150
  if (!ssrConfig) return;
143
151
  return () => {
144
152
  server.middlewares.use(async (req, res, next) => {
@@ -181,6 +189,112 @@ async function handleSsrRequest(server, entry, url, req, res, next) {
181
189
  res.end(html);
182
190
  }
183
191
  /**
192
+ * Generate .pyreon/context.json — project map for AI coding assistants.
193
+ * Extracts routes, components (with props/signals), and island declarations.
194
+ */
195
+ function generateProjectContext(root) {
196
+ try {
197
+ const srcDir = resolve(root, "src");
198
+ if (!existsSync(srcDir)) return;
199
+ const files = collectTsxFiles(srcDir);
200
+ const routes = [];
201
+ const components = [];
202
+ const islands = [];
203
+ for (const file of files) {
204
+ let code;
205
+ try {
206
+ code = readFileSync(file, "utf-8");
207
+ } catch {
208
+ continue;
209
+ }
210
+ const relFile = relative(root, file);
211
+ const routeRe = /path\s*:\s*["']([^"']+)["']/g;
212
+ let m;
213
+ for (m = routeRe.exec(code); m; m = routeRe.exec(code)) {
214
+ const routePath = m[1] ?? "";
215
+ const ctx = code.slice(Math.max(0, m.index - 50), Math.min(code.length, m.index + 200));
216
+ routes.push({
217
+ path: routePath,
218
+ name: ctx.match(/name\s*:\s*["']([^"']+)["']/)?.[1],
219
+ hasLoader: /loader\s*:/.test(ctx),
220
+ params: [...routePath.matchAll(/:(\w+)\??/g)].map(p => p[1] ?? "")
221
+ });
222
+ }
223
+ const compRe = /(?:export\s+)?(?:const|function)\s+([A-Z]\w*)\s*(?::\s*\w+<[^>]*>\s*)?=?\s*\(?\s*\{?\s*([^)]*?)\s*\}?\s*\)?\s*(?:=>|{)/g;
224
+ for (m = compRe.exec(code); m; m = compRe.exec(code)) {
225
+ const name = m[1] ?? "Unknown";
226
+ const props = (m[2] ?? "").split(",").map(p => p.trim().split(":")[0]?.split("=")[0]?.trim() ?? "").filter(p => p && p !== "props" && !p.startsWith("{"));
227
+ const body = code.slice(m.index + m[0].length, Math.min(code.length, m.index + m[0].length + 2e3));
228
+ const signals = [];
229
+ const sigRe = /(?:const|let)\s+(\w+)\s*=\s*signal\s*[<(]/g;
230
+ let sm;
231
+ for (sm = sigRe.exec(body); sm; sm = sigRe.exec(body)) if (sm[1]) signals.push(sm[1]);
232
+ components.push({
233
+ name,
234
+ file: relFile,
235
+ signals,
236
+ props
237
+ });
238
+ }
239
+ const islandRe = /island\s*\([^,]+,\s*\{[^}]*name\s*:\s*["']([^"']+)["'][^}]*?(?:hydrate\s*:\s*["']([^"']+)["'])?[^}]*\}/g;
240
+ for (m = islandRe.exec(code); m; m = islandRe.exec(code)) if (m[1]) islands.push({
241
+ name: m[1],
242
+ file: relFile,
243
+ hydrate: m[2] ?? "load"
244
+ });
245
+ }
246
+ const context = {
247
+ framework: "pyreon",
248
+ version: readProjectVersion(root),
249
+ generatedAt: (/* @__PURE__ */new Date()).toISOString(),
250
+ routes,
251
+ components,
252
+ islands
253
+ };
254
+ const outDir = join(root, ".pyreon");
255
+ if (!existsSync(outDir)) mkdirSync(outDir, {
256
+ recursive: true
257
+ });
258
+ writeFileSync(join(outDir, "context.json"), JSON.stringify(context, null, 2), "utf-8");
259
+ } catch {}
260
+ }
261
+ function collectTsxFiles(dir) {
262
+ const results = [];
263
+ const exts = new Set([".tsx", ".jsx", ".ts", ".js"]);
264
+ const skip = new Set(["node_modules", "dist", "lib", ".pyreon", ".git"]);
265
+ function walk(d) {
266
+ let entries;
267
+ try {
268
+ entries = readdirSync(d);
269
+ } catch {
270
+ return;
271
+ }
272
+ for (const name of entries) {
273
+ if (skip.has(name)) continue;
274
+ const full = join(d, name);
275
+ try {
276
+ const stat = lstatSync(full);
277
+ if (stat.isDirectory()) walk(full);else if (stat.isFile() && exts.has(extname(name))) results.push(full);
278
+ } catch {}
279
+ }
280
+ }
281
+ walk(dir);
282
+ return results;
283
+ }
284
+ function readProjectVersion(root) {
285
+ try {
286
+ const pkg = JSON.parse(readFileSync(join(root, "package.json"), "utf-8"));
287
+ const deps = {
288
+ ...pkg.dependencies,
289
+ ...pkg.devDependencies
290
+ };
291
+ for (const [name, ver] of Object.entries(deps)) if (name.startsWith("@pyreon/") && typeof ver === "string") return ver.replace(/^[\^~]/, "");
292
+ return pkg.version || "unknown";
293
+ } catch {
294
+ return "unknown";
295
+ }
296
+ }
297
+ /**
184
298
  * Regex that detects signal declarations (prefix + variable name).
185
299
  * The arguments are extracted via balanced-paren matching in `injectHmr`.
186
300
  * A brace-depth check filters out matches inside functions/blocks — only
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":["pathResolve"],"sources":["../../src/index.ts"],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","names":["pathResolve","pathJoin"],"sources":["../../src/index.ts"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pyreon/vite-plugin",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "description": "Vite plugin for Pyreon — .pyreon SFC support, HMR, compiler integration",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -39,7 +39,7 @@
39
39
  "prepublishOnly": "bun run build"
40
40
  },
41
41
  "dependencies": {
42
- "@pyreon/compiler": "^0.4.0"
42
+ "@pyreon/compiler": "^0.5.0"
43
43
  },
44
44
  "peerDependencies": {
45
45
  "vite": ">=8.0.0"
package/src/index.ts CHANGED
@@ -32,8 +32,8 @@
32
32
  * vite build --ssr src/entry-server.ts --outDir dist/server # server bundle
33
33
  */
34
34
 
35
- import { readFileSync } from "node:fs"
36
- import { resolve as pathResolve } from "node:path"
35
+ import { existsSync, lstatSync, mkdirSync, readdirSync, readFileSync, writeFileSync } from "node:fs"
36
+ import { extname, join as pathJoin, resolve as pathResolve, relative } from "node:path"
37
37
  import { transformJSX } from "@pyreon/compiler"
38
38
  import type { Plugin, ViteDevServer } from "vite"
39
39
 
@@ -265,6 +265,18 @@ export default function pyreonPlugin(options?: PyreonPluginOptions): Plugin {
265
265
 
266
266
  // ── SSR dev middleware ───────────────────────────────────────────────────
267
267
  configureServer(server: ViteDevServer) {
268
+ // Generate .pyreon/context.json for AI tools on dev server start
269
+ generateProjectContext(projectRoot)
270
+
271
+ // Debounced regeneration on file changes
272
+ let contextTimer: ReturnType<typeof setTimeout> | null = null
273
+ server.watcher.on("change", (file) => {
274
+ if (/\.(tsx|jsx|ts|js)$/.test(file) && !file.includes("node_modules")) {
275
+ if (contextTimer) clearTimeout(contextTimer)
276
+ contextTimer = setTimeout(() => generateProjectContext(projectRoot), 500)
277
+ }
278
+ })
279
+
268
280
  if (!ssrConfig) return
269
281
 
270
282
  // Return a function so the middleware runs AFTER Vite's built-in middleware
@@ -325,6 +337,154 @@ async function handleSsrRequest(
325
337
  res.end(html)
326
338
  }
327
339
 
340
+ // ── AI context generation ─────────────────────────────────────────────────────
341
+
342
+ /**
343
+ * Generate .pyreon/context.json — project map for AI coding assistants.
344
+ * Extracts routes, components (with props/signals), and island declarations.
345
+ */
346
+ // biome-ignore lint/complexity/noExcessiveCognitiveComplexity: single-pass file scanner, splitting hurts perf
347
+ function generateProjectContext(root: string): void {
348
+ try {
349
+ const srcDir = pathResolve(root, "src")
350
+ if (!existsSync(srcDir)) return
351
+
352
+ const files = collectTsxFiles(srcDir)
353
+ const routes: Array<{
354
+ path: string
355
+ name?: string | undefined
356
+ hasLoader: boolean
357
+ params: string[]
358
+ }> = []
359
+ const components: Array<{
360
+ name: string
361
+ file: string
362
+ signals: string[]
363
+ props: string[]
364
+ }> = []
365
+ const islands: Array<{ name: string; file: string; hydrate: string }> = []
366
+
367
+ for (const file of files) {
368
+ let code: string
369
+ try {
370
+ code = readFileSync(file, "utf-8")
371
+ } catch {
372
+ continue
373
+ }
374
+ const relFile = relative(root, file)
375
+
376
+ // Extract routes
377
+ const routeRe = /path\s*:\s*["']([^"']+)["']/g
378
+ let m: RegExpExecArray | null
379
+ for (m = routeRe.exec(code); m; m = routeRe.exec(code)) {
380
+ const routePath = m[1] ?? ""
381
+ const ctx = code.slice(Math.max(0, m.index - 50), Math.min(code.length, m.index + 200))
382
+ routes.push({
383
+ path: routePath,
384
+ name: ctx.match(/name\s*:\s*["']([^"']+)["']/)?.[1],
385
+ hasLoader: /loader\s*:/.test(ctx),
386
+ params: [...routePath.matchAll(/:(\w+)\??/g)].map((p) => p[1] ?? ""),
387
+ })
388
+ }
389
+
390
+ // Extract components
391
+ const compRe =
392
+ /(?:export\s+)?(?:const|function)\s+([A-Z]\w*)\s*(?::\s*\w+<[^>]*>\s*)?=?\s*\(?\s*\{?\s*([^)]*?)\s*\}?\s*\)?\s*(?:=>|{)/g
393
+ for (m = compRe.exec(code); m; m = compRe.exec(code)) {
394
+ const name = m[1] ?? "Unknown"
395
+ const propsStr = m[2] ?? ""
396
+ const props = propsStr
397
+ .split(",")
398
+ .map((p) => p.trim().split(":")[0]?.split("=")[0]?.trim() ?? "")
399
+ .filter((p) => p && p !== "props" && !p.startsWith("{"))
400
+
401
+ const body = code.slice(
402
+ m.index + m[0].length,
403
+ Math.min(code.length, m.index + m[0].length + 2000),
404
+ )
405
+ const signals: string[] = []
406
+ const sigRe = /(?:const|let)\s+(\w+)\s*=\s*signal\s*[<(]/g
407
+ let sm: RegExpExecArray | null
408
+ for (sm = sigRe.exec(body); sm; sm = sigRe.exec(body)) {
409
+ if (sm[1]) signals.push(sm[1])
410
+ }
411
+
412
+ components.push({ name, file: relFile, signals, props })
413
+ }
414
+
415
+ // Extract islands
416
+ const islandRe =
417
+ /island\s*\([^,]+,\s*\{[^}]*name\s*:\s*["']([^"']+)["'][^}]*?(?:hydrate\s*:\s*["']([^"']+)["'])?[^}]*\}/g
418
+ for (m = islandRe.exec(code); m; m = islandRe.exec(code)) {
419
+ if (m[1]) {
420
+ islands.push({ name: m[1], file: relFile, hydrate: m[2] ?? "load" })
421
+ }
422
+ }
423
+ }
424
+
425
+ const context = {
426
+ framework: "pyreon",
427
+ version: readProjectVersion(root),
428
+ generatedAt: new Date().toISOString(),
429
+ routes,
430
+ components,
431
+ islands,
432
+ }
433
+
434
+ const outDir = pathJoin(root, ".pyreon")
435
+ if (!existsSync(outDir)) mkdirSync(outDir, { recursive: true })
436
+ writeFileSync(pathJoin(outDir, "context.json"), JSON.stringify(context, null, 2), "utf-8")
437
+ } catch {
438
+ // Silently fail — context generation is best-effort
439
+ }
440
+ }
441
+
442
+ function collectTsxFiles(dir: string): string[] {
443
+ const results: string[] = []
444
+ const exts = new Set([".tsx", ".jsx", ".ts", ".js"])
445
+ const skip = new Set(["node_modules", "dist", "lib", ".pyreon", ".git"])
446
+
447
+ // biome-ignore lint/complexity/noExcessiveCognitiveComplexity: simple recursive walker
448
+ function walk(d: string): void {
449
+ let entries: string[]
450
+ try {
451
+ entries = readdirSync(d)
452
+ } catch {
453
+ return
454
+ }
455
+ for (const name of entries) {
456
+ if (skip.has(name)) continue
457
+ const full = pathJoin(d, name)
458
+ try {
459
+ const stat = lstatSync(full)
460
+ if (stat.isDirectory()) {
461
+ walk(full)
462
+ } else if (stat.isFile() && exts.has(extname(name))) {
463
+ results.push(full)
464
+ }
465
+ } catch {
466
+ // skip inaccessible files
467
+ }
468
+ }
469
+ }
470
+
471
+ walk(dir)
472
+ return results
473
+ }
474
+
475
+ function readProjectVersion(root: string): string {
476
+ try {
477
+ const pkg = JSON.parse(readFileSync(pathJoin(root, "package.json"), "utf-8"))
478
+ const deps: Record<string, unknown> = { ...pkg.dependencies, ...pkg.devDependencies }
479
+ for (const [name, ver] of Object.entries(deps)) {
480
+ if (name.startsWith("@pyreon/") && typeof ver === "string") return ver.replace(/^[\^~]/, "")
481
+ }
482
+ return pkg.version || "unknown"
483
+ } catch {
484
+ return "unknown"
485
+ }
486
+ }
487
+
328
488
  // ── HMR injection ─────────────────────────────────────────────────────────────
329
489
 
330
490
  /**