@molecule/app-e2e-preview 1.0.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/dist/server.js ADDED
@@ -0,0 +1,239 @@
1
+ /**
2
+ * The hub: a WebSocket endpoint attached to the dev server's HTTP server.
3
+ * Preview pages connect as `role=page` (from the browser, same origin through
4
+ * whatever proxy serves the preview); the test runner connects as
5
+ * `role=driver` (loopback only, with the hub's token). The hub forwards each
6
+ * driver command to a page and the page's reply back, and broadcasts page
7
+ * events (hello, navigated, console, pageerror, dialog, closed) to drivers.
8
+ *
9
+ * @module
10
+ */
11
+ import { randomUUID } from 'node:crypto';
12
+ import { unlinkSync, writeFileSync } from 'node:fs';
13
+ import process from 'node:process';
14
+ import { WebSocketServer } from 'ws';
15
+ import { E2E_WS_PATH, tokenFilePath } from './types.js';
16
+ const LOOPBACK = new Set(['127.0.0.1', '::1', '::ffff:127.0.0.1']);
17
+ const isLoopback = (address) => !!address && LOOPBACK.has(address);
18
+ /**
19
+ * Attach the hub to an HTTP server (Vite's `server.httpServer`). Safe next to
20
+ * Vite's own HMR upgrade listener: each ignores the other's path.
21
+ */
22
+ export const attachE2EHub = (httpServer, options = {}) => {
23
+ const path = options.path ?? E2E_WS_PATH;
24
+ const token = options.token ?? process.env['MOL_E2E_TOKEN'] ?? randomUUID();
25
+ const wss = new WebSocketServer({ noServer: true });
26
+ const pages = new Map();
27
+ const drivers = new Set();
28
+ const pending = new Map();
29
+ let tokenFile = null;
30
+ const sendTo = (ws, obj) => {
31
+ if (ws.readyState === ws.OPEN)
32
+ ws.send(JSON.stringify(obj));
33
+ };
34
+ const broadcast = (obj) => {
35
+ for (const d of drivers)
36
+ sendTo(d, obj);
37
+ };
38
+ const failPending = (pageId) => {
39
+ for (const [id, p] of pending) {
40
+ if (p.pageId !== pageId)
41
+ continue;
42
+ pending.delete(id);
43
+ sendTo(p.driver, {
44
+ id,
45
+ ok: false,
46
+ error: 'the page navigated away or closed before it replied',
47
+ pageClosed: true,
48
+ pageId,
49
+ });
50
+ }
51
+ };
52
+ const pickPage = (pageId) => {
53
+ if (pageId)
54
+ return pages.get(pageId);
55
+ const all = Array.from(pages.values());
56
+ const visible = all.filter((p) => !p.peer.hidden);
57
+ const pool = visible.length ? visible : all;
58
+ return pool.sort((a, b) => b.peer.lastSeen - a.peer.lastSeen)[0];
59
+ };
60
+ const onPage = (ws, id) => {
61
+ // A page counts as connected once it has said hello (href, title, visibility);
62
+ // until then a driver's `list` does not see it and no command can target it.
63
+ const peer = {
64
+ id,
65
+ href: '',
66
+ title: '',
67
+ hidden: false,
68
+ framed: false,
69
+ connectedAt: Date.now(),
70
+ lastSeen: Date.now(),
71
+ };
72
+ let announced = false;
73
+ const keepalive = setInterval(() => {
74
+ try {
75
+ ws.ping();
76
+ }
77
+ catch (_error) {
78
+ /* closing */
79
+ }
80
+ }, 25_000);
81
+ ws.on('message', (data) => {
82
+ let msg;
83
+ try {
84
+ msg = JSON.parse(String(data));
85
+ }
86
+ catch (_error) {
87
+ return;
88
+ }
89
+ peer.lastSeen = Date.now();
90
+ if (typeof msg.href === 'string')
91
+ peer.href = msg.href;
92
+ if (msg.hello) {
93
+ peer.title = String(msg.title ?? '');
94
+ peer.hidden = Boolean(msg.hidden);
95
+ peer.framed = Boolean(msg.framed);
96
+ pages.set(id, { peer, ws });
97
+ announced = true;
98
+ broadcast({
99
+ event: 'page-hello',
100
+ pageId: id,
101
+ ...peer,
102
+ readyState: msg.readyState,
103
+ innerWidth: msg.innerWidth,
104
+ innerHeight: msg.innerHeight,
105
+ });
106
+ return;
107
+ }
108
+ if (typeof msg.id === 'string' && pending.has(msg.id)) {
109
+ const p = pending.get(msg.id);
110
+ pending.delete(msg.id);
111
+ sendTo(p.driver, { ...msg, pageId: id });
112
+ return;
113
+ }
114
+ if (typeof msg.event === 'string') {
115
+ if (msg.event === 'visibility')
116
+ peer.hidden = Boolean(msg.hidden);
117
+ if (msg.event === 'navigated' && typeof msg.title === 'string')
118
+ peer.title = msg.title;
119
+ broadcast({ ...msg, pageId: id });
120
+ }
121
+ });
122
+ ws.on('close', () => {
123
+ clearInterval(keepalive);
124
+ if (!announced)
125
+ return;
126
+ pages.delete(id);
127
+ failPending(id);
128
+ broadcast({ event: 'page-closed', pageId: id });
129
+ });
130
+ ws.on('error', () => {
131
+ /* close follows */
132
+ });
133
+ };
134
+ const onDriver = (ws) => {
135
+ drivers.add(ws);
136
+ ws.on('message', (data) => {
137
+ let msg;
138
+ try {
139
+ msg = JSON.parse(String(data));
140
+ }
141
+ catch (_error) {
142
+ return;
143
+ }
144
+ const id = typeof msg.id === 'string' ? msg.id : randomUUID();
145
+ if (msg.op === 'list') {
146
+ sendTo(ws, { id, ok: true, value: Array.from(pages.values()).map((p) => p.peer) });
147
+ return;
148
+ }
149
+ if (msg.op === 'cmd') {
150
+ const target = pickPage(typeof msg.pageId === 'string' ? msg.pageId : undefined);
151
+ if (!target) {
152
+ sendTo(ws, { id, ok: false, error: 'no-page', noPage: true });
153
+ return;
154
+ }
155
+ pending.set(id, { driver: ws, pageId: target.peer.id });
156
+ sendTo(target.ws, { ...msg.cmd, id });
157
+ return;
158
+ }
159
+ sendTo(ws, { id, ok: false, error: 'unknown driver op: ' + String(msg.op) });
160
+ });
161
+ ws.on('close', () => {
162
+ drivers.delete(ws);
163
+ for (const [id, p] of pending)
164
+ if (p.driver === ws)
165
+ pending.delete(id);
166
+ });
167
+ ws.on('error', () => {
168
+ /* close follows */
169
+ });
170
+ };
171
+ const onUpgrade = (req, socket, head) => {
172
+ const url = new URL(req.url ?? '/', 'http://localhost');
173
+ if (url.pathname !== path)
174
+ return;
175
+ const role = url.searchParams.get('role');
176
+ if (role === 'driver') {
177
+ const remote = req.socket.remoteAddress;
178
+ if (!isLoopback(remote) || url.searchParams.get('token') !== token) {
179
+ socket.write('HTTP/1.1 403 Forbidden\r\nConnection: close\r\n\r\n');
180
+ socket.destroy();
181
+ return;
182
+ }
183
+ wss.handleUpgrade(req, socket, head, (ws) => onDriver(ws));
184
+ return;
185
+ }
186
+ if (role === 'page') {
187
+ const id = url.searchParams.get('id') || randomUUID();
188
+ wss.handleUpgrade(req, socket, head, (ws) => onPage(ws, id));
189
+ return;
190
+ }
191
+ socket.destroy();
192
+ };
193
+ httpServer.on('upgrade', onUpgrade);
194
+ const writeToken = () => {
195
+ const address = httpServer.address();
196
+ const port = address && typeof address === 'object' ? address.port : null;
197
+ if (!port)
198
+ return;
199
+ tokenFile = tokenFilePath(port);
200
+ try {
201
+ writeFileSync(tokenFile, JSON.stringify({ token, port, path, pid: process.pid }), {
202
+ mode: 0o600,
203
+ });
204
+ }
205
+ catch (_error) {
206
+ /* a read-only tmpdir: the driver can still use MOL_E2E_TOKEN */
207
+ }
208
+ };
209
+ const removeToken = () => {
210
+ if (!tokenFile)
211
+ return;
212
+ try {
213
+ unlinkSync(tokenFile);
214
+ }
215
+ catch (_error) {
216
+ /* already gone */
217
+ }
218
+ tokenFile = null;
219
+ };
220
+ if (httpServer.listening)
221
+ writeToken();
222
+ else
223
+ httpServer.once('listening', writeToken);
224
+ httpServer.once('close', removeToken);
225
+ return {
226
+ token,
227
+ pages: () => Array.from(pages.values()).map((p) => p.peer),
228
+ close: () => {
229
+ httpServer.off('upgrade', onUpgrade);
230
+ for (const p of pages.values())
231
+ p.ws.close();
232
+ for (const d of drivers)
233
+ d.close();
234
+ wss.close();
235
+ removeToken();
236
+ },
237
+ };
238
+ };
239
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Shapes shared by the three halves of the preview bond: the page client, the
3
+ * dev-server WebSocket hub, and the sandbox-side driver.
4
+ *
5
+ * @module
6
+ */
7
+ import type { E2EConnectOptions } from '@molecule/app-e2e';
8
+ /** WebSocket path the hub listens on (same origin as the previewed page). */
9
+ export declare const E2E_WS_PATH = "/__mol/e2e";
10
+ /** Path the page client script is served from (dev and `vite preview`). */
11
+ export declare const E2E_CLIENT_PATH = "/__mol/e2e-client.js";
12
+ /** The hub writes its driver token here so a runner on the same machine can find it. */
13
+ export declare const tokenFilePath: (port: number) => string;
14
+ /** Options for `provider.connect()` beyond the core's. */
15
+ export interface PreviewConnectOptions extends E2EConnectOptions {
16
+ /** Full hub URL (`ws://127.0.0.1:5173/__mol/e2e`); overrides port discovery. */
17
+ url?: string;
18
+ /** Dev-server port to try first (the sandbox serves the preview on 5173). */
19
+ port?: number;
20
+ /** Driver token; defaults to `MOL_E2E_TOKEN` or the hub's token file. */
21
+ token?: string;
22
+ /** Drive one specific page (an id from `listPages()`); defaults to the most recently seen visible page. */
23
+ pageId?: string;
24
+ /** How long to wait for a preview page to be connected before failing, ms. */
25
+ connectTimeout?: number;
26
+ }
27
+ /** A page currently connected to the hub. */
28
+ export interface PagePeer {
29
+ id: string;
30
+ href: string;
31
+ title: string;
32
+ hidden: boolean;
33
+ framed: boolean;
34
+ connectedAt: number;
35
+ lastSeen: number;
36
+ }
37
+ /** Hub → driver event envelope. */
38
+ export interface HubEvent {
39
+ event: string;
40
+ pageId?: string;
41
+ [key: string]: unknown;
42
+ }
43
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AAE1D,6EAA6E;AAC7E,eAAO,MAAM,WAAW,eAAe,CAAA;AAEvC,2EAA2E;AAC3E,eAAO,MAAM,eAAe,yBAAyB,CAAA;AAErD,wFAAwF;AACxF,eAAO,MAAM,aAAa,GAAI,MAAM,MAAM,KAAG,MAAgD,CAAA;AAE7F,0DAA0D;AAC1D,MAAM,WAAW,qBAAsB,SAAQ,iBAAiB;IAC9D,gFAAgF;IAChF,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,6EAA6E;IAC7E,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,yEAAyE;IACzE,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,2GAA2G;IAC3G,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,8EAA8E;IAC9E,cAAc,CAAC,EAAE,MAAM,CAAA;CACxB;AAED,6CAA6C;AAC7C,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,OAAO,CAAA;IACf,MAAM,EAAE,OAAO,CAAA;IACf,WAAW,EAAE,MAAM,CAAA;IACnB,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED,mCAAmC;AACnC,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CACvB"}
package/dist/types.js ADDED
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Shapes shared by the three halves of the preview bond: the page client, the
3
+ * dev-server WebSocket hub, and the sandbox-side driver.
4
+ *
5
+ * @module
6
+ */
7
+ import { tmpdir } from 'node:os';
8
+ import { join } from 'node:path';
9
+ /** WebSocket path the hub listens on (same origin as the previewed page). */
10
+ export const E2E_WS_PATH = '/__mol/e2e';
11
+ /** Path the page client script is served from (dev and `vite preview`). */
12
+ export const E2E_CLIENT_PATH = '/__mol/e2e-client.js';
13
+ /** The hub writes its driver token here so a runner on the same machine can find it. */
14
+ export const tokenFilePath = (port) => join(tmpdir(), `mol-e2e-${port}.json`);
15
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AAChC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAIhC,6EAA6E;AAC7E,MAAM,CAAC,MAAM,WAAW,GAAG,YAAY,CAAA;AAEvC,2EAA2E;AAC3E,MAAM,CAAC,MAAM,eAAe,GAAG,sBAAsB,CAAA;AAErD,wFAAwF;AACxF,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,IAAY,EAAU,EAAE,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,WAAW,IAAI,OAAO,CAAC,CAAA"}
package/dist/vite.d.ts ADDED
@@ -0,0 +1,22 @@
1
+ /**
2
+ * The Vite plugin: serves the page client, injects it into every dev and
3
+ * `vite preview` document, and attaches the hub to the server. Inert in
4
+ * `vite build` — production HTML never carries the client.
5
+ *
6
+ * @module
7
+ */
8
+ import type { Plugin } from 'vite';
9
+ /** Options for {@link molE2EPreviewPlugin}. */
10
+ export interface MolE2EPreviewPluginOptions {
11
+ /** Turn the plugin off (also `MOL_E2E_PREVIEW_PLUGIN=0`). Default on. */
12
+ enabled?: boolean;
13
+ }
14
+ /** Put the client tag at the top of `<head>` unless it is already there. */
15
+ export declare const injectE2EClientTag: (html: string) => string;
16
+ /**
17
+ * The Vite plugin every scaffolded app carries (through its scaffold-owned
18
+ * preview plugin file). Dev and preview servers get the hub and the client;
19
+ * builds are untouched.
20
+ */
21
+ export declare function molE2EPreviewPlugin(options?: MolE2EPreviewPluginOptions): Plugin;
22
+ //# sourceMappingURL=vite.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vite.d.ts","sourceRoot":"","sources":["../src/vite.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAKH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAA;AAMlC,+CAA+C;AAC/C,MAAM,WAAW,0BAA0B;IACzC,yEAAyE;IACzE,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB;AAOD,4EAA4E;AAC5E,eAAO,MAAM,kBAAkB,GAAI,MAAM,MAAM,KAAG,MAIjD,CAAA;AA6DD;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,GAAE,0BAA+B,GAAG,MAAM,CAgCpF"}
package/dist/vite.js ADDED
@@ -0,0 +1,131 @@
1
+ /**
2
+ * The Vite plugin: serves the page client, injects it into every dev and
3
+ * `vite preview` document, and attaches the hub to the server. Inert in
4
+ * `vite build` — production HTML never carries the client.
5
+ *
6
+ * @module
7
+ */
8
+ import process from 'node:process';
9
+ import { E2E_PREVIEW_CLIENT_SCRIPT } from './client.js';
10
+ import { attachE2EHub } from './server.js';
11
+ import { E2E_CLIENT_PATH } from './types.js';
12
+ const TAG = `<script src="${E2E_CLIENT_PATH}" data-mol-e2e></script>`;
13
+ /** Put the client tag at the top of `<head>` unless it is already there. */
14
+ export const injectE2EClientTag = (html) => {
15
+ if (html.includes('data-mol-e2e'))
16
+ return html;
17
+ if (/<head[^>]*>/i.test(html))
18
+ return html.replace(/<head[^>]*>/i, (m) => m + TAG);
19
+ return TAG + html;
20
+ };
21
+ const serveClient = (req, res, next) => {
22
+ if ((req.url ?? '').split('?')[0] !== E2E_CLIENT_PATH)
23
+ return next();
24
+ res.setHeader('content-type', 'text/javascript; charset=utf-8');
25
+ res.setHeader('cache-control', 'no-store');
26
+ res.end(E2E_PREVIEW_CLIENT_SCRIPT);
27
+ };
28
+ /**
29
+ * `vite preview` serves built files as-is, so the client is spliced into HTML
30
+ * responses on the way out (navigations only — requests that accept HTML).
31
+ */
32
+ const injectIntoPreviewHtml = (req, res, next) => {
33
+ if (req.method !== 'GET' && req.method !== 'HEAD')
34
+ return next();
35
+ if (!String(req.headers.accept ?? '').includes('text/html'))
36
+ return next();
37
+ const chunks = [];
38
+ let isHtml = false;
39
+ const check = () => {
40
+ isHtml = String(res.getHeader('content-type') ?? '').includes('text/html');
41
+ };
42
+ const origSetHeader = res.setHeader.bind(res);
43
+ const origWriteHead = res.writeHead.bind(res);
44
+ const origWrite = res.write.bind(res);
45
+ const origEnd = res.end.bind(res);
46
+ res.setHeader = ((name, value) => {
47
+ origSetHeader(name, value);
48
+ if (name.toLowerCase() === 'content-type')
49
+ check();
50
+ return res;
51
+ });
52
+ res.writeHead = ((status, ...rest) => {
53
+ const headers = rest.find((r) => r && typeof r === 'object' && !Array.isArray(r));
54
+ if (headers)
55
+ for (const [k, v] of Object.entries(headers))
56
+ origSetHeader(k, v);
57
+ check();
58
+ if (isHtml)
59
+ res.removeHeader('content-length');
60
+ const message = typeof rest[0] === 'string' ? rest[0] : undefined;
61
+ return message ? origWriteHead(status, message) : origWriteHead(status);
62
+ });
63
+ res.write = ((chunk, ...args) => {
64
+ check();
65
+ if (!isHtml)
66
+ return origWrite(chunk, ...args);
67
+ chunks.push(Buffer.from(chunk));
68
+ const cb = args.find((a) => typeof a === 'function');
69
+ if (cb)
70
+ cb();
71
+ return true;
72
+ });
73
+ res.end = ((chunk, ...args) => {
74
+ check();
75
+ if (!isHtml)
76
+ return origEnd(chunk, ...args);
77
+ if (chunk && typeof chunk !== 'function')
78
+ chunks.push(Buffer.from(chunk));
79
+ const html = injectE2EClientTag(Buffer.concat(chunks).toString('utf8'));
80
+ if (!res.headersSent) {
81
+ res.removeHeader('content-length');
82
+ origSetHeader('content-length', Buffer.byteLength(html));
83
+ }
84
+ return origEnd(html);
85
+ });
86
+ next();
87
+ };
88
+ /**
89
+ * The Vite plugin every scaffolded app carries (through its scaffold-owned
90
+ * preview plugin file). Dev and preview servers get the hub and the client;
91
+ * builds are untouched.
92
+ */
93
+ export function molE2EPreviewPlugin(options = {}) {
94
+ const enabled = options.enabled ?? process.env['MOL_E2E_PREVIEW_PLUGIN'] !== '0';
95
+ return {
96
+ name: 'molecule:e2e-preview',
97
+ configureServer(server) {
98
+ if (!enabled)
99
+ return;
100
+ if (server.httpServer)
101
+ attachE2EHub(server.httpServer);
102
+ server.middlewares.use(serveClient);
103
+ },
104
+ configurePreviewServer(server) {
105
+ if (!enabled)
106
+ return;
107
+ if (server.httpServer)
108
+ attachE2EHub(server.httpServer);
109
+ server.middlewares.use(serveClient);
110
+ server.middlewares.use(injectIntoPreviewHtml);
111
+ },
112
+ transformIndexHtml: {
113
+ order: 'pre',
114
+ handler(html, ctx) {
115
+ if (!enabled || !ctx.server)
116
+ return html;
117
+ return {
118
+ html,
119
+ tags: [
120
+ {
121
+ tag: 'script',
122
+ attrs: { src: E2E_CLIENT_PATH, 'data-mol-e2e': '' },
123
+ injectTo: 'head-prepend',
124
+ },
125
+ ],
126
+ };
127
+ },
128
+ },
129
+ };
130
+ }
131
+ //# sourceMappingURL=vite.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vite.js","sourceRoot":"","sources":["../src/vite.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,73 @@
1
+ {
2
+ "name": "@molecule/app-e2e-preview",
3
+ "version": "1.0.0",
4
+ "description": "E2E bond that drives the LIVE IDE preview as a Playwright-shaped page — the page the person is already looking at, in their own browser — over a same-origin WebSocket through the dev server. No browser binary in the sandbox.",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "scripts": {
9
+ "build": "tsc",
10
+ "test": "vitest run",
11
+ "test:watch": "vitest"
12
+ },
13
+ "exports": {
14
+ ".": {
15
+ "types": "./dist/index.d.ts",
16
+ "import": "./dist/index.js"
17
+ },
18
+ "./vite": {
19
+ "types": "./dist/vite.d.ts",
20
+ "import": "./dist/vite.js"
21
+ }
22
+ },
23
+ "files": [
24
+ "dist",
25
+ "README.md"
26
+ ],
27
+ "keywords": [
28
+ "molecule",
29
+ "e2e",
30
+ "preview",
31
+ "playwright",
32
+ "vite-plugin"
33
+ ],
34
+ "license": "Apache-2.0",
35
+ "repository": {
36
+ "type": "git",
37
+ "url": "https://github.com/molecule-dev/molecule.git",
38
+ "directory": "packages/app/bonds/e2e/preview"
39
+ },
40
+ "homepage": "https://molecule.dev",
41
+ "bugs": {
42
+ "url": "https://github.com/molecule-dev/molecule/issues"
43
+ },
44
+ "publishConfig": {
45
+ "access": "public"
46
+ },
47
+ "dependencies": {
48
+ "ws": "8.21.1"
49
+ },
50
+ "peerDependencies": {
51
+ "@molecule/app-bond": "^1.0.1",
52
+ "@molecule/app-e2e": "^1.0.0",
53
+ "@molecule/app-e2e-fixtures-default": "^1.0.1",
54
+ "@playwright/test": "^1.40.0",
55
+ "vite": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0"
56
+ },
57
+ "peerDependenciesMeta": {
58
+ "vite": {
59
+ "optional": true
60
+ }
61
+ },
62
+ "devDependencies": {
63
+ "@molecule/app-bond": "1.0.1",
64
+ "@molecule/app-e2e": "1.0.0",
65
+ "@molecule/app-e2e-fixtures-default": "1.0.1",
66
+ "@playwright/test": "1.62.0",
67
+ "@types/node": "26.1.2",
68
+ "@types/ws": "8.18.1",
69
+ "typescript": "6.0.3",
70
+ "vite": "8.1.5",
71
+ "vitest": "4.1.11"
72
+ }
73
+ }