twd-relay 0.2.0 → 0.2.1

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.
@@ -1 +1 @@
1
- "use strict";var k=Object.create;var T=Object.defineProperty;var b=Object.getOwnPropertyDescriptor;var D=Object.getOwnPropertyNames;var P=Object.getPrototypeOf,A=Object.prototype.hasOwnProperty;var L=(n,o,c,d)=>{if(o&&typeof o=="object"||typeof o=="function")for(let a of D(o))!A.call(n,a)&&a!==c&&T(n,a,{get:()=>o[a],enumerable:!(d=b(o,a))||d.enumerable});return n};var $=(n,o,c)=>(c=n!=null?k(P(n)):{},L(o||!n||!n.__esModule?T(c,"default",{value:n,enumerable:!0}):c,n));Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});function I(){return`${window.location.protocol==="https:"?"wss:":"ws:"}//${window.location.host}/__twd/ws`}function p(n,o){if(!n.parent)return"";const c=o.get(n.parent);return c?c.name:""}function M(n){const o=n?.url??I(),c=n?.reconnect??!0,d=n?.reconnectInterval??2e3,a="[twd-relay]";let t=null,m=!1,w=null;function i(r){t&&t.readyState===WebSocket.OPEN&&t.send(JSON.stringify(r))}function u(){window.dispatchEvent(new CustomEvent("twd:state-change"))}async function _(){const r=window.__TWD_STATE__;if(!r){i({type:"error",code:"NO_TWD",message:"TWD not initialized"});return}const s=r.handlers,y=Array.from(s.values()).filter(e=>e.type==="test").length;i({type:"run:start",testCount:y});let l=0,h=0,E=0;const g=performance.now(),O={onStart(e){e.status="running",u(),i({type:"test:start",id:e.id,name:e.name,suite:p(e,s)})},onPass(e){l++,e.status="pass",u(),i({type:"test:pass",id:e.id,name:e.name,suite:p(e,s),duration:performance.now()-g})},onFail(e,f){h++,e.status="fail",e.logs=[f.message],u(),i({type:"test:fail",id:e.id,name:e.name,suite:p(e,s),error:f.message,duration:performance.now()-g})},onSkip(e){E++,e.status="skip",u(),i({type:"test:skip",id:e.id,name:e.name,suite:p(e,s)})},onSuiteStart(e){e.status="running",u()},onSuiteEnd(e){e.status="idle",u()}};try{const{TestRunner:e}=await import("twd-js/runner");await new e(O).runAll()}catch(e){const f=e instanceof Error?e.message:String(e);i({type:"error",code:"RUNNER_ERROR",message:f})}const R=performance.now()-g;i({type:"run:complete",passed:l,failed:h,skipped:E,duration:R}),u()}function C(){const r=window.__TWD_STATE__;if(!r){i({type:"error",code:"NO_TWD",message:"TWD not initialized"});return}const s=r.handlers,y=[];for(const[,l]of s)l.type==="test"&&y.push({id:l.id,name:l.name,suite:p(l,s),status:l.status??"idle"});i({type:"status:result",tests:y})}function N(r){let s;try{s=JSON.parse(r.data)}catch{return}s.type==="run"?(console.info(a,"Received run command — running tests..."),_()):s.type==="status"&&C()}function v(){c&&!m&&(console.info(a,`Reconnecting in ${d}ms...`),w=setTimeout(()=>{S()},d))}function S(){t&&(t.readyState===WebSocket.OPEN||t.readyState===WebSocket.CONNECTING)||(m=!1,console.info(a,"Connecting to",o),t=new WebSocket(o),t.addEventListener("open",()=>{i({type:"hello",role:"browser"}),console.info(a,"Connected to relay — ready to receive run/status commands")}),t.addEventListener("message",N),t.addEventListener("close",r=>{t=null,m||console.info(a,"Disconnected",r.code?`(code ${r.code})`:"",r.reason||""),v()}),t.addEventListener("error",()=>{}))}function W(){m=!0,w&&(clearTimeout(w),w=null),t&&(t.close(1e3,"Client disconnecting"),t=null)}return{connect:S,disconnect:W,get connected(){return t!==null&&t.readyState===WebSocket.OPEN}}}exports.createBrowserClient=M;
1
+ "use strict";var P=Object.create;var C=Object.defineProperty;var A=Object.getOwnPropertyDescriptor;var L=Object.getOwnPropertyNames;var $=Object.getPrototypeOf,z=Object.prototype.hasOwnProperty;var I=(n,o,i,f)=>{if(o&&typeof o=="object"||typeof o=="function")for(let l of L(o))!z.call(n,l)&&l!==i&&C(n,l,{get:()=>o[l],enumerable:!(f=A(o,l))||f.enumerable});return n};var M=(n,o,i)=>(i=n!=null?P($(n)):{},I(o||!n||!n.__esModule?C(i,"default",{value:n,enumerable:!0}):i,n));Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});function j(){return`${window.location.protocol==="https:"?"wss:":"ws:"}//${window.location.host}/__twd/ws`}function p(n,o){if(!n.parent)return"";const i=o.get(n.parent);return i?i.name:""}function B(n){const o=n?.url??j(),i=n?.reconnect??!0,f=n?.reconnectInterval??2e3,l=n?.log??!1,T="[twd-relay]";function m(...t){l&&console.info(T,...t)}function S(...t){console.warn(T,...t)}let r=null,w=!1,g=null;function a(t){r&&r.readyState===WebSocket.OPEN&&r.send(JSON.stringify(t))}function u(){window.dispatchEvent(new CustomEvent("twd:state-change"))}async function N(){const t=window.__TWD_STATE__;if(!t){S("TWD not initialized — make sure twd-js is loaded before running tests"),a({type:"error",code:"NO_TWD",message:"TWD not initialized"});return}const s=t.handlers,y=Array.from(s.values()).filter(e=>e.type==="test").length;a({type:"run:start",testCount:y});let c=0,_=0,b=0;const h=performance.now(),O={onStart(e){e.status="running",u(),a({type:"test:start",id:e.id,name:e.name,suite:p(e,s)})},onPass(e){c++,e.status="pass",u(),a({type:"test:pass",id:e.id,name:e.name,suite:p(e,s),duration:performance.now()-h})},onFail(e,d){_++,e.status="fail",e.logs=[d.message],u(),a({type:"test:fail",id:e.id,name:e.name,suite:p(e,s),error:d.message,duration:performance.now()-h})},onSkip(e){b++,e.status="skip",u(),a({type:"test:skip",id:e.id,name:e.name,suite:p(e,s)})},onSuiteStart(e){e.status="running",u()},onSuiteEnd(e){e.status="idle",u()}};try{const{TestRunner:e}=await import("twd-js/runner");await new e(O).runAll()}catch(e){const d=e instanceof Error?e.message:String(e);S("Runner error:",d),a({type:"error",code:"RUNNER_ERROR",message:d})}const D=performance.now()-h;a({type:"run:complete",passed:c,failed:_,skipped:b,duration:D}),u()}function R(){const t=window.__TWD_STATE__;if(!t){a({type:"error",code:"NO_TWD",message:"TWD not initialized"});return}const s=t.handlers,y=[];for(const[,c]of s)c.type==="test"&&y.push({id:c.id,name:c.name,suite:p(c,s),status:c.status??"idle"});a({type:"status:result",tests:y})}function W(t){let s;try{s=JSON.parse(t.data)}catch{return}s.type==="run"?(m("Received run command — running tests..."),N()):s.type==="status"&&R()}function k(){i&&!w&&(m(`Reconnecting in ${f}ms...`),g=setTimeout(()=>{E()},f))}function E(){r&&(r.readyState===WebSocket.OPEN||r.readyState===WebSocket.CONNECTING)||(w=!1,m("Connecting to",o),r=new WebSocket(o),r.addEventListener("open",()=>{a({type:"hello",role:"browser"}),m("Connected to relay — ready to receive run/status commands")}),r.addEventListener("message",W),r.addEventListener("close",t=>{if(r=null,t.reason==="Replaced by new browser"){S("Another browser instance connected — this instance will not reconnect");return}w||m("Disconnected",t.code?`(code ${t.code})`:"",t.reason||""),k()}),r.addEventListener("error",()=>{}))}function v(){w=!0,g&&(clearTimeout(g),g=null),r&&(r.close(1e3,"Client disconnecting"),r=null)}return{connect:E,disconnect:v,get connected(){return r!==null&&r.readyState===WebSocket.OPEN}}}exports.createBrowserClient=B;
package/dist/browser.d.ts CHANGED
@@ -11,6 +11,8 @@ export declare interface BrowserClientOptions {
11
11
  reconnect?: boolean;
12
12
  /** Milliseconds between reconnect attempts. Default: 2000 */
13
13
  reconnectInterval?: number;
14
+ /** Enable console logging. Default: false */
15
+ log?: boolean;
14
16
  }
