sunpeak 0.18.6 → 0.18.9

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.
Files changed (63) hide show
  1. package/bin/commands/dev.mjs +9 -5
  2. package/bin/commands/inspect.mjs +13 -1
  3. package/bin/commands/new.mjs +5 -0
  4. package/bin/lib/dev-overlay.mjs +50 -0
  5. package/bin/lib/live/live-config.d.mts +3 -0
  6. package/bin/lib/live/live-config.mjs +3 -1
  7. package/bin/lib/sandbox-server.mjs +19 -0
  8. package/dist/chatgpt/index.cjs +2 -3
  9. package/dist/chatgpt/index.js +2 -3
  10. package/dist/claude/index.cjs +1 -2
  11. package/dist/claude/index.js +1 -2
  12. package/dist/host/chatgpt/index.cjs +0 -1
  13. package/dist/host/chatgpt/index.cjs.map +1 -1
  14. package/dist/host/chatgpt/index.js +0 -1
  15. package/dist/host/chatgpt/index.js.map +1 -1
  16. package/dist/index.cjs +1 -1
  17. package/dist/index.js +1 -1
  18. package/dist/inspector/index.cjs +2 -3
  19. package/dist/inspector/index.js +2 -3
  20. package/dist/inspector/inspector-url.d.ts +13 -0
  21. package/dist/inspector/use-inspector-state.d.ts +2 -0
  22. package/dist/{inspector-DRD_Q66E.cjs → inspector-CTMccsz9.cjs} +71 -22
  23. package/dist/inspector-CTMccsz9.cjs.map +1 -0
  24. package/dist/{inspector-CjSoXm6N.js → inspector-DkS75JCk.js} +71 -22
  25. package/dist/inspector-DkS75JCk.js.map +1 -0
  26. package/dist/{inspector-url-7qhtJwY6.cjs → inspector-url-C3LTKgXt.cjs} +3 -1
  27. package/dist/inspector-url-C3LTKgXt.cjs.map +1 -0
  28. package/dist/{inspector-url-DuEFmxLP.js → inspector-url-CyQcuBI9.js} +3 -1
  29. package/dist/inspector-url-CyQcuBI9.js.map +1 -0
  30. package/dist/mcp/index.cjs +98 -15
  31. package/dist/mcp/index.cjs.map +1 -1
  32. package/dist/mcp/index.js +98 -15
  33. package/dist/mcp/index.js.map +1 -1
  34. package/dist/style.css +4 -0
  35. package/package.json +5 -5
  36. package/template/dist/albums/albums.html +1 -1
  37. package/template/dist/albums/albums.json +1 -1
  38. package/template/dist/carousel/carousel.html +1 -1
  39. package/template/dist/carousel/carousel.json +1 -1
  40. package/template/dist/map/map.html +1 -1
  41. package/template/dist/map/map.json +1 -1
  42. package/template/dist/review/review.html +1 -1
  43. package/template/dist/review/review.json +1 -1
  44. package/template/node_modules/.bin/vite +2 -2
  45. package/template/node_modules/.bin/vitest +2 -2
  46. package/template/node_modules/.vite/deps/_metadata.json +4 -4
  47. package/template/node_modules/.vite-mcp/deps/@testing-library_react.js +9 -6
  48. package/template/node_modules/.vite-mcp/deps/@testing-library_react.js.map +1 -1
  49. package/template/node_modules/.vite-mcp/deps/_metadata.json +21 -21
  50. package/template/node_modules/.vite-mcp/deps/vitest.js +366 -128
  51. package/template/node_modules/.vite-mcp/deps/vitest.js.map +1 -1
  52. package/template/package.json +2 -2
  53. package/template/tests/e2e/albums.spec.ts +1 -1
  54. package/template/tests/e2e/carousel.spec.ts +1 -1
  55. package/template/tests/e2e/dev-overlay.spec.ts +118 -0
  56. package/template/tests/e2e/helpers.ts +13 -0
  57. package/template/tests/e2e/map.spec.ts +1 -1
  58. package/template/tests/e2e/review.spec.ts +1 -1
  59. package/template/tests/live/playwright.config.ts +1 -1
  60. package/dist/inspector-CjSoXm6N.js.map +0 -1
  61. package/dist/inspector-DRD_Q66E.cjs.map +0 -1
  62. package/dist/inspector-url-7qhtJwY6.cjs.map +0 -1
  63. package/dist/inspector-url-DuEFmxLP.js.map +0 -1
