@adcops/autocore-react 3.3.5 → 3.3.8
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/.claude/settings.local.json +7 -0
- package/dist/core/EventEmitterContext.d.ts +1 -0
- package/dist/core/EventEmitterContext.d.ts.map +1 -1
- package/dist/core/EventEmitterContext.js +1 -1
- package/dist/hooks/useAutoCoreTag.d.ts.map +1 -1
- package/dist/hooks/useAutoCoreTag.js +1 -1
- package/dist/hub/DebugPanel.d.ts +11 -0
- package/dist/hub/DebugPanel.d.ts.map +1 -1
- package/dist/hub/DebugPanel.js +1 -1
- package/dist/hub/index.d.ts +1 -0
- package/dist/hub/index.d.ts.map +1 -1
- package/dist/hub/index.js +1 -1
- package/package.json +1 -1
- package/src/core/EventEmitterContext.tsx +8 -1
- package/src/hooks/useAutoCoreTag.ts +83 -83
- package/src/hub/DebugPanel.ts +36 -9
- package/src/hub/index.ts +4 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EventEmitterContext.d.ts","sourceRoot":"","sources":["../../src/core/EventEmitterContext.tsx"],"names":[],"mappings":"AAUA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAEH,OAAO,KAON,MAAM,OAAO,CAAC;AAEf,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,OAAO,CAAC;AACrC,OAAO,EAAa,GAAG,EAAE,MAAM,QAAQ,CAAC;AACxC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,QAAQ,CAAC;AAC7C,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"EventEmitterContext.d.ts","sourceRoot":"","sources":["../../src/core/EventEmitterContext.tsx"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{jsx as _jsx}from"react/jsx-runtime";import React,{createContext,useState,useMemo,useCallback,useRef,useEffect}from"react";import{createHub,Hub}from"../hub";import{MessageType}from"../hub/CommandMessage";export{Hub};const placeholderResponse={data:{},success:!1,error_message:"Context not initialized",transaction_id:0,timecode:0,topic:"",message_type:MessageType.NoOp};export const EventEmitterContext=createContext({state:{subscriptions:{},nextSubscriptionId:1},dispatch:()=>{},subscribe:()=>0,unsubscribe:()=>{},invoke:async()=>placeholderResponse,read:async()=>placeholderResponse,write:async()=>placeholderResponse,serverSubscribe:async(e,t,s)=>placeholderResponse,serverUnsubscribe:async(e,t)=>placeholderResponse,hub:null,getSubscriptions:()=>[],isConnected:()=>!1});export const EventEmitterProvider=({children:e})=>{const[
|
|
1
|
+
import{jsx as _jsx}from"react/jsx-runtime";import React,{createContext,useState,useMemo,useCallback,useRef,useEffect}from"react";import{createHub,Hub}from"../hub";import{MessageType}from"../hub/CommandMessage";import{enableDebugPanel}from"../hub/DebugPanel";export{Hub};const placeholderResponse={data:{},success:!1,error_message:"Context not initialized",transaction_id:0,timecode:0,topic:"",message_type:MessageType.NoOp};export const EventEmitterContext=createContext({state:{subscriptions:{},nextSubscriptionId:1},dispatch:()=>{},subscribe:()=>0,unsubscribe:()=>{},invoke:async()=>placeholderResponse,read:async()=>placeholderResponse,write:async()=>placeholderResponse,serverSubscribe:async(e,t,s)=>placeholderResponse,serverUnsubscribe:async(e,t)=>placeholderResponse,hub:null,getSubscriptions:()=>[],isConnected:()=>!1});export const EventEmitterProvider=({children:e,debug:t=!1})=>{t&&enableDebugPanel();const[s,r]=useState({subscriptions:{},nextSubscriptionId:1}),c=useMemo(()=>createHub(),[]),n=useRef(1),o=useRef({});useEffect(()=>{r(e=>({...e,subscriptions:{...o.current},nextSubscriptionId:n.current}))},[]);const u=useCallback(e=>{const{topic:t,payload:s}=e,r=o.current[t]?.slice()??[];for(const e of r)try{e.callback(s)}catch(e){}},[]),a=useCallback((e,t)=>{const s=n.current++,c={id:s,callback:t},u=[...o.current[e]??[],c];return o.current={...o.current,[e]:u},r(e=>({...e,subscriptions:{...o.current},nextSubscriptionId:n.current})),s},[]),i=useCallback(e=>{const t={};for(const[s,r]of Object.entries(o.current)){const c=r.filter(t=>t.id!==e);c.length>0&&(t[s]=c)}o.current=t,r(e=>({...e,subscriptions:{...t}}))},[]);useEffect(()=>()=>{o.current={},n.current=1},[]),import.meta&&import.meta.hot&&import.meta.hot.dispose(()=>{o.current={},n.current=1});const b=useCallback((e,t,s)=>c.invoke(e,t,s),[c]),l=useCallback((e,t)=>c.read(e,t),[c]),p=useCallback((e,t)=>c.write(e,t),[c]),d=useCallback((e,t,s)=>c.subscribe(e,t,s),[c]),m=useCallback((e,t)=>c.unsubscribe(e,t),[c]),f=useCallback(()=>c.isConnected(),[c]),C=useMemo(()=>({state:s,dispatch:u,subscribe:a,unsubscribe:i,invoke:b,read:l,write:p,serverSubscribe:d,serverUnsubscribe:m,hub:c,getSubscriptions:e=>e?o.current[e]??[]:o.current,isConnected:f}),[s,c,u,a,i,b,l,p,d,m,f]);return useEffect(()=>{c.setContext(C)},[c,C]),_jsx(EventEmitterContext.Provider,{value:C,children:e})};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useAutoCoreTag.d.ts","sourceRoot":"","sources":["../../src/hooks/useAutoCoreTag.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,gBAAgB,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAEzF,wBAAgB,oBAAoB,CAAC,IAAI,SAAS,SAAS,SAAS,EAAE,
|
|
1
|
+
{"version":3,"file":"useAutoCoreTag.d.ts","sourceRoot":"","sources":["../../src/hooks/useAutoCoreTag.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,gBAAgB,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAEzF,wBAAgB,oBAAoB,CAAC,IAAI,SAAS,SAAS,SAAS,EAAE,EAClE,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,gBAAgB,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAC3D,IAAI,EAAE,IAAI;8BAYc,CAAC,2CAA4B,CAAC;;;;;;;+BAyB7B,CAAC,4CAA6B,SAAS,CAAC,EAAE;4BAO/C,CAAC;;kCAYyB,CAAC;;;iCAUpB,CAAC,YAAY,CAAC,GAAG,EAAE,QAAQ,CAAC,OAAO,mBAAM,CAAC,KAAK,CAAC,SAAQ,GAAG,EAAE;;;;;;;uCAW3C,MAAM;;EAKtD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{useCallback,useContext,useMemo}from"react";export function makeAutoCoreTagHooks(e,a){return{useAutoCoreTag:
|
|
1
|
+
import{useCallback,useContext,useMemo}from"react";export function makeAutoCoreTagHooks(e,a){return{useAutoCoreTag:t=>{const{values:s,rawValues:u,isLoading:o,write:r,tap:n}=useContext(e),l=(e=>a.find(a=>a.tagName===e))(t);if(!l)throw new Error(`useAutoCoreTag: unknown tagName '${String(t)}'`);const i=useCallback(e=>r(t,e),[r,t]),c=useCallback(()=>n?.(t),[n,t]);return{value:s[t],rawValue:u[t],write:i,tap:c,isLoading:o}},useAutoCoreTags:a=>{const{values:t,rawValues:s,isLoading:u,write:o}=useContext(e);return{values:useMemo(()=>Object.fromEntries(a.map(e=>[e,t[e]])),[t,a]),rawValues:useMemo(()=>Object.fromEntries(a.map(e=>[e,s[e]])),[s,a]),write:useCallback(async(e,a)=>{await o(e,a)},[o]),isLoading:u}},useAutoCoreSelect:(a,t=[])=>{const{values:s,isLoading:u}=useContext(e);return{selected:useMemo(()=>a(s),[s,...t]),isLoading:u}},useScales:()=>{const{scales:a,updateScale:t}=useContext(e),s=useCallback(e=>a[e],[a]);return{scales:a,updateScale:t,getScale:s}}}}
|
package/dist/hub/DebugPanel.d.ts
CHANGED
|
@@ -26,6 +26,17 @@ declare class DebugPanel {
|
|
|
26
26
|
messageReceived(type: string, command: string, requestId?: number): void;
|
|
27
27
|
updateState(state: string): void;
|
|
28
28
|
}
|
|
29
|
+
/**
|
|
30
|
+
* Returns the current debug panel instance.
|
|
31
|
+
* If the panel has not been enabled, returns a no-op stub so callers
|
|
32
|
+
* don't need to guard every call.
|
|
33
|
+
*/
|
|
29
34
|
export declare function getDebugPanel(): DebugPanel;
|
|
35
|
+
/**
|
|
36
|
+
* Enables the debug panel, injecting it into the DOM.
|
|
37
|
+
* Subsequent calls to `getDebugPanel()` will return the real panel.
|
|
38
|
+
* Safe to call multiple times — only creates one panel.
|
|
39
|
+
*/
|
|
40
|
+
export declare function enableDebugPanel(): void;
|
|
30
41
|
export default getDebugPanel;
|
|
31
42
|
//# sourceMappingURL=DebugPanel.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DebugPanel.d.ts","sourceRoot":"","sources":["../../src/hub/DebugPanel.ts"],"names":[],"mappings":"AAWA,UAAU,QAAQ;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,CAAC;IAClD,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,cAAM,UAAU;IACd,OAAO,CAAC,SAAS,CAA+B;IAChD,OAAO,CAAC,YAAY,CAA+B;IACnD,OAAO,CAAC,cAAc,CAA+B;IACrD,OAAO,CAAC,IAAI,CAAkB;IAC9B,OAAO,CAAC,OAAO,CAAO;IAGtB,OAAO,CAAC,KAAK,CASX;;IAOF,OAAO,CAAC,WAAW;IA2FnB,OAAO,CAAC,aAAa;IAiBrB,OAAO,CAAC,WAAW;IAsBnB,GAAG,CAAC,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI;IAyBlE,OAAO,CAAC,UAAU;IAgBlB,UAAU,IAAI,IAAI;IAMlB,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI;IAOxC,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAO3B,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI;IAO5C,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAM5B,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI;IAMnE,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI;IAMxE,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;CAIjC;
|
|
1
|
+
{"version":3,"file":"DebugPanel.d.ts","sourceRoot":"","sources":["../../src/hub/DebugPanel.ts"],"names":[],"mappings":"AAWA,UAAU,QAAQ;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,CAAC;IAClD,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,cAAM,UAAU;IACd,OAAO,CAAC,SAAS,CAA+B;IAChD,OAAO,CAAC,YAAY,CAA+B;IACnD,OAAO,CAAC,cAAc,CAA+B;IACrD,OAAO,CAAC,IAAI,CAAkB;IAC9B,OAAO,CAAC,OAAO,CAAO;IAGtB,OAAO,CAAC,KAAK,CASX;;IAOF,OAAO,CAAC,WAAW;IA2FnB,OAAO,CAAC,aAAa;IAiBrB,OAAO,CAAC,WAAW;IAsBnB,GAAG,CAAC,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI;IAyBlE,OAAO,CAAC,UAAU;IAgBlB,UAAU,IAAI,IAAI;IAMlB,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI;IAOxC,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAO3B,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI;IAO5C,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAM5B,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI;IAMnE,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI;IAMxE,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;CAIjC;AAsBD;;;;GAIG;AACH,wBAAgB,aAAa,IAAI,UAAU,CAE1C;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,IAAI,IAAI,CAMvC;AAED,eAAe,aAAa,CAAC"}
|
package/dist/hub/DebugPanel.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
class DebugPanel{constructor(){Object.defineProperty(this,"container",{enumerable:!0,configurable:!0,writable:!0,value:null}),Object.defineProperty(this,"logContainer",{enumerable:!0,configurable:!0,writable:!0,value:null}),Object.defineProperty(this,"statsContainer",{enumerable:!0,configurable:!0,writable:!0,value:null}),Object.defineProperty(this,"logs",{enumerable:!0,configurable:!0,writable:!0,value:[]}),Object.defineProperty(this,"maxLogs",{enumerable:!0,configurable:!0,writable:!0,value:100}),Object.defineProperty(this,"stats",{enumerable:!0,configurable:!0,writable:!0,value:{hubInstancesCreated:0,connectCalls:0,wsOpened:0,wsClosed:0,wsErrors:0,messagesSent:0,messagesReceived:0,currentState:"unknown"}}),this.injectPanel(),this.log("info","DebugPanel","Debug panel initialized")}injectPanel(){const e=document.getElementById("autocore-debug-panel");e&&e.remove(),this.container=document.createElement("div"),this.container.id="autocore-debug-panel",this.container.innerHTML='\n <style>\n #autocore-debug-panel {\n position: fixed;\n bottom: 10px;\n right: 10px;\n width: 400px;\n max-height: 300px;\n background: rgba(0, 0, 0, 0.9);\n color: #0f0;\n font-family: monospace;\n font-size: 11px;\n border: 1px solid #0f0;\n border-radius: 4px;\n z-index: 99999;\n overflow: hidden;\n }\n #autocore-debug-panel .header {\n background: #0f0;\n color: #000;\n padding: 4px 8px;\n font-weight: bold;\n cursor: pointer;\n display: flex;\n justify-content: space-between;\n }\n #autocore-debug-panel .stats {\n padding: 4px 8px;\n border-bottom: 1px solid #0f0;\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 2px;\n }\n #autocore-debug-panel .stats span {\n color: #fff;\n }\n #autocore-debug-panel .stats .value {\n color: #ff0;\n }\n #autocore-debug-panel .logs {\n max-height: 180px;\n overflow-y: auto;\n padding: 4px;\n }\n #autocore-debug-panel .log-entry {\n margin: 1px 0;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n #autocore-debug-panel .log-entry.info { color: #888; }\n #autocore-debug-panel .log-entry.warn { color: #fa0; }\n #autocore-debug-panel .log-entry.error { color: #f44; }\n #autocore-debug-panel .log-entry.send { color: #4f4; }\n #autocore-debug-panel .log-entry.recv { color: #44f; }\n #autocore-debug-panel .state-connected { color: #4f4 !important; }\n #autocore-debug-panel .state-disconnected { color: #f44 !important; }\n #autocore-debug-panel .state-connecting { color: #fa0 !important; }\n </style>\n <div class="header">\n <span>AutoCore Debug</span>\n <span id="debug-toggle">[_]</span>\n </div>\n <div id="debug-content">\n <div class="stats" id="debug-stats"></div>\n <div class="logs" id="debug-logs"></div>\n </div>\n ',document.body?(document.body.appendChild(this.container),this.setupElements()):document.addEventListener("DOMContentLoaded",()=>{document.body.appendChild(this.container),this.setupElements()})}setupElements(){this.statsContainer=document.getElementById("debug-stats"),this.logContainer=document.getElementById("debug-logs");const e=document.getElementById("debug-toggle"),t=document.getElementById("debug-content");e?.addEventListener("click",()=>{t&&(t.style.display="none"===t.style.display?"block":"none",e.textContent="none"===t.style.display?"[+]":"[_]")}),this.updateStats()}updateStats(){if(!this.statsContainer)return;const e="OPEN"===this.stats.currentState?"state-connected":"CONNECTING"===this.stats.currentState?"state-connecting":"state-disconnected";this.statsContainer.innerHTML=`\n <div><span>Hub Instances:</span> <span class="value">${this.stats.hubInstancesCreated}</span></div>\n <div><span>connect() calls:</span> <span class="value">${this.stats.connectCalls}</span></div>\n <div><span>WS Opened:</span> <span class="value">${this.stats.wsOpened}</span></div>\n <div><span>WS Closed:</span> <span class="value">${this.stats.wsClosed}</span></div>\n <div><span>WS Errors:</span> <span class="value">${this.stats.wsErrors}</span></div>\n <div><span>Msgs Sent:</span> <span class="value">${this.stats.messagesSent}</span></div>\n <div><span>Msgs Recv:</span> <span class="value">${this.stats.messagesReceived}</span></div>\n <div><span>WS State:</span> <span class="value ${e}">${this.stats.currentState}</span></div>\n `}log(e,t,n){const s=(new Date).toTimeString().slice(0,8),a={time:s,type:e,source:t,message:n};this.logs.push(a),this.logs.length>this.maxLogs&&this.logs.shift();this.renderLogs()}renderLogs(){this.logContainer&&(this.logContainer.innerHTML=this.logs.slice(-50).map(e=>`<div class="log-entry ${e.type}">[${e.time}] ${e.source}: ${e.message}</div>`).join(""),this.logContainer.scrollTop=this.logContainer.scrollHeight)}hubCreated(){this.stats.hubInstancesCreated++,this.log("warn","Hub",`NEW INSTANCE CREATED (total: ${this.stats.hubInstancesCreated})`),this.updateStats()}connectCalled(e){this.stats.connectCalls++,this.stats.currentState=e,this.log("info","Hub",`connect() called (socket state: ${e})`),this.updateStats()}wsOpened(e){this.stats.wsOpened++,this.stats.currentState="OPEN",this.log("info","WS",`OPENED: ${e}`),this.updateStats()}wsClosed(e,t){this.stats.wsClosed++,this.stats.currentState="CLOSED",this.log("warn","WS",`CLOSED: code=${e}, reason=${t}`),this.updateStats()}wsError(e){this.stats.wsErrors++,this.log("error","WS",`ERROR: ${e}`),this.updateStats()}messageSent(e,t,n){this.stats.messagesSent++,this.log("send","WS",`>>> ${e}/${t} (id=${n})`),this.updateStats()}messageReceived(e,t,n){this.stats.messagesReceived++,this.log("recv","WS",`<<< ${e}/${t} (id=${n??"none"})`),this.updateStats()}updateState(e){this.stats.currentState=e,this.updateStats()}}let debugPanel=
|
|
1
|
+
class DebugPanel{constructor(){Object.defineProperty(this,"container",{enumerable:!0,configurable:!0,writable:!0,value:null}),Object.defineProperty(this,"logContainer",{enumerable:!0,configurable:!0,writable:!0,value:null}),Object.defineProperty(this,"statsContainer",{enumerable:!0,configurable:!0,writable:!0,value:null}),Object.defineProperty(this,"logs",{enumerable:!0,configurable:!0,writable:!0,value:[]}),Object.defineProperty(this,"maxLogs",{enumerable:!0,configurable:!0,writable:!0,value:100}),Object.defineProperty(this,"stats",{enumerable:!0,configurable:!0,writable:!0,value:{hubInstancesCreated:0,connectCalls:0,wsOpened:0,wsClosed:0,wsErrors:0,messagesSent:0,messagesReceived:0,currentState:"unknown"}}),this.injectPanel(),this.log("info","DebugPanel","Debug panel initialized")}injectPanel(){const e=document.getElementById("autocore-debug-panel");e&&e.remove(),this.container=document.createElement("div"),this.container.id="autocore-debug-panel",this.container.innerHTML='\n <style>\n #autocore-debug-panel {\n position: fixed;\n bottom: 10px;\n right: 10px;\n width: 400px;\n max-height: 300px;\n background: rgba(0, 0, 0, 0.9);\n color: #0f0;\n font-family: monospace;\n font-size: 11px;\n border: 1px solid #0f0;\n border-radius: 4px;\n z-index: 99999;\n overflow: hidden;\n }\n #autocore-debug-panel .header {\n background: #0f0;\n color: #000;\n padding: 4px 8px;\n font-weight: bold;\n cursor: pointer;\n display: flex;\n justify-content: space-between;\n }\n #autocore-debug-panel .stats {\n padding: 4px 8px;\n border-bottom: 1px solid #0f0;\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 2px;\n }\n #autocore-debug-panel .stats span {\n color: #fff;\n }\n #autocore-debug-panel .stats .value {\n color: #ff0;\n }\n #autocore-debug-panel .logs {\n max-height: 180px;\n overflow-y: auto;\n padding: 4px;\n }\n #autocore-debug-panel .log-entry {\n margin: 1px 0;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n #autocore-debug-panel .log-entry.info { color: #888; }\n #autocore-debug-panel .log-entry.warn { color: #fa0; }\n #autocore-debug-panel .log-entry.error { color: #f44; }\n #autocore-debug-panel .log-entry.send { color: #4f4; }\n #autocore-debug-panel .log-entry.recv { color: #44f; }\n #autocore-debug-panel .state-connected { color: #4f4 !important; }\n #autocore-debug-panel .state-disconnected { color: #f44 !important; }\n #autocore-debug-panel .state-connecting { color: #fa0 !important; }\n </style>\n <div class="header">\n <span>AutoCore Debug</span>\n <span id="debug-toggle">[_]</span>\n </div>\n <div id="debug-content">\n <div class="stats" id="debug-stats"></div>\n <div class="logs" id="debug-logs"></div>\n </div>\n ',document.body?(document.body.appendChild(this.container),this.setupElements()):document.addEventListener("DOMContentLoaded",()=>{document.body.appendChild(this.container),this.setupElements()})}setupElements(){this.statsContainer=document.getElementById("debug-stats"),this.logContainer=document.getElementById("debug-logs");const e=document.getElementById("debug-toggle"),t=document.getElementById("debug-content");e?.addEventListener("click",()=>{t&&(t.style.display="none"===t.style.display?"block":"none",e.textContent="none"===t.style.display?"[+]":"[_]")}),this.updateStats()}updateStats(){if(!this.statsContainer)return;const e="OPEN"===this.stats.currentState?"state-connected":"CONNECTING"===this.stats.currentState?"state-connecting":"state-disconnected";this.statsContainer.innerHTML=`\n <div><span>Hub Instances:</span> <span class="value">${this.stats.hubInstancesCreated}</span></div>\n <div><span>connect() calls:</span> <span class="value">${this.stats.connectCalls}</span></div>\n <div><span>WS Opened:</span> <span class="value">${this.stats.wsOpened}</span></div>\n <div><span>WS Closed:</span> <span class="value">${this.stats.wsClosed}</span></div>\n <div><span>WS Errors:</span> <span class="value">${this.stats.wsErrors}</span></div>\n <div><span>Msgs Sent:</span> <span class="value">${this.stats.messagesSent}</span></div>\n <div><span>Msgs Recv:</span> <span class="value">${this.stats.messagesReceived}</span></div>\n <div><span>WS State:</span> <span class="value ${e}">${this.stats.currentState}</span></div>\n `}log(e,t,n){const s=(new Date).toTimeString().slice(0,8),a={time:s,type:e,source:t,message:n};this.logs.push(a),this.logs.length>this.maxLogs&&this.logs.shift();this.renderLogs()}renderLogs(){this.logContainer&&(this.logContainer.innerHTML=this.logs.slice(-50).map(e=>`<div class="log-entry ${e.type}">[${e.time}] ${e.source}: ${e.message}</div>`).join(""),this.logContainer.scrollTop=this.logContainer.scrollHeight)}hubCreated(){this.stats.hubInstancesCreated++,this.log("warn","Hub",`NEW INSTANCE CREATED (total: ${this.stats.hubInstancesCreated})`),this.updateStats()}connectCalled(e){this.stats.connectCalls++,this.stats.currentState=e,this.log("info","Hub",`connect() called (socket state: ${e})`),this.updateStats()}wsOpened(e){this.stats.wsOpened++,this.stats.currentState="OPEN",this.log("info","WS",`OPENED: ${e}`),this.updateStats()}wsClosed(e,t){this.stats.wsClosed++,this.stats.currentState="CLOSED",this.log("warn","WS",`CLOSED: code=${e}, reason=${t}`),this.updateStats()}wsError(e){this.stats.wsErrors++,this.log("error","WS",`ERROR: ${e}`),this.updateStats()}messageSent(e,t,n){this.stats.messagesSent++,this.log("send","WS",`>>> ${e}/${t} (id=${n})`),this.updateStats()}messageReceived(e,t,n){this.stats.messagesReceived++,this.log("recv","WS",`<<< ${e}/${t} (id=${n??"none"})`),this.updateStats()}updateState(e){this.stats.currentState=e,this.updateStats()}}const noOpPanel={log(){},hubCreated(){},connectCalled(){},wsOpened(){},wsClosed(){},wsError(){},messageSent(){},messageReceived(){},updateState(){}};let debugPanel=noOpPanel,debugEnabled=!1;export function getDebugPanel(){return debugPanel}export function enableDebugPanel(){debugEnabled||(debugEnabled=!0,debugPanel=new DebugPanel,window.__AUTOCORE_DEBUG_PANEL__=debugPanel)}export default getDebugPanel;
|
package/dist/hub/index.d.ts
CHANGED
package/dist/hub/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/hub/index.ts"],"names":[],"mappings":"AAYA,OAAO,EAAE,OAAO,IAAI,GAAG,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAW5C;;;;;;;;GAQG;AACH,wBAAgB,SAAS,IAAI,GAAG,CAiB/B;AAED;;;GAGG;AACH,wBAAgB,cAAc,IAAI,GAAG,GAAG,IAAI,CAE3C;AAED;;;GAGG;AACH,wBAAgB,QAAQ,IAAI,IAAI,CAE/B;AAGD,OAAO,EAAE,OAAO,IAAI,GAAG,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,QAAQ,EAAE,CAAC;AACpB,OAAO,EAAE,YAAY,EAAE,CAAC;AACxB,OAAO,EAAE,WAAW,EAAE,CAAC;AAGvB,YAAY,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/hub/index.ts"],"names":[],"mappings":"AAYA,OAAO,EAAE,OAAO,IAAI,GAAG,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAW5C;;;;;;;;GAQG;AACH,wBAAgB,SAAS,IAAI,GAAG,CAiB/B;AAED;;;GAGG;AACH,wBAAgB,cAAc,IAAI,GAAG,GAAG,IAAI,CAE3C;AAED;;;GAGG;AACH,wBAAgB,QAAQ,IAAI,IAAI,CAE/B;AAGD,OAAO,EAAE,OAAO,IAAI,GAAG,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,QAAQ,EAAE,CAAC;AACpB,OAAO,EAAE,YAAY,EAAE,CAAC;AACxB,OAAO,EAAE,WAAW,EAAE,CAAC;AAGvB,YAAY,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAG/C,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC"}
|
package/dist/hub/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{HubBase as Hub}from"./HubBase";import{HubTauri}from"./HubTauri";import{HubWebSocket}from"./HubWebSocket";import{HubSimulate}from"./HubSimulate";import{getDebugPanel}from"./DebugPanel";let hubInstance=null;export function createHub(){const e=getDebugPanel();return e.log("info","createHub",`called (hasInstance: ${!!hubInstance})`),hubInstance?e.log("info","createHub","Returning existing hub instance"):"undefined"!=typeof window&&void 0!==window.__TAURI__&&null!==window.__TAURI__?(e.log("info","createHub","Creating HubTauri instance"),hubInstance=new HubTauri):(e.log("info","createHub","Creating HubWebSocket instance"),hubInstance=new HubWebSocket),hubInstance}export function getHubInstance(){return hubInstance}export function resetHub(){hubInstance=null}export{HubBase as Hub}from"./HubBase";export{HubTauri};export{HubWebSocket};export{HubSimulate};export{MessageType}from"./CommandMessage";
|
|
1
|
+
import{HubBase as Hub}from"./HubBase";import{HubTauri}from"./HubTauri";import{HubWebSocket}from"./HubWebSocket";import{HubSimulate}from"./HubSimulate";import{getDebugPanel}from"./DebugPanel";let hubInstance=null;export function createHub(){const e=getDebugPanel();return e.log("info","createHub",`called (hasInstance: ${!!hubInstance})`),hubInstance?e.log("info","createHub","Returning existing hub instance"):"undefined"!=typeof window&&void 0!==window.__TAURI__&&null!==window.__TAURI__?(e.log("info","createHub","Creating HubTauri instance"),hubInstance=new HubTauri):(e.log("info","createHub","Creating HubWebSocket instance"),hubInstance=new HubWebSocket),hubInstance}export function getHubInstance(){return hubInstance}export function resetHub(){hubInstance=null}export{HubBase as Hub}from"./HubBase";export{HubTauri};export{HubWebSocket};export{HubSimulate};export{MessageType}from"./CommandMessage";export{enableDebugPanel}from"./DebugPanel";
|
package/package.json
CHANGED
|
@@ -56,6 +56,7 @@ import type {ReactNode} from "react";
|
|
|
56
56
|
import { createHub, Hub } from "../hub";
|
|
57
57
|
import type { CommandMessage } from "../hub";
|
|
58
58
|
import { MessageType } from "../hub/CommandMessage";
|
|
59
|
+
import { enableDebugPanel } from "../hub/DebugPanel";
|
|
59
60
|
|
|
60
61
|
export { Hub };
|
|
61
62
|
|
|
@@ -243,11 +244,17 @@ export const EventEmitterContext = createContext<EventEmitterContextType>({
|
|
|
243
244
|
*
|
|
244
245
|
* @param children The child components to be wrapped in the context.
|
|
245
246
|
*/
|
|
246
|
-
export const EventEmitterProvider: React.FC<{ children: ReactNode }> = ({
|
|
247
|
+
export const EventEmitterProvider: React.FC<{ children: ReactNode; debug?: boolean }> = ({
|
|
247
248
|
children,
|
|
249
|
+
debug = false,
|
|
248
250
|
}) => {
|
|
249
251
|
console.log("[EventEmitterProvider] Rendering...");
|
|
250
252
|
|
|
253
|
+
// Enable the debug panel if requested (must run before Hub creation)
|
|
254
|
+
if (debug) {
|
|
255
|
+
enableDebugPanel();
|
|
256
|
+
}
|
|
257
|
+
|
|
251
258
|
const [state, setState] = useState<State>({
|
|
252
259
|
subscriptions: {},
|
|
253
260
|
nextSubscriptionId: 1,
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Copyright (C) 2025 Automated Design Corp.. All Rights Reserved.
|
|
3
3
|
* Created Date: 2025-09-05 08:03:32
|
|
4
4
|
* -----
|
|
5
|
-
* Last Modified: 2026-
|
|
5
|
+
* Last Modified: 2026-03-05 06:27:56
|
|
6
6
|
* -----
|
|
7
7
|
*
|
|
8
8
|
*/
|
|
@@ -17,87 +17,87 @@ import { useCallback, useContext, useMemo } from "react";
|
|
|
17
17
|
import type { BaseContextValue, TagConfig, TagValueMap } from "../core/AutoCoreTagTypes";
|
|
18
18
|
|
|
19
19
|
export function makeAutoCoreTagHooks<Spec extends readonly TagConfig[]>(
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
Context: React.Context<BaseContextValue<TagValueMap<Spec>>>,
|
|
21
|
+
tags: Spec
|
|
22
22
|
) {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
23
|
+
type VMap = TagValueMap<Spec>;
|
|
24
|
+
type TagNames = keyof VMap & string;
|
|
25
|
+
|
|
26
|
+
const findCfg = (tagName: string) =>
|
|
27
|
+
tags.find(t => t.tagName === tagName) as (Spec[number] | undefined);
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Access a single tag by name.
|
|
31
|
+
* Returns current value, raw value, direct server writer, and tap helper.
|
|
32
|
+
*/
|
|
33
|
+
const useAutoCoreTag = <K extends TagNames>(tagName: K) => {
|
|
34
|
+
const { values, rawValues, isLoading, write: ctxWrite, tap: ctxTap } = useContext(Context);
|
|
35
|
+
|
|
36
|
+
const cfg = findCfg(tagName as string);
|
|
37
|
+
if (!cfg) throw new Error(`useAutoCoreTag: unknown tagName '${String(tagName)}'`);
|
|
38
|
+
|
|
39
|
+
const write = useCallback(
|
|
40
|
+
(displayValue: VMap[K]) => ctxWrite(tagName, displayValue),
|
|
41
|
+
[ctxWrite, tagName]
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
const tap = useCallback(() => ctxTap?.(tagName), [ctxTap, tagName]);
|
|
45
|
+
|
|
46
|
+
return {
|
|
47
|
+
value: values[tagName] as VMap[K],
|
|
48
|
+
rawValue: rawValues[tagName as string],
|
|
49
|
+
write,
|
|
50
|
+
tap,
|
|
51
|
+
isLoading,
|
|
52
|
+
} as const;
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Access multiple tags at once with a bulk writer.
|
|
57
|
+
*/
|
|
58
|
+
const useAutoCoreTags = <K extends TagNames>(tagNames: readonly K[]) => {
|
|
59
|
+
const { values, rawValues, isLoading, write: ctxWrite } = useContext(Context);
|
|
60
|
+
|
|
61
|
+
const subset = useMemo(
|
|
62
|
+
() =>
|
|
63
|
+
Object.fromEntries(
|
|
64
|
+
tagNames.map(k => [k, values[k] as VMap[K]])
|
|
65
|
+
) as { [P in K]: VMap[P] },
|
|
66
|
+
[values, tagNames]
|
|
67
|
+
);
|
|
68
|
+
|
|
69
|
+
const rawSubset = useMemo(
|
|
70
|
+
() =>
|
|
71
|
+
Object.fromEntries(
|
|
72
|
+
tagNames.map(k => [k, rawValues[k as string]])
|
|
73
|
+
) as { [P in K]: unknown },
|
|
74
|
+
[rawValues, tagNames]
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
const write = useCallback(async (tagName: K, value: VMap[K]) => {
|
|
78
|
+
await ctxWrite(tagName, value);
|
|
79
|
+
}, [ctxWrite]);
|
|
80
|
+
|
|
81
|
+
return { values: subset, rawValues: rawSubset, write, isLoading } as const;
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Compute a derived value from the full tag state.
|
|
86
|
+
*/
|
|
87
|
+
const useAutoCoreSelect = <R>(selector: (all: Readonly<Partial<VMap>>) => R, deps: any[] = []) => {
|
|
88
|
+
const { values, isLoading } = useContext(Context);
|
|
89
|
+
const selected = useMemo(() => selector(values), [values, ...deps]);
|
|
90
|
+
return { selected, isLoading } as const;
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Access scale configurations and update functions.
|
|
95
|
+
*/
|
|
96
|
+
const useScales = () => {
|
|
97
|
+
const { scales, updateScale } = useContext(Context);
|
|
98
|
+
const getScale = useCallback((scaleName: string) => scales[scaleName], [scales]);
|
|
99
|
+
return { scales, updateScale, getScale } as const;
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
return { useAutoCoreTag, useAutoCoreTags, useAutoCoreSelect, useScales } as const;
|
|
103
103
|
}
|
package/src/hub/DebugPanel.ts
CHANGED
|
@@ -262,19 +262,46 @@ class DebugPanel {
|
|
|
262
262
|
}
|
|
263
263
|
}
|
|
264
264
|
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
265
|
+
/**
|
|
266
|
+
* No-op stub that satisfies the DebugPanel interface without injecting any DOM elements.
|
|
267
|
+
* Used when the debug panel is not enabled.
|
|
268
|
+
*/
|
|
269
|
+
const noOpPanel: DebugPanel = {
|
|
270
|
+
log() {},
|
|
271
|
+
hubCreated() {},
|
|
272
|
+
connectCalled() {},
|
|
273
|
+
wsOpened() {},
|
|
274
|
+
wsClosed() {},
|
|
275
|
+
wsError() {},
|
|
276
|
+
messageSent() {},
|
|
277
|
+
messageReceived() {},
|
|
278
|
+
updateState() {},
|
|
279
|
+
} as unknown as DebugPanel;
|
|
280
|
+
|
|
281
|
+
// Singleton instance — starts as the no-op stub
|
|
282
|
+
let debugPanel: DebugPanel = noOpPanel;
|
|
283
|
+
let debugEnabled = false;
|
|
284
|
+
|
|
285
|
+
/**
|
|
286
|
+
* Returns the current debug panel instance.
|
|
287
|
+
* If the panel has not been enabled, returns a no-op stub so callers
|
|
288
|
+
* don't need to guard every call.
|
|
289
|
+
*/
|
|
268
290
|
export function getDebugPanel(): DebugPanel {
|
|
269
|
-
|
|
291
|
+
return debugPanel;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
/**
|
|
295
|
+
* Enables the debug panel, injecting it into the DOM.
|
|
296
|
+
* Subsequent calls to `getDebugPanel()` will return the real panel.
|
|
297
|
+
* Safe to call multiple times — only creates one panel.
|
|
298
|
+
*/
|
|
299
|
+
export function enableDebugPanel(): void {
|
|
300
|
+
if (!debugEnabled) {
|
|
301
|
+
debugEnabled = true;
|
|
270
302
|
debugPanel = new DebugPanel();
|
|
271
|
-
// Expose globally for console access
|
|
272
303
|
(window as any).__AUTOCORE_DEBUG_PANEL__ = debugPanel;
|
|
273
304
|
}
|
|
274
|
-
return debugPanel;
|
|
275
305
|
}
|
|
276
306
|
|
|
277
|
-
// Auto-initialize on import
|
|
278
|
-
getDebugPanel();
|
|
279
|
-
|
|
280
307
|
export default getDebugPanel;
|
package/src/hub/index.ts
CHANGED
|
@@ -76,4 +76,7 @@ export { HubSimulate };
|
|
|
76
76
|
|
|
77
77
|
// Export CommandMessage types
|
|
78
78
|
export type { CommandMessage } from './CommandMessage';
|
|
79
|
-
export { MessageType } from './CommandMessage';
|
|
79
|
+
export { MessageType } from './CommandMessage';
|
|
80
|
+
|
|
81
|
+
// Export DebugPanel utilities
|
|
82
|
+
export { enableDebugPanel } from './DebugPanel';
|