@tekyzinc/gsd-t 2.73.13 → 2.73.14

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/CHANGELOG.md CHANGED
@@ -2,10 +2,12 @@
2
2
 
3
3
  All notable changes to GSD-T are documented here. Updated with each release.
4
4
 
5
- ## [2.73.13] - 2026-04-08
5
+ ## [2.73.14] - 2026-04-08
6
6
 
7
- ### Fixed (review UI — test fixture props for component preview)
8
- - **Preview now passes test fixture props** from design contracts to mounted components. Reads `## Test Fixture` JSON block from contract, strips metadata keys (`__` prefixed), and passes as component props. Components that require data (charts, tables, stat cards) now render with sample data instead of blank.
7
+ ### Fixed (review UI — component preview rendering)
8
+ - **Preview HTML now proxied through Vite** for module resolution. Bare module specifiers (`'vue'`, `'react'`) are transformed by Vite into resolved paths. Previously served static HTML which caused `Failed to resolve module specifier "vue"` error.
9
+ - **Test fixture props extracted from design contracts** — reads `## Test Fixture` JSON block, strips metadata keys, passes as component props. Components now render with sample data.
10
+ - **Playwright-verified** — ChartDonut renders 5-segment donut with center value, sublabel, and percentage labels from contract fixture data.
9
11
 
10
12
  ## [2.73.12] - 2026-04-08
11
13
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tekyzinc/gsd-t",
3
- "version": "2.73.13",
3
+ "version": "2.73.14",
4
4
  "description": "GSD-T: Contract-Driven Development for Claude Code — 56 slash commands with headless CI/CD mode, graph-powered code analysis, real-time agent dashboard, execution intelligence, task telemetry, doc-ripple enforcement, backlog management, impact analysis, test sync, milestone archival, and PRD generation",
5
5
  "author": "Tekyz, Inc.",
6
6
  "license": "MIT",
@@ -107,7 +107,6 @@ function generatePreviewHtml(componentPath) {
107
107
  <meta charset="UTF-8">
108
108
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
109
109
  <title>Preview: ${path.basename(componentPath)}</title>
110
- <script type="module" src="/@vite/client"></script>
111
110
  ${linkTags}
112
111
  <style>
113
112
  * { margin: 0; padding: 0; box-sizing: border-box; }
@@ -361,7 +360,7 @@ const server = http.createServer((req, res) => {
361
360
  return;
362
361
  }
363
362
 
364
- // Component preview — mounts a single component in isolation via Vite
363
+ // Component preview — writes temp HTML to project, proxies through Vite for module resolution
365
364
  if (pathname === "/review/preview") {
366
365
  const component = parsed.query.component;
367
366
  if (!component) {
@@ -369,24 +368,44 @@ const server = http.createServer((req, res) => {
369
368
  res.end("Missing ?component= parameter");
370
369
  return;
371
370
  }
372
- // Proxy this HTML through Vite so module imports resolve correctly
371
+ // Write preview HTML to project dir so Vite transforms bare module specifiers (e.g., 'vue' → /node_modules/.vite/deps/vue.js)
372
+ const previewFile = path.join(PROJECT_DIR, "__gsd-preview.html");
373
373
  const html = generatePreviewHtml(component);
374
- // Send to Vite's HTML transform endpoint via proxy
374
+ try { fs.writeFileSync(previewFile, html); } catch { /* ignore */ }
375
+ // Proxy through Vite so it transforms the HTML
375
376
  const proxyOpts = {
376
377
  hostname: targetUrl.hostname,
377
378
  port: targetUrl.port,
378
- path: "/__gsd_preview",
379
+ path: "/__gsd-preview.html",
379
380
  method: "GET",
380
381
  headers: { ...req.headers, host: `${targetUrl.hostname}:${targetUrl.port}` },
381
382
  };
382
- // Vite won't know this path — serve directly but let browser resolve modules from Vite
383
- const buf = Buffer.from(html, "utf8");
384
- res.writeHead(200, {
385
- "Content-Type": "text/html",
386
- "Content-Length": buf.length,
387
- "Cache-Control": "no-cache",
383
+ const proxyReq = http.request(proxyOpts, (proxyRes) => {
384
+ const chunks = [];
385
+ proxyRes.on("data", (chunk) => chunks.push(chunk));
386
+ proxyRes.on("end", () => {
387
+ let transformed = Buffer.concat(chunks).toString("utf8");
388
+ // Inject review overlay if not already present
389
+ if (!transformed.includes("review/inject.js")) {
390
+ transformed = transformed.replace("</body>", '<script src="/review/inject.js"></script>\n</body>');
391
+ }
392
+ const buf = Buffer.from(transformed, "utf8");
393
+ res.writeHead(proxyRes.statusCode, {
394
+ ...proxyRes.headers,
395
+ "content-length": buf.length,
396
+ "cache-control": "no-cache",
397
+ });
398
+ res.end(buf);
399
+ // Clean up temp file
400
+ try { fs.unlinkSync(previewFile); } catch { /* ignore */ }
401
+ });
402
+ });
403
+ proxyReq.on("error", () => {
404
+ res.writeHead(502, { "Content-Type": "text/html" });
405
+ res.end("<h1>Dev server unreachable</h1>");
406
+ try { fs.unlinkSync(previewFile); } catch { /* ignore */ }
388
407
  });
389
- res.end(buf);
408
+ proxyReq.end();
390
409
  return;
391
410
  }
392
411