@@ -35,7 +35,7 @@
35
35
  "react-dom": "^19.2.4",
36
36
  "tailwindcss": "^4.2.2",
37
37
  "typescript": "^5.9.3",
38
- "vite": "^8.0.1",
39
- "vitest": "^4.1.0"
38
+ "vite": "^8.0.3",
39
+ "vitest": "^4.1.2"
40
40
  }
41
41
  }
@@ -1,5 +1,5 @@
1
1
  import { test, expect } from '@playwright/test';
2
- import { createInspectorUrl } from 'sunpeak/chatgpt';
2
+ import { createInspectorUrl } from './helpers';
3
3
 
4
4
  const hosts = ['chatgpt', 'claude'] as const;
5
5
 
@@ -1,5 +1,5 @@
1
1
  import { test, expect } from '@playwright/test';
2
- import { createInspectorUrl } from 'sunpeak/chatgpt';
2
+ import { createInspectorUrl } from './helpers';
3
3
 
4
4
  const hosts = ['chatgpt', 'claude'] as const;
5
5
 
@@ -0,0 +1,118 @@
1
+ import { test, expect } from '@playwright/test';
2
+ import { createInspectorUrl } from 'sunpeak/chatgpt';
3
+
4
+ const hosts = ['chatgpt', 'claude'] as const;
5
+
6
+ for (const host of hosts) {
7
+ test.describe(`Dev Overlay [${host}]`, () => {
8
+ test('shows resource timestamp in dev overlay on initial load', async ({ page }) => {
9
+ await page.goto(createInspectorUrl({ simulation: 'show-albums', theme: 'dark', host }));
10
+
11
+ const iframe = page.frameLocator('iframe').frameLocator('iframe');
12
+
13
+ // The dev overlay button should be present with the resource timestamp
14
+ const overlay = iframe.locator('#__sunpeak-dev-timing');
15
+ await expect(overlay).toBeAttached();
16
+
17
+ // Should contain the "Resource:" label with an HH:MM:SS timestamp
18
+ const text = await overlay.textContent();
19
+ expect(text).toMatch(/Resource:\s*\d{2}:\d{2}:\d{2}/);
20
+
21
+ // Should NOT contain "Tool:" row before any tool call via Run
22
+ expect(text).not.toContain('Tool:');
23
+ });
24
+
25
+ test('shows tool timing after Run is clicked', async ({ page }) => {
26
+ await page.goto(createInspectorUrl({ tool: 'show-albums', theme: 'dark', host }));
27
+
28
+ // Click Run to trigger a real tool call
29
+ const runButton = page.locator('button:has-text("Run")');
30
+ await expect(runButton).toBeVisible();
31
+ await runButton.click();
32
+
33
+ // Wait for the resource iframe to appear (Run loads the resource)
34
+ const iframe = page.frameLocator('iframe').frameLocator('iframe');
35
+
36
+ const overlay = iframe.locator('#__sunpeak-dev-timing');
37
+ await expect(overlay).toBeAttached();
38
+
39
+ // After Run, the overlay should show both Resource and Tool rows.
40
+ // Assert timing is a number followed by "ms" — don't assert the specific value.
41
+ await expect(overlay).toContainText(/Tool:\s*\d+(\.\d)?ms/, { timeout: 10_000 });
42
+ await expect(overlay).toContainText(/Resource:/);
43
+ });
44
+
45
+ test('dev overlay collapses and expands on click', async ({ page }) => {
46
+ await page.goto(createInspectorUrl({ simulation: 'show-albums', theme: 'dark', host }));
47
+
48
+ const iframe = page.frameLocator('iframe').frameLocator('iframe');
49
+ const overlay = iframe.locator('#__sunpeak-dev-timing');
50
+ await expect(overlay).toBeAttached();
51
+
52
+ // Initially expanded — shows "Resource:" label
53
+ await expect(overlay).toContainText('Resource:');
54
+
55
+ // Click to collapse
56
+ await overlay.evaluate((el) => (el as HTMLElement).click());
57
+ await expect(overlay).toContainText('DEV');
58
+ // Collapsed state should NOT show the timestamp
59
+ const collapsedText = await overlay.textContent();
60
+ expect(collapsedText).not.toMatch(/\d{2}:\d{2}:\d{2}/);
61
+
62
+ // Click again to expand
63
+ await overlay.evaluate((el) => (el as HTMLElement).click());
64
+ await expect(overlay).toContainText('Resource:');
65
+ });
66
+
67
+ test('dev overlay is still present in prod resources served from dev server', async ({
68
+ page,
69
+ }) => {
70
+ await page.goto(
71
+ createInspectorUrl({
72
+ simulation: 'show-albums',
73
+ theme: 'dark',
74
+ host,
75
+ prodResources: true,
76
+ })
77
+ );
78
+
79
+ // Wait for content to load
80
+ await page.waitForLoadState('networkidle');
81
+
82
+ // If the iframe is present, check that the dev overlay is NOT there.
83
+ // In prod resources mode served from the dev server, the overlay IS
84
+ // injected (dev server always adds it for debugging). So we verify
85
+ // it's at least attached if the iframe loaded.
86
+ const iframeCount = await page.locator('iframe').count();
87
+ if (iframeCount > 0) {
88
+ const iframe = page.frameLocator('iframe').frameLocator('iframe');
89
+ const overlay = iframe.locator('#__sunpeak-dev-timing');
90
+ // The dev server injects the overlay even into prod resources for debugging.
91
+ // This is by design — only a true production deployment omits it.
92
+ await expect(overlay).toBeAttached({ timeout: 5_000 });
93
+ }
94
+ });
95
+
96
+ test('dev overlay has correct visual styling', async ({ page }) => {
97
+ await page.goto(createInspectorUrl({ simulation: 'show-albums', theme: 'dark', host }));
98
+
99
+ const iframe = page.frameLocator('iframe').frameLocator('iframe');
100
+ const overlay = iframe.locator('#__sunpeak-dev-timing');
101
+ await expect(overlay).toBeAttached();
102
+
103
+ const styles = await overlay.evaluate((el) => {
104
+ const s = window.getComputedStyle(el);
105
+ return {
106
+ position: s.position,
107
+ zIndex: s.zIndex,
108
+ fontFamily: s.fontFamily,
109
+ };
110
+ });
111
+
112
+ expect(styles.position).toBe('fixed');
113
+ expect(Number(styles.zIndex)).toBe(2147483647);
114
+ // Monospace font family
115
+ expect(styles.fontFamily).toMatch(/monospace/i);
116
+ });
117
+ });
118
+ }
@@ -0,0 +1,13 @@
1
+ import {
2
+ createInspectorUrl as _createInspectorUrl,
3
+ type InspectorUrlParams,
4
+ } from 'sunpeak/chatgpt';
5
+
6
+ /**
7
+ * Wrapper around createInspectorUrl that hides the dev overlay by default.
8
+ * The overlay shows resource timestamps and tool timing, which can interfere
9
+ * with element assertions in e2e tests.
10
+ */
11
+ export function createInspectorUrl(params: InspectorUrlParams, basePath?: string): string {
12
+ return _createInspectorUrl({ devOverlay: false, ...params }, basePath);
13
+ }
@@ -1,5 +1,5 @@
1
1
  import { test, expect } from '@playwright/test';
2
- import { createInspectorUrl } from 'sunpeak/chatgpt';
2
+ import { createInspectorUrl } from './helpers';
3
3
 
4
4
  const hosts = ['chatgpt', 'claude'] as const;
5
5
 
@@ -1,5 +1,5 @@
1
1
  import { test, expect } from '@playwright/test';
2
- import { createInspectorUrl } from 'sunpeak/chatgpt';
2
+ import { createInspectorUrl } from './helpers';
3
3
 
4
4
  const hosts = ['chatgpt', 'claude'] as const;
5
5
 
@@ -1,3 +1,3 @@
1
1
  import { defineLiveConfig } from 'sunpeak/test/config';
2
2
 
3
- export default defineLiveConfig();
3
+ export default defineLiveConfig({ devOverlay: false });