15
17
 
16
18
  export declare function createBrowserClient(options?: BrowserClientOptions): BrowserClient;
@@ -1,29 +1,35 @@
1
- function k() {
1
+ function O() {
2
2
  return `${window.location.protocol === "https:" ? "wss:" : "ws:"}//${window.location.host}/__twd/ws`;
3
3
  }
4
- function l(a, d) {
5
- if (!a.parent) return "";
6
- const f = d.get(a.parent);
4
+ function l(s, d) {
5
+ if (!s.parent) return "";
6
+ const f = d.get(s.parent);
7
7
  return f ? f.name : "";
8
8
  }
9
- function O(a) {
10
- const d = a?.url ?? k(), f = a?.reconnect ?? !0, g = a?.reconnectInterval ?? 2e3, c = "[twd-relay]";
11
- let n = null, p = !1, m = null;
12
- function r(t) {
13
- n && n.readyState === WebSocket.OPEN && n.send(JSON.stringify(t));
9
+ function A(s) {
10
+ const d = s?.url ?? O(), f = s?.reconnect ?? !0, S = s?.reconnectInterval ?? 2e3, N = s?.log ?? !1, h = "[twd-relay]";
11
+ function u(...n) {
12
+ N && console.info(h, ...n);
13
+ }
14
+ function g(...n) {
15
+ console.warn(h, ...n);
16
+ }
17
+ let t = null, p = !1, m = null;
18
+ function r(n) {
19
+ t && t.readyState === WebSocket.OPEN && t.send(JSON.stringify(n));
14
20
  }
15
21
  function i() {
16
22
  window.dispatchEvent(new CustomEvent("twd:state-change"));
17
23
  }
18
- async function T() {
19
- const t = window.__TWD_STATE__;
20
- if (!t) {
21
- r({ type: "error", code: "NO_TWD", message: "TWD not initialized" });
24
+ async function C() {
25
+ const n = window.__TWD_STATE__;
26
+ if (!n) {
27
+ g("TWD not initialized — make sure twd-js is loaded before running tests"), r({ type: "error", code: "NO_TWD", message: "TWD not initialized" });
22
28
  return;
23
29
  }
24
- const o = t.handlers, w = Array.from(o.values()).filter((e) => e.type === "test").length;
30
+ const o = n.handlers, w = Array.from(o.values()).filter((e) => e.type === "test").length;
25
31
  r({ type: "run:start", testCount: w });
26
- let s = 0, h = 0, E = 0;
32
+ let a = 0, T = 0, _ = 0;
27
33
  const y = performance.now(), v = {
28
34
  onStart(e) {
29
35
  e.status = "running", i(), r({
@@ -34,7 +40,7 @@ function O(a) {
34
40
  });
35
41
  },
36
42
  onPass(e) {
37
- s++, e.status = "pass", i(), r({
43
+ a++, e.status = "pass", i(), r({
38
44
  type: "test:pass",
39
45
  id: e.id,
40
46
  name: e.name,
@@ -42,18 +48,18 @@ function O(a) {
42
48
  duration: performance.now() - y
43
49
  });
44
50
  },
45
- onFail(e, u) {
46
- h++, e.status = "fail", e.logs = [u.message], i(), r({
51
+ onFail(e, c) {
52
+ T++, e.status = "fail", e.logs = [c.message], i(), r({
47
53
  type: "test:fail",
48
54
  id: e.id,
49
55
  name: e.name,
50
56
  suite: l(e, o),
51
- error: u.message,
57
+ error: c.message,
52
58
  duration: performance.now() - y
53
59
  });
54
60
  },
55
61
  onSkip(e) {
56
- E++, e.status = "skip", i(), r({
62
+ _++, e.status = "skip", i(), r({
57
63
  type: "test:skip",
58
64
  id: e.id,
59
65
  name: e.name,
@@ -71,61 +77,65 @@ function O(a) {
71
77
  const { TestRunner: e } = await import("twd-js/runner");
72
78
  await new e(v).runAll();
73
79
  } catch (e) {
74
- const u = e instanceof Error ? e.message : String(e);
75
- r({ type: "error", code: "RUNNER_ERROR", message: u });
80
+ const c = e instanceof Error ? e.message : String(e);
81
+ g("Runner error:", c), r({ type: "error", code: "RUNNER_ERROR", message: c });
76
82
  }
77
- const R = performance.now() - y;
78
- r({ type: "run:complete", passed: s, failed: h, skipped: E, duration: R }), i();
83
+ const D = performance.now() - y;
84
+ r({ type: "run:complete", passed: a, failed: T, skipped: _, duration: D }), i();
79
85
  }
80
- function _() {
81
- const t = window.__TWD_STATE__;
82
- if (!t) {
86
+ function R() {
87
+ const n = window.__TWD_STATE__;
88
+ if (!n) {
83
89
  r({ type: "error", code: "NO_TWD", message: "TWD not initialized" });
84
90
  return;
85
91
  }
86
- const o = t.handlers, w = [];
87
- for (const [, s] of o)
88
- s.type === "test" && w.push({
89
- id: s.id,
90
- name: s.name,
91
- suite: l(s, o),
92
- status: s.status ?? "idle"
92
+ const o = n.handlers, w = [];
93
+ for (const [, a] of o)
94
+ a.type === "test" && w.push({
95
+ id: a.id,
96
+ name: a.name,
97
+ suite: l(a, o),
98
+ status: a.status ?? "idle"
93
99
  });
94
100
  r({ type: "status:result", tests: w });
95
101
  }
96
- function N(t) {
102
+ function W(n) {
97
103
  let o;
98
104
  try {
99
- o = JSON.parse(t.data);
105
+ o = JSON.parse(n.data);
100
106
  } catch {
101
107
  return;
102
108
  }
103
- o.type === "run" ? (console.info(c, "Received run command — running tests..."), T()) : o.type === "status" && _();
109
+ o.type === "run" ? (u("Received run command — running tests..."), C()) : o.type === "status" && R();
104
110
  }
105
- function C() {
106
- f && !p && (console.info(c, `Reconnecting in ${g}ms...`), m = setTimeout(() => {
107
- S();
108
- }, g));
111
+ function b() {
112
+ f && !p && (u(`Reconnecting in ${S}ms...`), m = setTimeout(() => {
113
+ E();
114
+ }, S));
109
115
  }
110
- function S() {
111
- n && (n.readyState === WebSocket.OPEN || n.readyState === WebSocket.CONNECTING) || (p = !1, console.info(c, "Connecting to", d), n = new WebSocket(d), n.addEventListener("open", () => {
112
- r({ type: "hello", role: "browser" }), console.info(c, "Connected to relay — ready to receive run/status commands");
113
- }), n.addEventListener("message", N), n.addEventListener("close", (t) => {
114
- n = null, p || console.info(c, "Disconnected", t.code ? `(code ${t.code})` : "", t.reason || ""), C();
115
- }), n.addEventListener("error", () => {
116
+ function E() {
117
+ t && (t.readyState === WebSocket.OPEN || t.readyState === WebSocket.CONNECTING) || (p = !1, u("Connecting to", d), t = new WebSocket(d), t.addEventListener("open", () => {
118
+ r({ type: "hello", role: "browser" }), u("Connected to relay — ready to receive run/status commands");
119
+ }), t.addEventListener("message", W), t.addEventListener("close", (n) => {
120
+ if (t = null, n.reason === "Replaced by new browser") {
121
+ g("Another browser instance connected — this instance will not reconnect");
122
+ return;
123
+ }
124
+ p || u("Disconnected", n.code ? `(code ${n.code})` : "", n.reason || ""), b();
125
+ }), t.addEventListener("error", () => {
116
126
  }));
117
127
  }
118
- function W() {
119
- p = !0, m && (clearTimeout(m), m = null), n && (n.close(1e3, "Client disconnecting"), n = null);
128
+ function k() {
129
+ p = !0, m && (clearTimeout(m), m = null), t && (t.close(1e3, "Client disconnecting"), t = null);
120
130
  }
121
131
  return {
122
- connect: S,
123
- disconnect: W,
132
+ connect: E,
133
+ disconnect: k,
124
134
  get connected() {
125
- return n !== null && n.readyState === WebSocket.OPEN;
135
+ return t !== null && t.readyState === WebSocket.OPEN;
126
136
  }
127
137
  };
128
138
  }
129
139
  export {
130
- O as createBrowserClient
140
+ A as createBrowserClient
131
141
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "twd-relay",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "WebSocket relay for TWD — enables AI agents and external tools to run and observe in-browser tests",
5
5
  "license": "MIT",
6
6
  "author": "BRIKEV",