crann 1.0.21 → 1.0.22

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/cjs/index.js CHANGED
@@ -1,3 +1,3 @@
1
- "use strict";var H=Object.create;var T=Object.defineProperty;var M=Object.getOwnPropertyDescriptor;var V=Object.getOwnPropertyNames;var W=Object.getPrototypeOf,G=Object.prototype.hasOwnProperty;var J=(s,e)=>{for(var t in e)T(s,t,{get:e[t],enumerable:!0})},j=(s,e,t,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of V(e))!G.call(s,i)&&i!==t&&T(s,i,{get:()=>e[i],enumerable:!(n=M(e,i))||n.enumerable});return s};var Q=(s,e,t)=>(t=s!=null?H(W(s)):{},j(e||!s||!s.__esModule?T(t,"default",{value:s,enumerable:!0}):t,s)),X=s=>j(T({},"__esModule",{value:!0}),s),R=(s,e,t,n)=>{for(var i=n>1?void 0:n?M(e,t):e,a=s.length-1,o;a>=0;a--)(o=s[a])&&(i=(n?o(e,t,i):o(i))||i);return n&&i&&T(e,t,i),i};var Z={};J(Z,{Crann:()=>I,Partition:()=>y,Persistence:()=>N,connect:()=>w,connected:()=>$,create:()=>z,createCrannStateHook:()=>F});module.exports=X(Z);var b=Q(require("webextension-polyfill"));var y={Instance:"instance",Service:"service"},N={Session:"session",Local:"local",None:"none"};var C=require("porter-source");function A(s,e){if(s===e)return!0;if(s==null||typeof s!="object"||e==null||typeof e!="object")return!1;let t=Object.keys(s),n=Object.keys(e);if(t.length!==n.length)return!1;t.sort(),n.sort();for(let i=0;i<t.length;i++){let a=t[i];if(a!==n[i]||!A(s[a],e[a]))return!1}return!0}var m=class m{static setDebug(e){m._debug=e}static isDebugEnabled(){return m._debug}};m._debug=!1;var D=m;function q(){return D.isDebugEnabled()}function E(s,e,t){let n=t.value;return t.value=function(...i){var a;if(q()){let o=new Error().stack,r=(a=((o==null?void 0:o.split(`
2
- `))||[])[3])==null?void 0:a.match(/at\s+(\S+)\s+/),f=r?r[1]:"unknown",c=i.length>1?i[1]:void 0,v={source:f,timestamp:Date.now(),changes:i[0],instanceKey:c};console.log("Crann State Change:",v)}return n.apply(this,i)},t}var S=class S{constructor(e,t){this.config=e;this.instances=new Map;this.stateChangeListeners=[];this.storagePrefix="crann_";this.post=()=>{};this.debug=!1;t!=null&&t.debug&&D.setDebug(!0),this.debug=(t==null?void 0:t.debug)||!1,this.storagePrefix=(t==null?void 0:t.storagePrefix)??this.storagePrefix,this.log("Constructing"),this.defaultInstanceState=this.initializeInstanceDefault(),this.defaultServiceState=this.serviceState=this.initializeServiceDefault(),this.hydrate();let[n,i,a,o,d]=(0,C.source)("crann");this.post=n,i({setState:(r,f)=>{if(!f){this.log("setState message heard from unknown agent");return}let c=this.getAgentTag(f);this.instanceLog("Setting state: ",c,r),this.set(r.payload.state,f.id)}}),d(r=>{this.instanceLog("Messages set received. Sending initial state.",this.getAgentTag(r),{info:r});let f=this.get(r.id);this.post({action:"initialState",payload:{state:f,key:r.id}},r.location)}),a(r=>{let f=this.getAgentTag(r);this.instanceLog("Agent connected ",f,{info:r}),this.addInstance(r.id),o(c=>{this.instanceLog("Agent disconnect heard. Connection type, context and location: ",this.getAgentTag(c),{info:c}),this.removeInstance(c.id)})})}static getInstance(e,t){return S.instance?t!=null&&t.debug&&console.log("CrannSource [static-core], Instance requested and already existed, returning"):S.instance=new S(e,t),S.instance}async addInstance(e){if(this.instances.has(e))this.instanceLog("Instance was already registered, ignoring request from key: ",e);else{this.instanceLog("Adding instance from agent key: ",e);let t={...this.defaultInstanceState};this.instances.set(e,t)}}async removeInstance(e){this.instances.has(e)?(this.instanceLog("Remove instance requested. ",e),this.instances.delete(e)):this.instanceLog("Remove instance requested but it did not exist!. ",e)}async setServiceState(e){this.log("Request to set service state with: ",e);let t={...this.serviceState,...e};A(this.serviceState,t)?this.log("New state seems to be the same as existing, skipping"):(this.log("Confirmed new state was different than existing so proceeding to persist then notify all connected instances."),this.serviceState=t,await this.persist(e),this.notify(e))}async setInstanceState(e,t){this.instanceLog("Request to update instance state, update: ",e,t);let n=this.instances.get(e)||this.defaultInstanceState,i={...n,...t};A(n,i)?this.instanceLog("Instance state update is not different, skipping update. ",e):(this.instanceLog("Instance state update is different, updating and notifying. ",e),this.instances.set(e,i),this.notify(t,e))}async persist(e){this.log("Persisting state");let t=!1;for(let n in e||this.serviceState){let a=this.config[n].persist||"none",o=e?e[n]:this.serviceState[n];switch(a){case"session":await b.default.storage.session.set({[this.storagePrefix+n]:o}),t=!0;break;case"local":await b.default.storage.local.set({[this.storagePrefix+n]:o}),t=!0;break;default:break}}t?this.log("State was persisted"):this.log("Nothing to persist")}async clear(){this.log("Clearing state"),this.serviceState=this.defaultServiceState,this.instances.forEach((e,t)=>{this.instances.set(t,this.defaultInstanceState)}),await this.persist(),this.notify({})}subscribe(e){this.log("Subscribing to state"),this.stateChangeListeners.push(e)}notify(e,t){let n=t?(0,C.getAgentById)(t):void 0,i=t?this.get(t):this.get();this.stateChangeListeners.length>0&&(this.log("Notifying state change listeners in source"),this.stateChangeListeners.forEach(a=>{a(i,e,n==null?void 0:n.info)})),t&&(n!=null&&n.info.location)?(this.instanceLog("Notifying of state change.",t),this.post({action:"stateUpdate",payload:{state:e}},n.info.location)):(console.log("Notifying everyone"),this.instances.forEach((a,o)=>{this.post({action:"stateUpdate",payload:{state:e}},o)}))}get(e){return e?{...this.serviceState,...this.instances.get(e)}:{...this.serviceState}}findInstance(e){let t=(0,C.getAgentByLocation)(e);if(!t)return this.log("Could not find agent for location: ",{location:e}),null;for(let[n,i]of this.instances)if(n===t.info.id)return this.log("Found instance for key: ",n),n;return this.log("Could not find instance for context and location: ",{location:e}),null}async set(e,t){let n={},i={};for(let a in e){let o=this.config[a];if(o.partition==="instance"){let d=a,r=e;n[d]=r[d]}else if(!o.partition||o.partition===y.Service){let d=a,r=e;i[d]=r[d]}}t&&Object.keys(n).length>0&&(this.instanceLog("Setting instance state: ",t,n),this.setInstanceState(t,n)),Object.keys(i).length>0&&(this.log("Setting service state: ",i),this.setServiceState(i))}async hydrate(){this.log("Hydrating state from storage.");let e=await b.default.storage.local.get(null),t=await b.default.storage.session.get(null),n={...e,...t},i={},a=!1;for(let o in n){let d=this.removePrefix(o);if(this.config.hasOwnProperty(d)){let r=n[d];i[d]=r,a=!0}}a?this.log("Hydrated some items."):this.log("No items found in storage."),this.serviceState={...this.defaultServiceState,...i}}removePrefix(e){return e.startsWith(this.storagePrefix)?e.replace(this.storagePrefix,""):e}getAgentTag(e){return`${e.location.context}:${e.location.tabId}:${e.location.frameId}`}initializeInstanceDefault(){let e={};return Object.keys(this.config).forEach(t=>{let n=this.config[t];n.partition==="instance"&&(e[t]=n.default)}),e}initializeServiceDefault(){let e={};return Object.keys(this.config).forEach(t=>{let n=this.config[t];n.partition===y.Service&&(e[t]=n.default)}),e}log(e,...t){this.debug&&console.log("CrannSource [core], "+e,...t)}instanceLog(e,t,...n){this.debug&&console.log(`CrannSource [${t}], `+e,...n)}error(e,...t){console.error("CrannSource [core], "+e,...t)}warn(e,...t){console.warn("CrannSource [core], "+e,...t)}};S.instance=null,R([E],S.prototype,"setServiceState",1),R([E],S.prototype,"setInstanceState",1);var I=S;function z(s,e){let t=I.getInstance(s,e);return[t.get.bind(t),t.set.bind(t),t.subscribe.bind(t),t.findInstance.bind(t)]}var B=require("porter-source"),P=null;function w(s,e){let t=(e==null?void 0:e.debug)||!1,n=e==null?void 0:e.context,i="unset",a=(g,...u)=>{t&&console.log(`CrannAgent [${i}] `+g,...u)};if(a("Initializing with context: ",n),P)return a("We had an instance already, returning"),P;a("No existing instance, creating a new one");let[o,d]=(0,B.connect)({namespace:"crann",agentContext:n});d({initialState:g=>{r=g.payload.state,i=g.payload.key,c.forEach(u=>{u.callback(r)}),a(`Initial state received and ${c.size} listeners notified`)},stateUpdate:g=>{a("State updated: ",g),f=g.payload.state,r={...r,...f},f&&(a("Notifying listeners of state update"),c.forEach(u=>{u.keys===void 0?(a("Found a universal listener, notifying"),u.callback(f)):u.keys.some(K=>f.hasOwnProperty(K))&&(a("Found a specific listener for this item, notifying"),u.callback(f))}))}}),a("Porter connected. Setting up state and listeners");let r=Y(s),f=null,c=new Set;a("Completed setup, returning instance");let v=()=>r,h=g=>{console.log("CrannAgent, calling post with setState"),o({action:"setState",payload:{state:g}})},x=(g,u)=>{let p={keys:u,callback:g};return c.add(p),()=>{c.delete(p)}};return P=[g=>{let u=()=>v()[g],p=L=>h({[g]:L}),K=L=>x(U=>{g in U&&L(U[g])},[g]);return[u(),p,K]},v,h,x],P}function $(){return P!==null}function Y(s){let e={};Object.keys(s).forEach(n=>{let i=s[n];i.partition==="instance"&&(e[n]=i.default)});let t={};return Object.keys(s).forEach(n=>{let i=s[n];i.partition==="instance"&&(t[n]=i.default)}),{...e,...t}}var l=require("react");function F(s){return function(t){let[n,i,a,o]=(0,l.useMemo)(()=>w(s),[t]),d=(0,l.useCallback)(c=>{let[v,h]=(0,l.useState)(i()[c]),x=(0,l.useRef)(v);(0,l.useEffect)(()=>{x.current=v},[v]),(0,l.useEffect)(()=>(h(i()[c]),o(g=>{c in g&&h(g[c])},[c])),[c]);let O=(0,l.useCallback)(k=>{a({[c]:k})},[c]);return[v,O]},[i,a,o]),r=(0,l.useCallback)(()=>i(),[i]),f=(0,l.useCallback)(c=>{a(c)},[a]);return{useStateItem:d,getState:r,setState:f,useCrann:n}}}0&&(module.exports={Crann,Partition,Persistence,connect,connected,create,createCrannStateHook});
1
+ "use strict";var H=Object.create;var T=Object.defineProperty;var M=Object.getOwnPropertyDescriptor;var V=Object.getOwnPropertyNames;var W=Object.getPrototypeOf,G=Object.prototype.hasOwnProperty;var J=(s,e)=>{for(var t in e)T(s,t,{get:e[t],enumerable:!0})},j=(s,e,t,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of V(e))!G.call(s,i)&&i!==t&&T(s,i,{get:()=>e[i],enumerable:!(n=M(e,i))||n.enumerable});return s};var Q=(s,e,t)=>(t=s!=null?H(W(s)):{},j(e||!s||!s.__esModule?T(t,"default",{value:s,enumerable:!0}):t,s)),X=s=>j(T({},"__esModule",{value:!0}),s),R=(s,e,t,n)=>{for(var i=n>1?void 0:n?M(e,t):e,a=s.length-1,o;a>=0;a--)(o=s[a])&&(i=(n?o(e,t,i):o(i))||i);return n&&i&&T(e,t,i),i};var Z={};J(Z,{Crann:()=>I,Partition:()=>y,Persistence:()=>N,connect:()=>w,connected:()=>$,create:()=>z,createCrannStateHook:()=>F});module.exports=X(Z);var b=Q(require("webextension-polyfill"));var y={Instance:"instance",Service:"service"},N={Session:"session",Local:"local",None:"none"};var C=require("porter-source");function A(s,e){if(s===e)return!0;if(s==null||typeof s!="object"||e==null||typeof e!="object")return!1;let t=Object.keys(s),n=Object.keys(e);if(t.length!==n.length)return!1;t.sort(),n.sort();for(let i=0;i<t.length;i++){let a=t[i];if(a!==n[i]||!A(s[a],e[a]))return!1}return!0}var D=class D{static setDebug(e){D._debug=e}static isDebugEnabled(){return D._debug}};D._debug=!1;var m=D;function q(){return m.isDebugEnabled()}function E(s,e,t){let n=t.value;return t.value=function(...i){var a;if(q()){let o=new Error().stack,r=(a=((o==null?void 0:o.split(`
2
+ `))||[])[3])==null?void 0:a.match(/at\s+(\S+)\s+/),f=r?r[1]:"unknown",c=i.length>1?i[1]:void 0,v={source:f,timestamp:Date.now(),changes:i[0],instanceKey:c};console.log("Crann State Change:",v)}return n.apply(this,i)},t}var S=class S{constructor(e,t){this.config=e;this.instances=new Map;this.stateChangeListeners=[];this.storagePrefix="crann_";this.post=()=>{};this.debug=!1;t!=null&&t.debug&&m.setDebug(!0),this.debug=(t==null?void 0:t.debug)||!1,this.storagePrefix=(t==null?void 0:t.storagePrefix)??this.storagePrefix,this.log("Constructing"),this.defaultInstanceState=this.initializeInstanceDefault(),this.defaultServiceState=this.serviceState=this.initializeServiceDefault(),this.hydrate();let[n,i,a,o,d]=(0,C.source)("crann");this.post=n,i({setState:(r,f)=>{if(!f){this.log("setState message heard from unknown agent");return}let c=this.getAgentTag(f);this.instanceLog("Setting state: ",c,r),this.set(r.payload.state,f.id)}}),d(r=>{this.instanceLog("Messages set received. Sending initial state.",this.getAgentTag(r),{info:r});let f=this.get(r.id);this.post({action:"initialState",payload:{state:f,key:r.id}},r.location)}),a(r=>{let f=this.getAgentTag(r);this.instanceLog("Agent connected ",f,{info:r}),this.addInstance(r.id),o(c=>{this.instanceLog("Agent disconnect heard. Connection type, context and location: ",this.getAgentTag(c),{info:c}),this.removeInstance(c.id)})})}static getInstance(e,t){return S.instance?t!=null&&t.debug&&console.log("CrannSource [static-core], Instance requested and already existed, returning"):S.instance=new S(e,t),S.instance}async addInstance(e){if(this.instances.has(e))this.instanceLog("Instance was already registered, ignoring request from key: ",e);else{this.instanceLog("Adding instance from agent key: ",e);let t={...this.defaultInstanceState};this.instances.set(e,t)}}async removeInstance(e){this.instances.has(e)?(this.instanceLog("Remove instance requested. ",e),this.instances.delete(e)):this.instanceLog("Remove instance requested but it did not exist!. ",e)}async setServiceState(e){this.log("Request to set service state with: ",e);let t={...this.serviceState,...e};A(this.serviceState,t)?this.log("New state seems to be the same as existing, skipping"):(this.log("Confirmed new state was different than existing so proceeding to persist then notify all connected instances."),this.serviceState=t,await this.persist(e),this.notify(e))}async setInstanceState(e,t){this.instanceLog("Request to update instance state, update: ",e,t);let n=this.instances.get(e)||this.defaultInstanceState,i={...n,...t};A(n,i)?this.instanceLog("Instance state update is not different, skipping update. ",e):(this.instanceLog("Instance state update is different, updating and notifying. ",e),this.instances.set(e,i),this.notify(t,e))}async persist(e){this.log("Persisting state");let t=!1;for(let n in e||this.serviceState){let a=this.config[n].persist||"none",o=e?e[n]:this.serviceState[n];switch(a){case"session":await b.default.storage.session.set({[this.storagePrefix+n]:o}),t=!0;break;case"local":await b.default.storage.local.set({[this.storagePrefix+n]:o}),t=!0;break;default:break}}t?this.log("State was persisted"):this.log("Nothing to persist")}async clear(){this.log("Clearing state"),this.serviceState=this.defaultServiceState,this.instances.forEach((e,t)=>{this.instances.set(t,this.defaultInstanceState)}),await this.persist(),this.notify({})}subscribe(e){this.log("Subscribing to state"),this.stateChangeListeners.push(e)}notify(e,t){let n=t?(0,C.getAgentById)(t):void 0,i=t?this.get(t):this.get();this.stateChangeListeners.length>0&&(this.log("Notifying state change listeners in source"),this.stateChangeListeners.forEach(a=>{a(i,e,n==null?void 0:n.info)})),t&&(n!=null&&n.info.location)?(this.instanceLog("Notifying of state change.",t),this.post({action:"stateUpdate",payload:{state:e}},n.info.location)):(console.log("Notifying everyone"),this.instances.forEach((a,o)=>{this.post({action:"stateUpdate",payload:{state:e}},o)}))}get(e){return e?{...this.serviceState,...this.instances.get(e)}:{...this.serviceState}}findInstance(e){let t=(0,C.getAgentByLocation)(e);if(!t)return this.log("Could not find agent for location: ",{location:e}),null;for(let[n,i]of this.instances)if(n===t.info.id)return this.log("Found instance for key: ",n),n;return this.log("Could not find instance for context and location: ",{location:e}),null}async set(e,t){let n={},i={};for(let a in e){let o=this.config[a];if(o.partition==="instance"){let d=a,r=e;n[d]=r[d]}else if(!o.partition||o.partition===y.Service){let d=a,r=e;i[d]=r[d]}}t&&Object.keys(n).length>0&&(this.instanceLog("Setting instance state: ",t,n),this.setInstanceState(t,n)),Object.keys(i).length>0&&(this.log("Setting service state: ",i),this.setServiceState(i))}async hydrate(){this.log("Hydrating state from storage.");let e=await b.default.storage.local.get(null),t=await b.default.storage.session.get(null),n={...e,...t},i={},a=!1;for(let o in n){let d=this.removePrefix(o);if(this.config.hasOwnProperty(d)){let r=n[d];i[d]=r,a=!0}}a?this.log("Hydrated some items."):this.log("No items found in storage."),this.serviceState={...this.defaultServiceState,...i}}removePrefix(e){return e.startsWith(this.storagePrefix)?e.replace(this.storagePrefix,""):e}getAgentTag(e){return`${e.location.context}:${e.location.tabId}:${e.location.frameId}`}initializeInstanceDefault(){let e={};return Object.keys(this.config).forEach(t=>{let n=this.config[t];n.partition==="instance"&&(e[t]=n.default)}),e}initializeServiceDefault(){let e={};return Object.keys(this.config).forEach(t=>{let n=this.config[t];n.partition===y.Service&&(e[t]=n.default)}),e}log(e,...t){this.debug&&console.log("CrannSource [core], "+e,...t)}instanceLog(e,t,...n){this.debug&&console.log(`CrannSource [${t}], `+e,...n)}error(e,...t){console.error("CrannSource [core], "+e,...t)}warn(e,...t){console.warn("CrannSource [core], "+e,...t)}};S.instance=null,R([E],S.prototype,"setServiceState",1),R([E],S.prototype,"setInstanceState",1);var I=S;function z(s,e){let t=I.getInstance(s,e);return[t.get.bind(t),t.set.bind(t),t.subscribe.bind(t),t.findInstance.bind(t)]}var B=require("porter-source"),P=null;function w(s,e){let t=(e==null?void 0:e.debug)||!1,n=e==null?void 0:e.context,i="unset",a=(g,...u)=>{t&&console.log(`CrannAgent [${i}] `+g,...u)};if(a("Initializing with context: ",n),P)return a("We had an instance already, returning"),P;a("No existing instance, creating a new one");let[o,d]=(0,B.connect)({namespace:"crann",agentContext:n});d({initialState:g=>{r=g.payload.state,i=g.payload.key,c.forEach(u=>{u.callback(r)}),a(`Initial state received and ${c.size} listeners notified`)},stateUpdate:g=>{a("State updated: ",g),f=g.payload.state,r={...r,...f},f&&(a("Notifying listeners of state update"),c.forEach(u=>{u.keys===void 0?(a("Found a universal listener, notifying"),u.callback(f)):u.keys.some(K=>f.hasOwnProperty(K))&&(a("Found a specific listener for this item, notifying"),u.callback(f))}))}}),a("Porter connected. Setting up state and listeners");let r=Y(s),f=null,c=new Set;a("Completed setup, returning instance");let v=()=>r,h=g=>{console.log("CrannAgent, calling post with setState"),o({action:"setState",payload:{state:g}})},x=(g,u)=>{let p={keys:u,callback:g};return c.add(p),()=>{c.delete(p)}};return P=[g=>{let u=()=>v()[g],p=L=>h({[g]:L}),K=L=>x(U=>{g in U&&L(U[g])},[g]);return[u(),p,K]},v,h,x],P}function $(){return P!==null}function Y(s){let e={};Object.keys(s).forEach(n=>{let i=s[n];i.partition==="instance"&&(e[n]=i.default)});let t={};return Object.keys(s).forEach(n=>{let i=s[n];i.partition==="instance"&&(t[n]=i.default)}),{...e,...t}}var l=require("react");function F(s){return function(t){let[n,i,a,o]=(0,l.useMemo)(()=>w(s),[t]),d=(0,l.useCallback)(c=>{let[v,h]=(0,l.useState)(i()[c]),x=(0,l.useRef)(v);(0,l.useEffect)(()=>{x.current=v},[v]),(0,l.useEffect)(()=>(h(i()[c]),o(g=>{c in g&&h(g[c])},[c])),[c]);let O=(0,l.useCallback)(k=>{a({[c]:k})},[c]);return[v,O]},[i,a,o]),r=(0,l.useCallback)(()=>i(),[i]),f=(0,l.useCallback)(c=>{a(c)},[a]);return{useStateItem:d,getState:r,setState:f,useCrann:n}}}0&&(module.exports={Crann,Partition,Persistence,connect,connected,create,createCrannStateHook});
3
3
  //# sourceMappingURL=index.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/index.ts", "../../src/crann.ts", "../../src/model/crann.model.ts", "../../src/utils/deepEqual.ts", "../../src/utils/debug.ts", "../../src/utils/tracking.ts", "../../src/crannAgent.ts", "../../src/hooks/useCrannState.ts"],
4
- "sourcesContent": ["export { create, Crann } from \"./crann\";\nexport { connect, connected } from \"./crannAgent\";\nexport { createCrannStateHook } from \"./hooks/useCrannState\";\nexport {\n CrannAgent,\n StateUpdate,\n State,\n Partition,\n Persistence,\n ConfigItem,\n DerivedState,\n} from \"./model/crann.model\";\n", "import browser from \"webextension-polyfill\";\nimport {\n DerivedInstanceState,\n DerivedServiceState,\n ConfigItem,\n DerivedState,\n Partition,\n CrannOptions,\n} from \"./model/crann.model\";\nimport {\n AgentInfo,\n source,\n getAgentById,\n getAgentByLocation,\n MessageTarget,\n} from \"porter-source\";\nimport { deepEqual } from \"./utils/deepEqual\";\nimport { Message, BrowserLocation } from \"porter-source\";\nimport { trackStateChange } from \"./utils/tracking\";\nimport { DebugManager } from \"./utils/debug\";\n\nexport class Crann<TConfig extends Record<string, ConfigItem<any>>> {\n private static instance: Crann<any> | null = null;\n private instances: Map<string, DerivedInstanceState<TConfig>> = new Map();\n private defaultServiceState: DerivedServiceState<TConfig>;\n private defaultInstanceState: DerivedInstanceState<TConfig>;\n private serviceState: DerivedServiceState<TConfig>;\n private stateChangeListeners: Array<\n (\n state: DerivedInstanceState<TConfig> | DerivedState<TConfig>,\n changes: Partial<\n DerivedServiceState<TConfig> & DerivedInstanceState<TConfig>\n >,\n agent?: AgentInfo\n ) => void\n > = [];\n private storagePrefix = \"crann_\";\n private post: (message: Message<any>, target?: MessageTarget) => void =\n () => {};\n private debug: boolean = false;\n\n constructor(private config: TConfig, options?: CrannOptions) {\n // Set the debug flag globally\n if (options?.debug) {\n DebugManager.setDebug(true);\n }\n this.debug = options?.debug || false;\n this.storagePrefix = options?.storagePrefix ?? this.storagePrefix;\n this.log(\"Constructing\");\n this.defaultInstanceState = this.initializeInstanceDefault();\n this.defaultServiceState = this.serviceState =\n this.initializeServiceDefault();\n this.hydrate();\n const [post, setMessages, onConnect, onDisconnect, onMessagesSet] =\n source(\"crann\");\n this.post = post;\n setMessages({\n setState: (message, info) => {\n if (!info) {\n this.log(\"setState message heard from unknown agent\");\n return;\n }\n\n const agentTag = this.getAgentTag(info);\n this.instanceLog(\"Setting state: \", agentTag, message);\n this.set(message.payload.state, info.id);\n },\n });\n onMessagesSet((info: AgentInfo) => {\n this.instanceLog(\n \"Messages set received. Sending initial state.\",\n this.getAgentTag(info),\n { info }\n );\n const fullState = this.get(info.id);\n this.post(\n {\n action: \"initialState\",\n payload: { state: fullState, key: info.id },\n },\n info.location\n );\n });\n onConnect((info: AgentInfo) => {\n const agentTag = this.getAgentTag(info);\n this.instanceLog(\"Agent connected \", agentTag, { info });\n this.addInstance(info.id);\n onDisconnect((info: AgentInfo) => {\n this.instanceLog(\n \"Agent disconnect heard. Connection type, context and location: \",\n this.getAgentTag(info),\n { info }\n );\n this.removeInstance(info.id);\n });\n });\n }\n\n public static getInstance<TConfig extends Record<string, ConfigItem<any>>>(\n config: TConfig,\n options?: CrannOptions\n ): Crann<TConfig> {\n if (!Crann.instance) {\n Crann.instance = new Crann(config, options);\n } else if (options?.debug) {\n console.log(\n \"CrannSource [static-core], Instance requested and already existed, returning\"\n );\n }\n return Crann.instance;\n }\n\n private async addInstance(key: string): Promise<void> {\n if (!this.instances.has(key)) {\n this.instanceLog(\"Adding instance from agent key: \", key);\n const initialInstanceState = {\n ...this.defaultInstanceState,\n } as DerivedInstanceState<TConfig>;\n this.instances.set(key, initialInstanceState);\n } else {\n this.instanceLog(\n \"Instance was already registered, ignoring request from key: \",\n key\n );\n }\n }\n\n private async removeInstance(key: string): Promise<void> {\n if (this.instances.has(key)) {\n this.instanceLog(\"Remove instance requested. \", key);\n this.instances.delete(key);\n } else {\n this.instanceLog(\n \"Remove instance requested but it did not exist!. \",\n key\n );\n }\n }\n\n @trackStateChange\n public async setServiceState(\n state: Partial<DerivedServiceState<TConfig>>\n ): Promise<void> {\n this.log(\"Request to set service state with: \", state);\n const update = { ...this.serviceState, ...state };\n if (!deepEqual(this.serviceState, update)) {\n this.log(\n \"Confirmed new state was different than existing so proceeding to persist then notify all connected instances.\"\n );\n this.serviceState = update;\n await this.persist(state);\n this.notify(state as Partial<DerivedState<TConfig>>);\n } else {\n this.log(\"New state seems to be the same as existing, skipping\");\n }\n }\n\n @trackStateChange\n public async setInstanceState(\n key: string,\n state: Partial<DerivedInstanceState<TConfig>>\n ): Promise<void> {\n this.instanceLog(\"Request to update instance state, update: \", key, state);\n const currentState = this.instances.get(key) || this.defaultInstanceState;\n const update = { ...currentState, ...state };\n if (!deepEqual(currentState, update)) {\n this.instanceLog(\n \"Instance state update is different, updating and notifying. \",\n key\n );\n this.instances.set(key, update);\n this.notify(state as Partial<DerivedState<TConfig>>, key);\n } else {\n this.instanceLog(\n \"Instance state update is not different, skipping update. \",\n key\n );\n }\n }\n\n // If we pass in specific state to persist, it only persists that state.\n // Otherwise persists all of the worker state.\n private async persist(\n state?: Partial<DerivedServiceState<TConfig>>\n ): Promise<void> {\n this.log(\"Persisting state\");\n let wasPersisted = false;\n for (const key in state || this.serviceState) {\n const item = this.config[key] as ConfigItem<any>;\n const persistence = item.persist || \"none\";\n const value = state\n ? state[key as keyof DerivedServiceState<TConfig>]\n : this.serviceState[key];\n switch (persistence) {\n case \"session\":\n await browser.storage.session.set({\n [this.storagePrefix + (key as string)]: value,\n });\n wasPersisted = true;\n break;\n case \"local\":\n await browser.storage.local.set({\n [this.storagePrefix + (key as string)]: value,\n });\n wasPersisted = true;\n break;\n default:\n break;\n }\n }\n if (wasPersisted) {\n this.log(\"State was persisted\");\n } else {\n this.log(\"Nothing to persist\");\n }\n }\n\n public async clear(): Promise<void> {\n this.log(\"Clearing state\");\n this.serviceState = this.defaultServiceState;\n this.instances.forEach((_, key) => {\n this.instances.set(key, this.defaultInstanceState);\n });\n await this.persist();\n this.notify({});\n }\n\n public subscribe(\n listener: (\n state: DerivedInstanceState<TConfig> | DerivedState<TConfig>,\n changes: Partial<\n DerivedInstanceState<TConfig> & DerivedServiceState<TConfig>\n >,\n agent?: AgentInfo\n ) => void\n ): void {\n this.log(\"Subscribing to state\");\n this.stateChangeListeners.push(listener);\n }\n\n // Right now we notify the instance even if the state change came from the instance.\n // This should probably be skipped for instance state, since it already knows.\n private notify(changes: Partial<DerivedState<TConfig>>, key?: string): void {\n const agent = key ? getAgentById(key) : undefined;\n const state = key ? this.get(key) : this.get();\n\n if (this.stateChangeListeners.length > 0) {\n this.log(\"Notifying state change listeners in source\");\n this.stateChangeListeners.forEach((listener) => {\n listener(state, changes, agent?.info);\n });\n }\n\n if (key && agent?.info.location) {\n this.instanceLog(\"Notifying of state change.\", key);\n this.post(\n { action: \"stateUpdate\", payload: { state: changes } },\n agent.info.location\n );\n } else {\n console.log(\"Notifying everyone\");\n // for every key of this.instances, post the state update to the corresponding key\n this.instances.forEach((_, key) => {\n this.post({ action: \"stateUpdate\", payload: { state: changes } }, key);\n });\n }\n }\n\n public get(): DerivedState<TConfig>;\n public get(\n key: string\n ): DerivedInstanceState<TConfig> & DerivedServiceState<TConfig>;\n public get(\n key?: string\n ): DerivedServiceState<TConfig> | DerivedState<TConfig> {\n if (!key) {\n return { ...this.serviceState, ...({} as DerivedInstanceState<TConfig>) };\n }\n return { ...this.serviceState, ...this.instances.get(key) };\n }\n\n // Todo: Should we return the instance data? What is the point of this.\n public findInstance(location: BrowserLocation): string | null {\n const agent = getAgentByLocation(location);\n if (!agent) {\n this.log(\"Could not find agent for location: \", { location });\n return null;\n }\n for (const [key, instance] of this.instances) {\n if (key === agent.info.id) {\n this.log(\"Found instance for key: \", key);\n return key;\n }\n }\n this.log(\"Could not find instance for context and location: \", {\n location,\n });\n return null;\n }\n\n public async set(state: Partial<DerivedServiceState<TConfig>>): Promise<void>;\n public async set(\n state: Partial<\n DerivedInstanceState<TConfig> & DerivedServiceState<TConfig>\n >,\n key: string\n ): Promise<void>;\n public async set(\n state: Partial<\n DerivedInstanceState<TConfig> | DerivedServiceState<TConfig>\n >,\n key?: string\n ): Promise<void> {\n const instance = {} as Partial<DerivedInstanceState<TConfig>>;\n const worker = {} as Partial<DerivedServiceState<TConfig>>;\n\n for (const itemKey in state) {\n const item = this.config[itemKey as keyof TConfig] as ConfigItem<any>;\n if (item.partition === \"instance\") {\n const instanceItemKey = itemKey as keyof DerivedInstanceState<TConfig>;\n const instanceState = state as Partial<DerivedInstanceState<TConfig>>;\n instance[instanceItemKey] = instanceState[instanceItemKey];\n } else if (!item.partition || item.partition === Partition.Service) {\n const serviceItemKey = itemKey as keyof DerivedServiceState<TConfig>;\n const serviceState = state as Partial<DerivedServiceState<TConfig>>;\n worker[serviceItemKey] = serviceState[serviceItemKey]!;\n }\n }\n if (key && Object.keys(instance).length > 0) {\n this.instanceLog(\"Setting instance state: \", key, instance);\n this.setInstanceState(key, instance);\n }\n if (Object.keys(worker).length > 0) {\n this.log(\"Setting service state: \", worker);\n this.setServiceState(worker);\n }\n }\n\n private async hydrate(): Promise<void> {\n this.log(\"Hydrating state from storage.\");\n const local = await browser.storage.local.get(null);\n const session = await browser.storage.session.get(null);\n const combined = { ...local, ...session };\n const update: Partial<DerivedServiceState<TConfig>> = {}; // Cast update as Partial<DerivedState<TConfig>>\n let hadItems = false;\n for (const prefixedKey in combined) {\n const key = this.removePrefix(prefixedKey);\n if (this.config.hasOwnProperty(key)) {\n const value = combined[key];\n update[key as keyof DerivedServiceState<TConfig>] = value;\n hadItems = true;\n }\n }\n if (hadItems) {\n this.log(\"Hydrated some items.\");\n } else {\n this.log(\"No items found in storage.\");\n }\n this.serviceState = { ...this.defaultServiceState, ...update };\n }\n\n private removePrefix(key: string): string {\n if (key.startsWith(this.storagePrefix)) {\n return key.replace(this.storagePrefix, \"\");\n }\n return key;\n }\n\n private getAgentTag(agent: AgentInfo): string {\n return `${agent.location.context}:${agent.location.tabId}:${agent.location.frameId}`;\n }\n\n private initializeInstanceDefault(): DerivedInstanceState<TConfig> {\n const instanceState: any = {};\n Object.keys(this.config).forEach((key) => {\n const item: ConfigItem<any> = this.config[key];\n if (item.partition === \"instance\") {\n instanceState[key] = item.default;\n }\n });\n return instanceState;\n }\n\n private initializeServiceDefault(): DerivedServiceState<TConfig> {\n const serviceState: any = {};\n Object.keys(this.config).forEach((key) => {\n const item: ConfigItem<any> = this.config[key];\n if (item.partition === Partition.Service) {\n serviceState[key] = item.default;\n }\n });\n return serviceState;\n }\n\n private log(message: string, ...args: any[]) {\n if (this.debug) {\n console.log(`CrannSource [core], ` + message, ...args);\n }\n }\n private instanceLog(message: string, key: string, ...args: any[]) {\n if (this.debug) {\n console.log(`CrannSource [${key}], ` + message, ...args);\n }\n }\n private error(message: string, ...args: any[]) {\n console.error(`CrannSource [core], ` + message, ...args);\n }\n private warn(message: string, ...args: any[]) {\n console.warn(`CrannSource [core], ` + message, ...args);\n }\n}\n\nexport function create<TConfig extends Record<string, ConfigItem<any>>>(\n config: TConfig,\n options?: CrannOptions\n): [\n (key?: string) => DerivedState<TConfig>,\n (\n state: Partial<\n DerivedInstanceState<TConfig> & DerivedServiceState<TConfig>\n >,\n key?: string\n ) => Promise<void>,\n (\n listener: (\n state: DerivedInstanceState<TConfig> | DerivedState<TConfig>,\n changes: Partial<\n DerivedInstanceState<TConfig> & DerivedServiceState<TConfig>\n >,\n agent?: AgentInfo\n ) => void\n ) => void,\n (location: BrowserLocation) => string | null\n] {\n const instance = Crann.getInstance(config, options);\n return [\n instance.get.bind(instance),\n instance.set.bind(instance),\n instance.subscribe.bind(instance),\n instance.findInstance.bind(instance),\n ];\n}\n", "export const Partition = {\n Instance: \"instance\" as const,\n Service: \"service\" as const,\n};\n\nexport const Persistence = {\n Session: \"session\" as const,\n Local: \"local\" as const,\n None: \"none\" as const,\n};\n\ntype ConfigItem<T> = {\n default: T;\n partition?: (typeof Partition)[keyof typeof Partition];\n persist?: (typeof Persistence)[keyof typeof Persistence];\n};\n\ntype AnyConfig = Record<string, ConfigItem<any>>;\n\n// export type Config = typeof StateConfig;\n\ntype DerivedState<T extends AnyConfig> = {\n [P in keyof T]: T[P][\"default\"];\n};\n\ntype DerivedInstanceState<T extends AnyConfig> = {\n [P in keyof T as T[P][\"partition\"] extends \"instance\"\n ? P\n : never]: T[P][\"default\"];\n};\n\ntype DerivedServiceState<T extends AnyConfig> = {\n [P in keyof T as T[P][\"partition\"] extends \"service\"\n ? P\n : never]: T[P][\"default\"];\n};\n\ntype StateSubscriber<TConfig extends AnyConfig> = {\n keys?: Array<keyof DerivedState<TConfig>>;\n callback: (changes: StateUpdate<TConfig>) => void;\n};\n\ntype CrannAgent<TConfig extends AnyConfig> = {\n get: () => DerivedState<TConfig>;\n set: (update: StateUpdate<TConfig>) => void;\n subscribe: (\n callback: (changes: StateUpdate<TConfig>) => void,\n keys?: Array<keyof TConfig>\n ) => () => void;\n};\n\ntype UseCrann<TConfig extends AnyConfig> = <\n K extends keyof DerivedState<TConfig>\n>(\n key: K\n) => [\n DerivedState<TConfig>[K],\n (value: DerivedState<TConfig>[K]) => void,\n (callback: (value: DerivedState<TConfig>[K]) => void) => () => void\n];\n\ntype ConnectReturn<TConfig extends AnyConfig> = [\n UseCrann<TConfig>,\n CrannAgent<TConfig>[\"get\"],\n CrannAgent<TConfig>[\"set\"],\n CrannAgent<TConfig>[\"subscribe\"]\n];\n\ntype AgentSubscription<TConfig extends AnyConfig> = {\n (\n callback: (changes: StateUpdate<TConfig>) => void,\n key?: keyof DerivedState<TConfig>\n ): number;\n};\n\ntype StateUpdate<TConfig extends AnyConfig> = Partial<DerivedState<TConfig>>;\n\nexport type CrannOptions = {\n debug?: boolean;\n storagePrefix?: string;\n};\n\nexport {\n AnyConfig,\n ConfigItem,\n DerivedState,\n DerivedInstanceState,\n DerivedServiceState,\n StateSubscriber,\n CrannAgent,\n AgentSubscription,\n StateUpdate,\n DerivedState as State,\n ConnectReturn,\n UseCrann,\n};\n", "export function deepEqual(a: any, b: any): boolean {\n if (a === b) return true;\n\n if (a == null || typeof a !== 'object' || b == null || typeof b !== 'object') return false;\n\n const keysA = Object.keys(a);\n const keysB = Object.keys(b);\n\n if (keysA.length !== keysB.length) return false;\n\n keysA.sort();\n keysB.sort();\n\n for (let i = 0; i < keysA.length; i++) {\n const key = keysA[i];\n if (key !== keysB[i] || !deepEqual(a[key], b[key])) return false;\n }\n return true;\n}", "// Create a global debug state manager\nexport class DebugManager {\n private static _debug: boolean = false;\n\n static setDebug(value: boolean): void {\n DebugManager._debug = value;\n }\n\n static isDebugEnabled(): boolean {\n return DebugManager._debug;\n }\n}\n\n// Export a convenience function\nexport function isDebugEnabled(): boolean {\n return DebugManager.isDebugEnabled();\n}\n", "import { isDebugEnabled } from \"./debug\";\n\nexport type StateChangeMetadata = {\n source: string;\n timestamp: number;\n changes: any;\n instanceKey?: string;\n};\n\nexport function trackStateChange(\n target: any,\n propertyKey: string,\n descriptor: PropertyDescriptor\n): PropertyDescriptor {\n const originalMethod = descriptor.value;\n\n descriptor.value = function (...args: any[]) {\n // Only log if debugging is enabled\n if (isDebugEnabled()) {\n // Get the stack trace to find the actual caller\n const stack = new Error().stack;\n const lines = stack?.split(\"\\n\") || [];\n const callerMatch = lines[3]?.match(/at\\s+(\\S+)\\s+/);\n const caller = callerMatch ? callerMatch[1] : \"unknown\";\n\n const instanceKey = args.length > 1 ? args[1] : undefined;\n\n const metadata: StateChangeMetadata = {\n source: caller,\n timestamp: Date.now(),\n changes: args[0],\n instanceKey,\n };\n\n console.log(`Crann State Change:`, metadata);\n }\n return originalMethod.apply(this, args);\n };\n\n return descriptor;\n}\n", "import { match } from \"assert\";\nimport {\n ConfigItem,\n CrannAgent,\n DerivedState,\n StateSubscriber,\n DerivedInstanceState,\n DerivedServiceState,\n ConnectReturn,\n UseCrann,\n} from \"./model/crann.model\";\nimport { connect as connectPorter, PorterContext } from \"porter-source\";\n\nlet crannInstance: unknown = null;\n\nexport function connect<TConfig extends Record<string, ConfigItem<any>>>(\n config: TConfig,\n options?: { context?: string; debug?: boolean }\n): ConnectReturn<TConfig> {\n const debug = options?.debug || false;\n const context = options?.context;\n let _myKey = \"unset\";\n const log = (message: string, ...args: any[]) => {\n if (debug) {\n console.log(`CrannAgent [${_myKey}] ` + message, ...args);\n }\n };\n log(\"Initializing with context: \", context);\n if (crannInstance) {\n log(\"We had an instance already, returning\");\n return crannInstance as ConnectReturn<TConfig>;\n }\n log(\"No existing instance, creating a new one\");\n const [post, setMessages] = connectPorter({\n namespace: \"crann\",\n agentContext: context as PorterContext,\n });\n setMessages({\n initialState: (message) => {\n _state = message.payload.state;\n _myKey = message.payload.key;\n listeners.forEach((listener) => {\n listener.callback(_state);\n });\n log(`Initial state received and ${listeners.size} listeners notified`);\n },\n stateUpdate: (message) => {\n log(\"State updated: \", message);\n changes = message.payload.state;\n _state = { ..._state, ...changes };\n if (!!changes) {\n log(\"Notifying listeners of state update\");\n listeners.forEach((listener) => {\n if (listener.keys === undefined) {\n log(\"Found a universal listener, notifying\");\n listener.callback(changes!);\n } else {\n const matchFound = listener.keys.some((key) =>\n changes!.hasOwnProperty(key)\n );\n if (matchFound) {\n log(\"Found a specific listener for this item, notifying\");\n listener.callback(changes!);\n }\n }\n });\n }\n },\n });\n log(\"Porter connected. Setting up state and listeners\");\n let _state = getDerivedState(config);\n let changes: Partial<DerivedState<TConfig>> | null = null;\n const listeners = new Set<StateSubscriber<TConfig>>();\n\n log(\"Completed setup, returning instance\");\n\n const get = () => _state;\n const set = (newState: Partial<DerivedState<TConfig>>) => {\n console.log(\"CrannAgent, calling post with setState\");\n post({ action: \"setState\", payload: { state: newState } });\n };\n const subscribe = (\n callback: (changes: Partial<DerivedState<TConfig>>) => void,\n keys?: Array<keyof DerivedState<TConfig>>\n ): (() => void) => {\n const listener = { keys, callback };\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n };\n\n const useCrann: UseCrann<TConfig> = <K extends keyof DerivedState<TConfig>>(\n key: K\n ) => {\n const getValue = () => get()[key] as DerivedState<TConfig>;\n const setValue = (value: DerivedState<TConfig>[K]) =>\n set({ [key]: value } as Partial<DerivedState<TConfig>>);\n const subscribeToChanges = (\n callback: (value: DerivedState<TConfig>[K]) => void\n ) => {\n return subscribe(\n (changes) => {\n if (key in changes) {\n callback(changes[key] as DerivedState<TConfig>[K]);\n }\n },\n [key]\n );\n };\n\n return [getValue(), setValue, subscribeToChanges];\n };\n\n const instance: ConnectReturn<TConfig> = [useCrann, get, set, subscribe];\n crannInstance = instance;\n\n return crannInstance as ConnectReturn<TConfig>;\n}\n\nexport function connected(): boolean {\n return crannInstance !== null;\n}\n\nfunction getDerivedState<TConfig extends Record<string, ConfigItem<any>>>(\n config: TConfig\n): DerivedState<TConfig> {\n const instanceState = {} as DerivedInstanceState<TConfig>;\n\n Object.keys(config).forEach((key) => {\n const item: ConfigItem<any> = config[key];\n if (item.partition === \"instance\") {\n instanceState[key as keyof DerivedInstanceState<TConfig>] = item.default;\n }\n });\n\n const serviceState = {} as DerivedServiceState<TConfig>;\n Object.keys(config).forEach((key) => {\n const item: ConfigItem<any> = config[key];\n if (item.partition === \"instance\") {\n serviceState[key as keyof DerivedServiceState<TConfig>] = item.default;\n }\n });\n\n return {\n ...instanceState,\n ...serviceState,\n } as unknown as DerivedState<TConfig>;\n}\n", "import { useState, useEffect, useCallback, useMemo, useRef } from \"react\";\nimport { ConfigItem, DerivedState } from \"../model/crann.model\";\nimport { connect } from \"../crannAgent\";\n\nexport function createCrannStateHook<\n TConfig extends Record<string, ConfigItem<any>>\n>(config: TConfig) {\n return function useCrannState(context?: string) {\n const [useCrann, get, set, subscribe] = useMemo(() => {\n const instance = connect(config);\n return instance;\n }, [context]);\n\n const useStateItem = useCallback(\n <K extends keyof DerivedState<TConfig>>(key: K) => {\n const [value, setValue] = useState<DerivedState<TConfig>[K]>(\n get()[key]\n );\n const valueRef = useRef(value);\n\n useEffect(() => {\n valueRef.current = value;\n }, [value]);\n\n useEffect(() => {\n setValue(get()[key]);\n const unsubscribe = subscribe(\n (changes) => {\n if (key in changes) {\n setValue(changes[key] as DerivedState<TConfig>[K]);\n }\n },\n [key]\n );\n return unsubscribe;\n }, [key]);\n\n const updateValue = useCallback(\n (newValue: DerivedState<TConfig>[K]) => {\n set({ [key]: newValue } as Partial<DerivedState<TConfig>>);\n },\n [key]\n );\n\n return [value, updateValue] as const;\n },\n [get, set, subscribe]\n );\n\n const getState = useCallback(() => get(), [get]);\n\n const setState = useCallback(\n (newState: Partial<DerivedState<TConfig>>) => {\n set(newState);\n },\n [set]\n );\n\n return {\n useStateItem,\n getState,\n setState,\n useCrann,\n };\n };\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["export { create, Crann } from \"./crann\";\nexport { connect, connected } from \"./crannAgent\";\nexport { createCrannStateHook } from \"./hooks/useCrannState\";\nexport {\n CrannAgent,\n StateUpdate,\n State,\n Partition,\n Persistence,\n ConfigItem,\n DerivedState,\n} from \"./model/crann.model\";\n", "import browser from \"webextension-polyfill\";\nimport {\n DerivedInstanceState,\n DerivedServiceState,\n ConfigItem,\n DerivedState,\n Partition,\n CrannOptions,\n} from \"./model/crann.model\";\nimport {\n AgentInfo,\n source,\n getAgentById,\n getAgentByLocation,\n MessageTarget,\n} from \"porter-source\";\nimport { deepEqual } from \"./utils/deepEqual\";\nimport { Message, BrowserLocation } from \"porter-source\";\nimport { trackStateChange } from \"./utils/tracking\";\nimport { DebugManager } from \"./utils/debug\";\n\nexport class Crann<TConfig extends Record<string, ConfigItem<any>>> {\n private static instance: Crann<any> | null = null;\n private instances: Map<string, DerivedInstanceState<TConfig>> = new Map();\n private defaultServiceState: DerivedServiceState<TConfig>;\n private defaultInstanceState: DerivedInstanceState<TConfig>;\n private serviceState: DerivedServiceState<TConfig>;\n private stateChangeListeners: Array<\n (\n state: DerivedInstanceState<TConfig> | DerivedState<TConfig>,\n changes: Partial<\n DerivedServiceState<TConfig> & DerivedInstanceState<TConfig>\n >,\n agent?: AgentInfo\n ) => void\n > = [];\n private storagePrefix = \"crann_\";\n private post: (message: Message<any>, target?: MessageTarget) => void =\n () => {};\n private debug: boolean = false;\n\n constructor(private config: TConfig, options?: CrannOptions) {\n // Set the debug flag globally\n if (options?.debug) {\n DebugManager.setDebug(true);\n }\n this.debug = options?.debug || false;\n this.storagePrefix = options?.storagePrefix ?? this.storagePrefix;\n this.log(\"Constructing\");\n this.defaultInstanceState = this.initializeInstanceDefault();\n this.defaultServiceState = this.serviceState =\n this.initializeServiceDefault();\n this.hydrate();\n const [post, setMessages, onConnect, onDisconnect, onMessagesSet] =\n source(\"crann\");\n this.post = post;\n setMessages({\n setState: (message, info) => {\n if (!info) {\n this.log(\"setState message heard from unknown agent\");\n return;\n }\n\n const agentTag = this.getAgentTag(info);\n this.instanceLog(\"Setting state: \", agentTag, message);\n this.set(message.payload.state, info.id);\n },\n });\n onMessagesSet((info: AgentInfo) => {\n this.instanceLog(\n \"Messages set received. Sending initial state.\",\n this.getAgentTag(info),\n { info }\n );\n const fullState = this.get(info.id);\n this.post(\n {\n action: \"initialState\",\n payload: { state: fullState, key: info.id },\n },\n info.location\n );\n });\n onConnect((info: AgentInfo) => {\n const agentTag = this.getAgentTag(info);\n this.instanceLog(\"Agent connected \", agentTag, { info });\n this.addInstance(info.id);\n onDisconnect((info: AgentInfo) => {\n this.instanceLog(\n \"Agent disconnect heard. Connection type, context and location: \",\n this.getAgentTag(info),\n { info }\n );\n this.removeInstance(info.id);\n });\n });\n }\n\n public static getInstance<TConfig extends Record<string, ConfigItem<any>>>(\n config: TConfig,\n options?: CrannOptions\n ): Crann<TConfig> {\n if (!Crann.instance) {\n Crann.instance = new Crann(config, options);\n } else if (options?.debug) {\n console.log(\n \"CrannSource [static-core], Instance requested and already existed, returning\"\n );\n }\n return Crann.instance;\n }\n\n private async addInstance(key: string): Promise<void> {\n if (!this.instances.has(key)) {\n this.instanceLog(\"Adding instance from agent key: \", key);\n const initialInstanceState = {\n ...this.defaultInstanceState,\n } as DerivedInstanceState<TConfig>;\n this.instances.set(key, initialInstanceState);\n } else {\n this.instanceLog(\n \"Instance was already registered, ignoring request from key: \",\n key\n );\n }\n }\n\n private async removeInstance(key: string): Promise<void> {\n if (this.instances.has(key)) {\n this.instanceLog(\"Remove instance requested. \", key);\n this.instances.delete(key);\n } else {\n this.instanceLog(\n \"Remove instance requested but it did not exist!. \",\n key\n );\n }\n }\n\n @trackStateChange\n public async setServiceState(\n state: Partial<DerivedServiceState<TConfig>>\n ): Promise<void> {\n this.log(\"Request to set service state with: \", state);\n const update = { ...this.serviceState, ...state };\n if (!deepEqual(this.serviceState, update)) {\n this.log(\n \"Confirmed new state was different than existing so proceeding to persist then notify all connected instances.\"\n );\n this.serviceState = update;\n await this.persist(state);\n this.notify(state as Partial<DerivedState<TConfig>>);\n } else {\n this.log(\"New state seems to be the same as existing, skipping\");\n }\n }\n\n @trackStateChange\n public async setInstanceState(\n key: string,\n state: Partial<DerivedInstanceState<TConfig>>\n ): Promise<void> {\n this.instanceLog(\"Request to update instance state, update: \", key, state);\n const currentState = this.instances.get(key) || this.defaultInstanceState;\n const update = { ...currentState, ...state };\n if (!deepEqual(currentState, update)) {\n this.instanceLog(\n \"Instance state update is different, updating and notifying. \",\n key\n );\n this.instances.set(key, update);\n this.notify(state as Partial<DerivedState<TConfig>>, key);\n } else {\n this.instanceLog(\n \"Instance state update is not different, skipping update. \",\n key\n );\n }\n }\n\n // If we pass in specific state to persist, it only persists that state.\n // Otherwise persists all of the worker state.\n private async persist(\n state?: Partial<DerivedServiceState<TConfig>>\n ): Promise<void> {\n this.log(\"Persisting state\");\n let wasPersisted = false;\n for (const key in state || this.serviceState) {\n const item = this.config[key] as ConfigItem<any>;\n const persistence = item.persist || \"none\";\n const value = state\n ? state[key as keyof DerivedServiceState<TConfig>]\n : this.serviceState[key];\n switch (persistence) {\n case \"session\":\n await browser.storage.session.set({\n [this.storagePrefix + (key as string)]: value,\n });\n wasPersisted = true;\n break;\n case \"local\":\n await browser.storage.local.set({\n [this.storagePrefix + (key as string)]: value,\n });\n wasPersisted = true;\n break;\n default:\n break;\n }\n }\n if (wasPersisted) {\n this.log(\"State was persisted\");\n } else {\n this.log(\"Nothing to persist\");\n }\n }\n\n public async clear(): Promise<void> {\n this.log(\"Clearing state\");\n this.serviceState = this.defaultServiceState;\n this.instances.forEach((_, key) => {\n this.instances.set(key, this.defaultInstanceState);\n });\n await this.persist();\n this.notify({});\n }\n\n public subscribe(\n listener: (\n state: DerivedInstanceState<TConfig> | DerivedState<TConfig>,\n changes: Partial<\n DerivedInstanceState<TConfig> & DerivedServiceState<TConfig>\n >,\n agent?: AgentInfo\n ) => void\n ): void {\n this.log(\"Subscribing to state\");\n this.stateChangeListeners.push(listener);\n }\n\n // Right now we notify the instance even if the state change came from the instance.\n // This should probably be skipped for instance state, since it already knows.\n private notify(changes: Partial<DerivedState<TConfig>>, key?: string): void {\n const agent = key ? getAgentById(key) : undefined;\n const state = key ? this.get(key) : this.get();\n\n if (this.stateChangeListeners.length > 0) {\n this.log(\"Notifying state change listeners in source\");\n this.stateChangeListeners.forEach((listener) => {\n listener(state, changes, agent?.info);\n });\n }\n\n if (key && agent?.info.location) {\n this.instanceLog(\"Notifying of state change.\", key);\n this.post(\n { action: \"stateUpdate\", payload: { state: changes } },\n agent.info.location\n );\n } else {\n console.log(\"Notifying everyone\");\n // for every key of this.instances, post the state update to the corresponding key\n this.instances.forEach((_, key) => {\n this.post({ action: \"stateUpdate\", payload: { state: changes } }, key);\n });\n }\n }\n\n public get(): DerivedState<TConfig>;\n public get(\n key: string\n ): DerivedInstanceState<TConfig> & DerivedServiceState<TConfig>;\n public get(\n key?: string\n ): DerivedServiceState<TConfig> | DerivedState<TConfig> {\n if (!key) {\n return { ...this.serviceState, ...({} as DerivedInstanceState<TConfig>) };\n }\n return { ...this.serviceState, ...this.instances.get(key) };\n }\n\n // Todo: Should we return the instance data? What is the point of this.\n public findInstance(location: BrowserLocation): string | null {\n const agent = getAgentByLocation(location);\n if (!agent) {\n this.log(\"Could not find agent for location: \", { location });\n return null;\n }\n for (const [key, instance] of this.instances) {\n if (key === agent.info.id) {\n this.log(\"Found instance for key: \", key);\n return key;\n }\n }\n this.log(\"Could not find instance for context and location: \", {\n location,\n });\n return null;\n }\n\n public async set(state: Partial<DerivedServiceState<TConfig>>): Promise<void>;\n public async set(\n state: Partial<\n DerivedInstanceState<TConfig> & DerivedServiceState<TConfig>\n >,\n key: string\n ): Promise<void>;\n public async set(\n state: Partial<\n DerivedInstanceState<TConfig> | DerivedServiceState<TConfig>\n >,\n key?: string\n ): Promise<void> {\n const instance = {} as Partial<DerivedInstanceState<TConfig>>;\n const worker = {} as Partial<DerivedServiceState<TConfig>>;\n\n for (const itemKey in state) {\n const item = this.config[itemKey as keyof TConfig] as ConfigItem<any>;\n if (item.partition === \"instance\") {\n const instanceItemKey = itemKey as keyof DerivedInstanceState<TConfig>;\n const instanceState = state as Partial<DerivedInstanceState<TConfig>>;\n instance[instanceItemKey] = instanceState[instanceItemKey];\n } else if (!item.partition || item.partition === Partition.Service) {\n const serviceItemKey = itemKey as keyof DerivedServiceState<TConfig>;\n const serviceState = state as Partial<DerivedServiceState<TConfig>>;\n worker[serviceItemKey] = serviceState[serviceItemKey]!;\n }\n }\n if (key && Object.keys(instance).length > 0) {\n this.instanceLog(\"Setting instance state: \", key, instance);\n this.setInstanceState(key, instance);\n }\n if (Object.keys(worker).length > 0) {\n this.log(\"Setting service state: \", worker);\n this.setServiceState(worker);\n }\n }\n\n private async hydrate(): Promise<void> {\n this.log(\"Hydrating state from storage.\");\n const local = await browser.storage.local.get(null);\n const session = await browser.storage.session.get(null);\n const combined = { ...local, ...session };\n const update: Partial<DerivedServiceState<TConfig>> = {}; // Cast update as Partial<DerivedState<TConfig>>\n let hadItems = false;\n for (const prefixedKey in combined) {\n const key = this.removePrefix(prefixedKey);\n if (this.config.hasOwnProperty(key)) {\n const value = combined[key];\n update[key as keyof DerivedServiceState<TConfig>] = value;\n hadItems = true;\n }\n }\n if (hadItems) {\n this.log(\"Hydrated some items.\");\n } else {\n this.log(\"No items found in storage.\");\n }\n this.serviceState = { ...this.defaultServiceState, ...update };\n }\n\n private removePrefix(key: string): string {\n if (key.startsWith(this.storagePrefix)) {\n return key.replace(this.storagePrefix, \"\");\n }\n return key;\n }\n\n private getAgentTag(agent: AgentInfo): string {\n return `${agent.location.context}:${agent.location.tabId}:${agent.location.frameId}`;\n }\n\n private initializeInstanceDefault(): DerivedInstanceState<TConfig> {\n const instanceState: any = {};\n Object.keys(this.config).forEach((key) => {\n const item: ConfigItem<any> = this.config[key];\n if (item.partition === \"instance\") {\n instanceState[key] = item.default;\n }\n });\n return instanceState;\n }\n\n private initializeServiceDefault(): DerivedServiceState<TConfig> {\n const serviceState: any = {};\n Object.keys(this.config).forEach((key) => {\n const item: ConfigItem<any> = this.config[key];\n if (item.partition === Partition.Service) {\n serviceState[key] = item.default;\n }\n });\n return serviceState;\n }\n\n private log(message: string, ...args: any[]) {\n if (this.debug) {\n console.log(`CrannSource [core], ` + message, ...args);\n }\n }\n private instanceLog(message: string, key: string, ...args: any[]) {\n if (this.debug) {\n console.log(`CrannSource [${key}], ` + message, ...args);\n }\n }\n private error(message: string, ...args: any[]) {\n console.error(`CrannSource [core], ` + message, ...args);\n }\n private warn(message: string, ...args: any[]) {\n console.warn(`CrannSource [core], ` + message, ...args);\n }\n}\n\nexport function create<TConfig extends Record<string, ConfigItem<any>>>(\n config: TConfig,\n options?: CrannOptions\n): [\n (key?: string) => DerivedState<TConfig>,\n (\n state: Partial<\n DerivedInstanceState<TConfig> & DerivedServiceState<TConfig>\n >,\n key?: string\n ) => Promise<void>,\n (\n listener: (\n state: DerivedInstanceState<TConfig> | DerivedState<TConfig>,\n changes: Partial<\n DerivedInstanceState<TConfig> & DerivedServiceState<TConfig>\n >,\n agent?: AgentInfo\n ) => void\n ) => void,\n (location: BrowserLocation) => string | null\n] {\n const instance = Crann.getInstance(config, options);\n return [\n instance.get.bind(instance),\n instance.set.bind(instance),\n instance.subscribe.bind(instance),\n instance.findInstance.bind(instance),\n ];\n}\n", "export const Partition = {\n Instance: \"instance\" as const,\n Service: \"service\" as const,\n};\n\nexport const Persistence = {\n Session: \"session\" as const,\n Local: \"local\" as const,\n None: \"none\" as const,\n};\n\ntype ConfigItem<T> = {\n default: T;\n partition?: (typeof Partition)[keyof typeof Partition];\n persist?: (typeof Persistence)[keyof typeof Persistence];\n};\n\ntype AnyConfig = Record<string, ConfigItem<any>>;\n\n// export type Config = typeof StateConfig;\n\ntype DerivedState<T extends AnyConfig> = {\n [P in keyof T]: T[P][\"default\"];\n};\n\ntype DerivedInstanceState<T extends AnyConfig> = {\n [P in keyof T as T[P][\"partition\"] extends \"instance\"\n ? P\n : never]: T[P][\"default\"];\n};\n\ntype DerivedServiceState<T extends AnyConfig> = {\n [P in keyof T as T[P][\"partition\"] extends \"service\"\n ? P\n : never]: T[P][\"default\"];\n};\n\ntype StateSubscriber<TConfig extends AnyConfig> = {\n keys?: Array<keyof DerivedState<TConfig>>;\n callback: (changes: StateUpdate<TConfig>) => void;\n};\n\ntype CrannAgent<TConfig extends AnyConfig> = {\n get: () => DerivedState<TConfig>;\n set: (update: StateUpdate<TConfig>) => void;\n subscribe: (\n callback: (changes: StateUpdate<TConfig>) => void,\n keys?: Array<keyof TConfig>\n ) => () => void;\n};\n\ntype UseCrann<TConfig extends AnyConfig> = <\n K extends keyof DerivedState<TConfig>\n>(\n key: K\n) => [\n DerivedState<TConfig>[K],\n (value: DerivedState<TConfig>[K]) => void,\n (callback: (value: DerivedState<TConfig>[K]) => void) => () => void\n];\n\ntype ConnectReturn<TConfig extends AnyConfig> = [\n UseCrann<TConfig>,\n CrannAgent<TConfig>[\"get\"],\n CrannAgent<TConfig>[\"set\"],\n CrannAgent<TConfig>[\"subscribe\"]\n];\n\ntype AgentSubscription<TConfig extends AnyConfig> = {\n (\n callback: (changes: StateUpdate<TConfig>) => void,\n key?: keyof DerivedState<TConfig>\n ): number;\n};\n\ntype StateUpdate<TConfig extends AnyConfig> = Partial<DerivedState<TConfig>>;\n\nexport type CrannOptions = {\n debug?: boolean;\n storagePrefix?: string;\n};\n\nexport {\n AnyConfig,\n ConfigItem,\n DerivedState,\n DerivedInstanceState,\n DerivedServiceState,\n StateSubscriber,\n CrannAgent,\n AgentSubscription,\n StateUpdate,\n DerivedState as State,\n ConnectReturn,\n UseCrann,\n};\n", "export function deepEqual(a: any, b: any): boolean {\n if (a === b) return true;\n\n if (a == null || typeof a !== 'object' || b == null || typeof b !== 'object') return false;\n\n const keysA = Object.keys(a);\n const keysB = Object.keys(b);\n\n if (keysA.length !== keysB.length) return false;\n\n keysA.sort();\n keysB.sort();\n\n for (let i = 0; i < keysA.length; i++) {\n const key = keysA[i];\n if (key !== keysB[i] || !deepEqual(a[key], b[key])) return false;\n }\n return true;\n}", "// Create a global debug state manager\nexport class DebugManager {\n private static _debug: boolean = false;\n\n static setDebug(value: boolean): void {\n DebugManager._debug = value;\n }\n\n static isDebugEnabled(): boolean {\n return DebugManager._debug;\n }\n}\n\n// Export a convenience function\nexport function isDebugEnabled(): boolean {\n return DebugManager.isDebugEnabled();\n}\n", "import { isDebugEnabled } from \"./debug\";\n\nexport type StateChangeMetadata = {\n source: string;\n timestamp: number;\n changes: any;\n instanceKey?: string;\n};\n\nexport function trackStateChange(\n target: any,\n propertyKey: string,\n descriptor: PropertyDescriptor\n): PropertyDescriptor {\n const originalMethod = descriptor.value;\n\n descriptor.value = function (...args: any[]) {\n // Only log if debugging is enabled\n if (isDebugEnabled()) {\n // Get the stack trace to find the actual caller\n const stack = new Error().stack;\n const lines = stack?.split(\"\\n\") || [];\n const callerMatch = lines[3]?.match(/at\\s+(\\S+)\\s+/);\n const caller = callerMatch ? callerMatch[1] : \"unknown\";\n\n const instanceKey = args.length > 1 ? args[1] : undefined;\n\n const metadata: StateChangeMetadata = {\n source: caller,\n timestamp: Date.now(),\n changes: args[0],\n instanceKey,\n };\n\n console.log(`Crann State Change:`, metadata);\n }\n return originalMethod.apply(this, args);\n };\n\n return descriptor;\n}\n", "import {\n ConfigItem,\n DerivedState,\n StateSubscriber,\n DerivedInstanceState,\n DerivedServiceState,\n ConnectReturn,\n UseCrann,\n} from \"./model/crann.model\";\nimport { connect as connectPorter, PorterContext } from \"porter-source\";\n\nlet crannInstance: unknown = null;\n\nexport function connect<TConfig extends Record<string, ConfigItem<any>>>(\n config: TConfig,\n options?: { context?: string; debug?: boolean }\n): ConnectReturn<TConfig> {\n const debug = options?.debug || false;\n const context = options?.context;\n let _myKey = \"unset\";\n const log = (message: string, ...args: any[]) => {\n if (debug) {\n console.log(`CrannAgent [${_myKey}] ` + message, ...args);\n }\n };\n log(\"Initializing with context: \", context);\n if (crannInstance) {\n log(\"We had an instance already, returning\");\n return crannInstance as ConnectReturn<TConfig>;\n }\n log(\"No existing instance, creating a new one\");\n const [post, setMessages] = connectPorter({\n namespace: \"crann\",\n agentContext: context as PorterContext,\n });\n setMessages({\n initialState: (message) => {\n _state = message.payload.state;\n _myKey = message.payload.key;\n listeners.forEach((listener) => {\n listener.callback(_state);\n });\n log(`Initial state received and ${listeners.size} listeners notified`);\n },\n stateUpdate: (message) => {\n log(\"State updated: \", message);\n changes = message.payload.state;\n _state = { ..._state, ...changes };\n if (!!changes) {\n log(\"Notifying listeners of state update\");\n listeners.forEach((listener) => {\n if (listener.keys === undefined) {\n log(\"Found a universal listener, notifying\");\n listener.callback(changes!);\n } else {\n const matchFound = listener.keys.some((key) =>\n changes!.hasOwnProperty(key)\n );\n if (matchFound) {\n log(\"Found a specific listener for this item, notifying\");\n listener.callback(changes!);\n }\n }\n });\n }\n },\n });\n log(\"Porter connected. Setting up state and listeners\");\n let _state = getDerivedState(config);\n let changes: Partial<DerivedState<TConfig>> | null = null;\n const listeners = new Set<StateSubscriber<TConfig>>();\n\n log(\"Completed setup, returning instance\");\n\n const get = () => _state;\n const set = (newState: Partial<DerivedState<TConfig>>) => {\n console.log(\"CrannAgent, calling post with setState\");\n post({ action: \"setState\", payload: { state: newState } });\n };\n const subscribe = (\n callback: (changes: Partial<DerivedState<TConfig>>) => void,\n keys?: Array<keyof DerivedState<TConfig>>\n ): (() => void) => {\n const listener = { keys, callback };\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n };\n\n const useCrann: UseCrann<TConfig> = <K extends keyof DerivedState<TConfig>>(\n key: K\n ) => {\n const getValue = () => get()[key] as DerivedState<TConfig>;\n const setValue = (value: DerivedState<TConfig>[K]) =>\n set({ [key]: value } as Partial<DerivedState<TConfig>>);\n const subscribeToChanges = (\n callback: (value: DerivedState<TConfig>[K]) => void\n ) => {\n return subscribe(\n (changes) => {\n if (key in changes) {\n callback(changes[key] as DerivedState<TConfig>[K]);\n }\n },\n [key]\n );\n };\n\n return [getValue(), setValue, subscribeToChanges];\n };\n\n const instance: ConnectReturn<TConfig> = [useCrann, get, set, subscribe];\n crannInstance = instance;\n\n return crannInstance as ConnectReturn<TConfig>;\n}\n\nexport function connected(): boolean {\n return crannInstance !== null;\n}\n\nfunction getDerivedState<TConfig extends Record<string, ConfigItem<any>>>(\n config: TConfig\n): DerivedState<TConfig> {\n const instanceState = {} as DerivedInstanceState<TConfig>;\n\n Object.keys(config).forEach((key) => {\n const item: ConfigItem<any> = config[key];\n if (item.partition === \"instance\") {\n instanceState[key as keyof DerivedInstanceState<TConfig>] = item.default;\n }\n });\n\n const serviceState = {} as DerivedServiceState<TConfig>;\n Object.keys(config).forEach((key) => {\n const item: ConfigItem<any> = config[key];\n if (item.partition === \"instance\") {\n serviceState[key as keyof DerivedServiceState<TConfig>] = item.default;\n }\n });\n\n return {\n ...instanceState,\n ...serviceState,\n } as unknown as DerivedState<TConfig>;\n}\n", "import { useState, useEffect, useCallback, useMemo, useRef } from \"react\";\nimport { ConfigItem, DerivedState } from \"../model/crann.model\";\nimport { connect } from \"../crannAgent\";\n\nexport function createCrannStateHook<\n TConfig extends Record<string, ConfigItem<any>>\n>(config: TConfig) {\n return function useCrannState(context?: string) {\n const [useCrann, get, set, subscribe] = useMemo(() => {\n const instance = connect(config);\n return instance;\n }, [context]);\n\n const useStateItem = useCallback(\n <K extends keyof DerivedState<TConfig>>(key: K) => {\n const [value, setValue] = useState<DerivedState<TConfig>[K]>(\n get()[key]\n );\n const valueRef = useRef(value);\n\n useEffect(() => {\n valueRef.current = value;\n }, [value]);\n\n useEffect(() => {\n setValue(get()[key]);\n const unsubscribe = subscribe(\n (changes) => {\n if (key in changes) {\n setValue(changes[key] as DerivedState<TConfig>[K]);\n }\n },\n [key]\n );\n return unsubscribe;\n }, [key]);\n\n const updateValue = useCallback(\n (newValue: DerivedState<TConfig>[K]) => {\n set({ [key]: newValue } as Partial<DerivedState<TConfig>>);\n },\n [key]\n );\n\n return [value, updateValue] as const;\n },\n [get, set, subscribe]\n );\n\n const getState = useCallback(() => get(), [get]);\n\n const setState = useCallback(\n (newState: Partial<DerivedState<TConfig>>) => {\n set(newState);\n },\n [set]\n );\n\n return {\n useStateItem,\n getState,\n setState,\n useCrann,\n };\n };\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["src_exports", "__export", "Crann", "Partition", "Persistence", "connect", "connected", "create", "createCrannStateHook", "__toCommonJS", "import_webextension_polyfill", "Partition", "Persistence", "import_porter_source", "deepEqual", "a", "b", "keysA", "keysB", "key", "_DebugManager", "value", "DebugManager", "isDebugEnabled", "trackStateChange", "target", "propertyKey", "descriptor", "originalMethod", "args", "_a", "isDebugEnabled", "stack", "callerMatch", "caller", "instanceKey", "metadata", "_Crann", "config", "options", "DebugManager", "post", "setMessages", "onConnect", "onDisconnect", "onMessagesSet", "message", "info", "agentTag", "fullState", "key", "initialInstanceState", "state", "update", "deepEqual", "currentState", "wasPersisted", "persistence", "value", "browser", "_", "listener", "changes", "agent", "location", "instance", "worker", "itemKey", "item", "instanceItemKey", "instanceState", "Partition", "serviceItemKey", "serviceState", "local", "session", "combined", "hadItems", "prefixedKey", "args", "__decorateClass", "trackStateChange", "Crann", "create", "import_porter_source", "crannInstance", "connect", "config", "options", "debug", "context", "_myKey", "log", "message", "args", "post", "setMessages", "connectPorter", "_state", "listeners", "listener", "changes", "key", "getDerivedState", "get", "set", "newState", "subscribe", "callback", "keys", "getValue", "setValue", "value", "subscribeToChanges", "connected", "instanceState", "item", "serviceState", "import_react", "createCrannStateHook", "config", "context", "useCrann", "get", "set", "subscribe", "connect", "useStateItem", "key", "value", "setValue", "valueRef", "changes", "updateValue", "newValue", "getState", "setState", "newState"]
7
7
  }
package/dist/esm/index.js CHANGED
@@ -1,3 +1,3 @@
1
- var M=Object.defineProperty;var j=Object.getOwnPropertyDescriptor;var k=(c,e,t,n)=>{for(var i=n>1?void 0:n?j(e,t):e,a=c.length-1,r;a>=0;a--)(r=c[a])&&(i=(n?r(e,t,i):r(i))||i);return n&&i&&M(e,t,i),i};import b from"webextension-polyfill";var m={Instance:"instance",Service:"service"},N={Session:"session",Local:"local",None:"none"};import{source as q,getAgentById as z,getAgentByLocation as B}from"porter-source";function D(c,e){if(c===e)return!0;if(c==null||typeof c!="object"||e==null||typeof e!="object")return!1;let t=Object.keys(c),n=Object.keys(e);if(t.length!==n.length)return!1;t.sort(),n.sort();for(let i=0;i<t.length;i++){let a=t[i];if(a!==n[i]||!D(c[a],e[a]))return!1}return!0}var h=class h{static setDebug(e){h._debug=e}static isDebugEnabled(){return h._debug}};h._debug=!1;var p=h;function O(){return p.isDebugEnabled()}function K(c,e,t){let n=t.value;return t.value=function(...i){var a;if(O()){let r=new Error().stack,f=(a=((r==null?void 0:r.split(`
2
- `))||[])[3])==null?void 0:a.match(/at\s+(\S+)\s+/),o=f?f[1]:"unknown",s=i.length>1?i[1]:void 0,l={source:o,timestamp:Date.now(),changes:i[0],instanceKey:s};console.log("Crann State Change:",l)}return n.apply(this,i)},t}var v=class v{constructor(e,t){this.config=e;this.instances=new Map;this.stateChangeListeners=[];this.storagePrefix="crann_";this.post=()=>{};this.debug=!1;var f;t!=null&&t.debug&&p.setDebug(!0),this.debug=(t==null?void 0:t.debug)||!1,this.storagePrefix=(f=t==null?void 0:t.storagePrefix)!=null?f:this.storagePrefix,this.log("Constructing"),this.defaultInstanceState=this.initializeInstanceDefault(),this.defaultServiceState=this.serviceState=this.initializeServiceDefault(),this.hydrate();let[n,i,a,r,d]=q("crann");this.post=n,i({setState:(o,s)=>{if(!s){this.log("setState message heard from unknown agent");return}let l=this.getAgentTag(s);this.instanceLog("Setting state: ",l,o),this.set(o.payload.state,s.id)}}),d(o=>{this.instanceLog("Messages set received. Sending initial state.",this.getAgentTag(o),{info:o});let s=this.get(o.id);this.post({action:"initialState",payload:{state:s,key:o.id}},o.location)}),a(o=>{let s=this.getAgentTag(o);this.instanceLog("Agent connected ",s,{info:o}),this.addInstance(o.id),r(l=>{this.instanceLog("Agent disconnect heard. Connection type, context and location: ",this.getAgentTag(l),{info:l}),this.removeInstance(l.id)})})}static getInstance(e,t){return v.instance?t!=null&&t.debug&&console.log("CrannSource [static-core], Instance requested and already existed, returning"):v.instance=new v(e,t),v.instance}async addInstance(e){if(this.instances.has(e))this.instanceLog("Instance was already registered, ignoring request from key: ",e);else{this.instanceLog("Adding instance from agent key: ",e);let t={...this.defaultInstanceState};this.instances.set(e,t)}}async removeInstance(e){this.instances.has(e)?(this.instanceLog("Remove instance requested. ",e),this.instances.delete(e)):this.instanceLog("Remove instance requested but it did not exist!. ",e)}async setServiceState(e){this.log("Request to set service state with: ",e);let t={...this.serviceState,...e};D(this.serviceState,t)?this.log("New state seems to be the same as existing, skipping"):(this.log("Confirmed new state was different than existing so proceeding to persist then notify all connected instances."),this.serviceState=t,await this.persist(e),this.notify(e))}async setInstanceState(e,t){this.instanceLog("Request to update instance state, update: ",e,t);let n=this.instances.get(e)||this.defaultInstanceState,i={...n,...t};D(n,i)?this.instanceLog("Instance state update is not different, skipping update. ",e):(this.instanceLog("Instance state update is different, updating and notifying. ",e),this.instances.set(e,i),this.notify(t,e))}async persist(e){this.log("Persisting state");let t=!1;for(let n in e||this.serviceState){let a=this.config[n].persist||"none",r=e?e[n]:this.serviceState[n];switch(a){case"session":await b.storage.session.set({[this.storagePrefix+n]:r}),t=!0;break;case"local":await b.storage.local.set({[this.storagePrefix+n]:r}),t=!0;break;default:break}}t?this.log("State was persisted"):this.log("Nothing to persist")}async clear(){this.log("Clearing state"),this.serviceState=this.defaultServiceState,this.instances.forEach((e,t)=>{this.instances.set(t,this.defaultInstanceState)}),await this.persist(),this.notify({})}subscribe(e){this.log("Subscribing to state"),this.stateChangeListeners.push(e)}notify(e,t){let n=t?z(t):void 0,i=t?this.get(t):this.get();this.stateChangeListeners.length>0&&(this.log("Notifying state change listeners in source"),this.stateChangeListeners.forEach(a=>{a(i,e,n==null?void 0:n.info)})),t&&(n!=null&&n.info.location)?(this.instanceLog("Notifying of state change.",t),this.post({action:"stateUpdate",payload:{state:e}},n.info.location)):(console.log("Notifying everyone"),this.instances.forEach((a,r)=>{this.post({action:"stateUpdate",payload:{state:e}},r)}))}get(e){return e?{...this.serviceState,...this.instances.get(e)}:{...this.serviceState}}findInstance(e){let t=B(e);if(!t)return this.log("Could not find agent for location: ",{location:e}),null;for(let[n,i]of this.instances)if(n===t.info.id)return this.log("Found instance for key: ",n),n;return this.log("Could not find instance for context and location: ",{location:e}),null}async set(e,t){let n={},i={};for(let a in e){let r=this.config[a];if(r.partition==="instance"){let d=a,f=e;n[d]=f[d]}else if(!r.partition||r.partition===m.Service){let d=a,f=e;i[d]=f[d]}}t&&Object.keys(n).length>0&&(this.instanceLog("Setting instance state: ",t,n),this.setInstanceState(t,n)),Object.keys(i).length>0&&(this.log("Setting service state: ",i),this.setServiceState(i))}async hydrate(){this.log("Hydrating state from storage.");let e=await b.storage.local.get(null),t=await b.storage.session.get(null),n={...e,...t},i={},a=!1;for(let r in n){let d=this.removePrefix(r);if(this.config.hasOwnProperty(d)){let f=n[d];i[d]=f,a=!0}}a?this.log("Hydrated some items."):this.log("No items found in storage."),this.serviceState={...this.defaultServiceState,...i}}removePrefix(e){return e.startsWith(this.storagePrefix)?e.replace(this.storagePrefix,""):e}getAgentTag(e){return`${e.location.context}:${e.location.tabId}:${e.location.frameId}`}initializeInstanceDefault(){let e={};return Object.keys(this.config).forEach(t=>{let n=this.config[t];n.partition==="instance"&&(e[t]=n.default)}),e}initializeServiceDefault(){let e={};return Object.keys(this.config).forEach(t=>{let n=this.config[t];n.partition===m.Service&&(e[t]=n.default)}),e}log(e,...t){this.debug&&console.log("CrannSource [core], "+e,...t)}instanceLog(e,t,...n){this.debug&&console.log(`CrannSource [${t}], `+e,...n)}error(e,...t){console.error("CrannSource [core], "+e,...t)}warn(e,...t){console.warn("CrannSource [core], "+e,...t)}};v.instance=null,k([K],v.prototype,"setServiceState",1),k([K],v.prototype,"setInstanceState",1);var I=v;function $(c,e){let t=I.getInstance(c,e);return[t.get.bind(t),t.set.bind(t),t.subscribe.bind(t),t.findInstance.bind(t)]}import{connect as F}from"porter-source";var T=null;function L(c,e){let t=(e==null?void 0:e.debug)||!1,n=e==null?void 0:e.context,i="unset",a=(g,...u)=>{t&&console.log(`CrannAgent [${i}] `+g,...u)};if(a("Initializing with context: ",n),T)return a("We had an instance already, returning"),T;a("No existing instance, creating a new one");let[r,d]=F({namespace:"crann",agentContext:n});d({initialState:g=>{f=g.payload.state,i=g.payload.key,s.forEach(u=>{u.callback(f)}),a(`Initial state received and ${s.size} listeners notified`)},stateUpdate:g=>{a("State updated: ",g),o=g.payload.state,f={...f,...o},o&&(a("Notifying listeners of state update"),s.forEach(u=>{u.keys===void 0?(a("Found a universal listener, notifying"),u.callback(o)):u.keys.some(A=>o.hasOwnProperty(A))&&(a("Found a specific listener for this item, notifying"),u.callback(o))}))}}),a("Porter connected. Setting up state and listeners");let f=V(c),o=null,s=new Set;a("Completed setup, returning instance");let l=()=>f,S=g=>{console.log("CrannAgent, calling post with setState"),r({action:"setState",payload:{state:g}})},y=(g,u)=>{let C={keys:u,callback:g};return s.add(C),()=>{s.delete(C)}};return T=[g=>{let u=()=>l()[g],C=w=>S({[g]:w}),A=w=>y(E=>{g in E&&w(E[g])},[g]);return[u(),C,A]},l,S,y],T}function H(){return T!==null}function V(c){let e={};Object.keys(c).forEach(n=>{let i=c[n];i.partition==="instance"&&(e[n]=i.default)});let t={};return Object.keys(c).forEach(n=>{let i=c[n];i.partition==="instance"&&(t[n]=i.default)}),{...e,...t}}import{useState as W,useEffect as U,useCallback as P,useMemo as G,useRef as J}from"react";function Q(c){return function(t){let[n,i,a,r]=G(()=>L(c),[t]),d=P(s=>{let[l,S]=W(i()[s]),y=J(l);U(()=>{y.current=l},[l]),U(()=>(S(i()[s]),r(g=>{s in g&&S(g[s])},[s])),[s]);let R=P(x=>{a({[s]:x})},[s]);return[l,R]},[i,a,r]),f=P(()=>i(),[i]),o=P(s=>{a(s)},[a]);return{useStateItem:d,getState:f,setState:o,useCrann:n}}}export{I as Crann,m as Partition,N as Persistence,L as connect,H as connected,$ as create,Q as createCrannStateHook};
1
+ var M=Object.defineProperty;var j=Object.getOwnPropertyDescriptor;var k=(c,e,t,n)=>{for(var i=n>1?void 0:n?j(e,t):e,a=c.length-1,r;a>=0;a--)(r=c[a])&&(i=(n?r(e,t,i):r(i))||i);return n&&i&&M(e,t,i),i};import b from"webextension-polyfill";var D={Instance:"instance",Service:"service"},N={Session:"session",Local:"local",None:"none"};import{source as q,getAgentById as z,getAgentByLocation as B}from"porter-source";function m(c,e){if(c===e)return!0;if(c==null||typeof c!="object"||e==null||typeof e!="object")return!1;let t=Object.keys(c),n=Object.keys(e);if(t.length!==n.length)return!1;t.sort(),n.sort();for(let i=0;i<t.length;i++){let a=t[i];if(a!==n[i]||!m(c[a],e[a]))return!1}return!0}var h=class h{static setDebug(e){h._debug=e}static isDebugEnabled(){return h._debug}};h._debug=!1;var p=h;function O(){return p.isDebugEnabled()}function K(c,e,t){let n=t.value;return t.value=function(...i){var a;if(O()){let r=new Error().stack,f=(a=((r==null?void 0:r.split(`
2
+ `))||[])[3])==null?void 0:a.match(/at\s+(\S+)\s+/),o=f?f[1]:"unknown",s=i.length>1?i[1]:void 0,l={source:o,timestamp:Date.now(),changes:i[0],instanceKey:s};console.log("Crann State Change:",l)}return n.apply(this,i)},t}var v=class v{constructor(e,t){this.config=e;this.instances=new Map;this.stateChangeListeners=[];this.storagePrefix="crann_";this.post=()=>{};this.debug=!1;var f;t!=null&&t.debug&&p.setDebug(!0),this.debug=(t==null?void 0:t.debug)||!1,this.storagePrefix=(f=t==null?void 0:t.storagePrefix)!=null?f:this.storagePrefix,this.log("Constructing"),this.defaultInstanceState=this.initializeInstanceDefault(),this.defaultServiceState=this.serviceState=this.initializeServiceDefault(),this.hydrate();let[n,i,a,r,d]=q("crann");this.post=n,i({setState:(o,s)=>{if(!s){this.log("setState message heard from unknown agent");return}let l=this.getAgentTag(s);this.instanceLog("Setting state: ",l,o),this.set(o.payload.state,s.id)}}),d(o=>{this.instanceLog("Messages set received. Sending initial state.",this.getAgentTag(o),{info:o});let s=this.get(o.id);this.post({action:"initialState",payload:{state:s,key:o.id}},o.location)}),a(o=>{let s=this.getAgentTag(o);this.instanceLog("Agent connected ",s,{info:o}),this.addInstance(o.id),r(l=>{this.instanceLog("Agent disconnect heard. Connection type, context and location: ",this.getAgentTag(l),{info:l}),this.removeInstance(l.id)})})}static getInstance(e,t){return v.instance?t!=null&&t.debug&&console.log("CrannSource [static-core], Instance requested and already existed, returning"):v.instance=new v(e,t),v.instance}async addInstance(e){if(this.instances.has(e))this.instanceLog("Instance was already registered, ignoring request from key: ",e);else{this.instanceLog("Adding instance from agent key: ",e);let t={...this.defaultInstanceState};this.instances.set(e,t)}}async removeInstance(e){this.instances.has(e)?(this.instanceLog("Remove instance requested. ",e),this.instances.delete(e)):this.instanceLog("Remove instance requested but it did not exist!. ",e)}async setServiceState(e){this.log("Request to set service state with: ",e);let t={...this.serviceState,...e};m(this.serviceState,t)?this.log("New state seems to be the same as existing, skipping"):(this.log("Confirmed new state was different than existing so proceeding to persist then notify all connected instances."),this.serviceState=t,await this.persist(e),this.notify(e))}async setInstanceState(e,t){this.instanceLog("Request to update instance state, update: ",e,t);let n=this.instances.get(e)||this.defaultInstanceState,i={...n,...t};m(n,i)?this.instanceLog("Instance state update is not different, skipping update. ",e):(this.instanceLog("Instance state update is different, updating and notifying. ",e),this.instances.set(e,i),this.notify(t,e))}async persist(e){this.log("Persisting state");let t=!1;for(let n in e||this.serviceState){let a=this.config[n].persist||"none",r=e?e[n]:this.serviceState[n];switch(a){case"session":await b.storage.session.set({[this.storagePrefix+n]:r}),t=!0;break;case"local":await b.storage.local.set({[this.storagePrefix+n]:r}),t=!0;break;default:break}}t?this.log("State was persisted"):this.log("Nothing to persist")}async clear(){this.log("Clearing state"),this.serviceState=this.defaultServiceState,this.instances.forEach((e,t)=>{this.instances.set(t,this.defaultInstanceState)}),await this.persist(),this.notify({})}subscribe(e){this.log("Subscribing to state"),this.stateChangeListeners.push(e)}notify(e,t){let n=t?z(t):void 0,i=t?this.get(t):this.get();this.stateChangeListeners.length>0&&(this.log("Notifying state change listeners in source"),this.stateChangeListeners.forEach(a=>{a(i,e,n==null?void 0:n.info)})),t&&(n!=null&&n.info.location)?(this.instanceLog("Notifying of state change.",t),this.post({action:"stateUpdate",payload:{state:e}},n.info.location)):(console.log("Notifying everyone"),this.instances.forEach((a,r)=>{this.post({action:"stateUpdate",payload:{state:e}},r)}))}get(e){return e?{...this.serviceState,...this.instances.get(e)}:{...this.serviceState}}findInstance(e){let t=B(e);if(!t)return this.log("Could not find agent for location: ",{location:e}),null;for(let[n,i]of this.instances)if(n===t.info.id)return this.log("Found instance for key: ",n),n;return this.log("Could not find instance for context and location: ",{location:e}),null}async set(e,t){let n={},i={};for(let a in e){let r=this.config[a];if(r.partition==="instance"){let d=a,f=e;n[d]=f[d]}else if(!r.partition||r.partition===D.Service){let d=a,f=e;i[d]=f[d]}}t&&Object.keys(n).length>0&&(this.instanceLog("Setting instance state: ",t,n),this.setInstanceState(t,n)),Object.keys(i).length>0&&(this.log("Setting service state: ",i),this.setServiceState(i))}async hydrate(){this.log("Hydrating state from storage.");let e=await b.storage.local.get(null),t=await b.storage.session.get(null),n={...e,...t},i={},a=!1;for(let r in n){let d=this.removePrefix(r);if(this.config.hasOwnProperty(d)){let f=n[d];i[d]=f,a=!0}}a?this.log("Hydrated some items."):this.log("No items found in storage."),this.serviceState={...this.defaultServiceState,...i}}removePrefix(e){return e.startsWith(this.storagePrefix)?e.replace(this.storagePrefix,""):e}getAgentTag(e){return`${e.location.context}:${e.location.tabId}:${e.location.frameId}`}initializeInstanceDefault(){let e={};return Object.keys(this.config).forEach(t=>{let n=this.config[t];n.partition==="instance"&&(e[t]=n.default)}),e}initializeServiceDefault(){let e={};return Object.keys(this.config).forEach(t=>{let n=this.config[t];n.partition===D.Service&&(e[t]=n.default)}),e}log(e,...t){this.debug&&console.log("CrannSource [core], "+e,...t)}instanceLog(e,t,...n){this.debug&&console.log(`CrannSource [${t}], `+e,...n)}error(e,...t){console.error("CrannSource [core], "+e,...t)}warn(e,...t){console.warn("CrannSource [core], "+e,...t)}};v.instance=null,k([K],v.prototype,"setServiceState",1),k([K],v.prototype,"setInstanceState",1);var I=v;function $(c,e){let t=I.getInstance(c,e);return[t.get.bind(t),t.set.bind(t),t.subscribe.bind(t),t.findInstance.bind(t)]}import{connect as F}from"porter-source";var T=null;function L(c,e){let t=(e==null?void 0:e.debug)||!1,n=e==null?void 0:e.context,i="unset",a=(g,...u)=>{t&&console.log(`CrannAgent [${i}] `+g,...u)};if(a("Initializing with context: ",n),T)return a("We had an instance already, returning"),T;a("No existing instance, creating a new one");let[r,d]=F({namespace:"crann",agentContext:n});d({initialState:g=>{f=g.payload.state,i=g.payload.key,s.forEach(u=>{u.callback(f)}),a(`Initial state received and ${s.size} listeners notified`)},stateUpdate:g=>{a("State updated: ",g),o=g.payload.state,f={...f,...o},o&&(a("Notifying listeners of state update"),s.forEach(u=>{u.keys===void 0?(a("Found a universal listener, notifying"),u.callback(o)):u.keys.some(A=>o.hasOwnProperty(A))&&(a("Found a specific listener for this item, notifying"),u.callback(o))}))}}),a("Porter connected. Setting up state and listeners");let f=V(c),o=null,s=new Set;a("Completed setup, returning instance");let l=()=>f,S=g=>{console.log("CrannAgent, calling post with setState"),r({action:"setState",payload:{state:g}})},y=(g,u)=>{let C={keys:u,callback:g};return s.add(C),()=>{s.delete(C)}};return T=[g=>{let u=()=>l()[g],C=w=>S({[g]:w}),A=w=>y(E=>{g in E&&w(E[g])},[g]);return[u(),C,A]},l,S,y],T}function H(){return T!==null}function V(c){let e={};Object.keys(c).forEach(n=>{let i=c[n];i.partition==="instance"&&(e[n]=i.default)});let t={};return Object.keys(c).forEach(n=>{let i=c[n];i.partition==="instance"&&(t[n]=i.default)}),{...e,...t}}import{useState as W,useEffect as U,useCallback as P,useMemo as G,useRef as J}from"react";function Q(c){return function(t){let[n,i,a,r]=G(()=>L(c),[t]),d=P(s=>{let[l,S]=W(i()[s]),y=J(l);U(()=>{y.current=l},[l]),U(()=>(S(i()[s]),r(g=>{s in g&&S(g[s])},[s])),[s]);let R=P(x=>{a({[s]:x})},[s]);return[l,R]},[i,a,r]),f=P(()=>i(),[i]),o=P(s=>{a(s)},[a]);return{useStateItem:d,getState:f,setState:o,useCrann:n}}}export{I as Crann,D as Partition,N as Persistence,L as connect,H as connected,$ as create,Q as createCrannStateHook};
3
3
  //# sourceMappingURL=index.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/crann.ts", "../../src/model/crann.model.ts", "../../src/utils/deepEqual.ts", "../../src/utils/debug.ts", "../../src/utils/tracking.ts", "../../src/crannAgent.ts", "../../src/hooks/useCrannState.ts"],
4
- "sourcesContent": ["import browser from \"webextension-polyfill\";\nimport {\n DerivedInstanceState,\n DerivedServiceState,\n ConfigItem,\n DerivedState,\n Partition,\n CrannOptions,\n} from \"./model/crann.model\";\nimport {\n AgentInfo,\n source,\n getAgentById,\n getAgentByLocation,\n MessageTarget,\n} from \"porter-source\";\nimport { deepEqual } from \"./utils/deepEqual\";\nimport { Message, BrowserLocation } from \"porter-source\";\nimport { trackStateChange } from \"./utils/tracking\";\nimport { DebugManager } from \"./utils/debug\";\n\nexport class Crann<TConfig extends Record<string, ConfigItem<any>>> {\n private static instance: Crann<any> | null = null;\n private instances: Map<string, DerivedInstanceState<TConfig>> = new Map();\n private defaultServiceState: DerivedServiceState<TConfig>;\n private defaultInstanceState: DerivedInstanceState<TConfig>;\n private serviceState: DerivedServiceState<TConfig>;\n private stateChangeListeners: Array<\n (\n state: DerivedInstanceState<TConfig> | DerivedState<TConfig>,\n changes: Partial<\n DerivedServiceState<TConfig> & DerivedInstanceState<TConfig>\n >,\n agent?: AgentInfo\n ) => void\n > = [];\n private storagePrefix = \"crann_\";\n private post: (message: Message<any>, target?: MessageTarget) => void =\n () => {};\n private debug: boolean = false;\n\n constructor(private config: TConfig, options?: CrannOptions) {\n // Set the debug flag globally\n if (options?.debug) {\n DebugManager.setDebug(true);\n }\n this.debug = options?.debug || false;\n this.storagePrefix = options?.storagePrefix ?? this.storagePrefix;\n this.log(\"Constructing\");\n this.defaultInstanceState = this.initializeInstanceDefault();\n this.defaultServiceState = this.serviceState =\n this.initializeServiceDefault();\n this.hydrate();\n const [post, setMessages, onConnect, onDisconnect, onMessagesSet] =\n source(\"crann\");\n this.post = post;\n setMessages({\n setState: (message, info) => {\n if (!info) {\n this.log(\"setState message heard from unknown agent\");\n return;\n }\n\n const agentTag = this.getAgentTag(info);\n this.instanceLog(\"Setting state: \", agentTag, message);\n this.set(message.payload.state, info.id);\n },\n });\n onMessagesSet((info: AgentInfo) => {\n this.instanceLog(\n \"Messages set received. Sending initial state.\",\n this.getAgentTag(info),\n { info }\n );\n const fullState = this.get(info.id);\n this.post(\n {\n action: \"initialState\",\n payload: { state: fullState, key: info.id },\n },\n info.location\n );\n });\n onConnect((info: AgentInfo) => {\n const agentTag = this.getAgentTag(info);\n this.instanceLog(\"Agent connected \", agentTag, { info });\n this.addInstance(info.id);\n onDisconnect((info: AgentInfo) => {\n this.instanceLog(\n \"Agent disconnect heard. Connection type, context and location: \",\n this.getAgentTag(info),\n { info }\n );\n this.removeInstance(info.id);\n });\n });\n }\n\n public static getInstance<TConfig extends Record<string, ConfigItem<any>>>(\n config: TConfig,\n options?: CrannOptions\n ): Crann<TConfig> {\n if (!Crann.instance) {\n Crann.instance = new Crann(config, options);\n } else if (options?.debug) {\n console.log(\n \"CrannSource [static-core], Instance requested and already existed, returning\"\n );\n }\n return Crann.instance;\n }\n\n private async addInstance(key: string): Promise<void> {\n if (!this.instances.has(key)) {\n this.instanceLog(\"Adding instance from agent key: \", key);\n const initialInstanceState = {\n ...this.defaultInstanceState,\n } as DerivedInstanceState<TConfig>;\n this.instances.set(key, initialInstanceState);\n } else {\n this.instanceLog(\n \"Instance was already registered, ignoring request from key: \",\n key\n );\n }\n }\n\n private async removeInstance(key: string): Promise<void> {\n if (this.instances.has(key)) {\n this.instanceLog(\"Remove instance requested. \", key);\n this.instances.delete(key);\n } else {\n this.instanceLog(\n \"Remove instance requested but it did not exist!. \",\n key\n );\n }\n }\n\n @trackStateChange\n public async setServiceState(\n state: Partial<DerivedServiceState<TConfig>>\n ): Promise<void> {\n this.log(\"Request to set service state with: \", state);\n const update = { ...this.serviceState, ...state };\n if (!deepEqual(this.serviceState, update)) {\n this.log(\n \"Confirmed new state was different than existing so proceeding to persist then notify all connected instances.\"\n );\n this.serviceState = update;\n await this.persist(state);\n this.notify(state as Partial<DerivedState<TConfig>>);\n } else {\n this.log(\"New state seems to be the same as existing, skipping\");\n }\n }\n\n @trackStateChange\n public async setInstanceState(\n key: string,\n state: Partial<DerivedInstanceState<TConfig>>\n ): Promise<void> {\n this.instanceLog(\"Request to update instance state, update: \", key, state);\n const currentState = this.instances.get(key) || this.defaultInstanceState;\n const update = { ...currentState, ...state };\n if (!deepEqual(currentState, update)) {\n this.instanceLog(\n \"Instance state update is different, updating and notifying. \",\n key\n );\n this.instances.set(key, update);\n this.notify(state as Partial<DerivedState<TConfig>>, key);\n } else {\n this.instanceLog(\n \"Instance state update is not different, skipping update. \",\n key\n );\n }\n }\n\n // If we pass in specific state to persist, it only persists that state.\n // Otherwise persists all of the worker state.\n private async persist(\n state?: Partial<DerivedServiceState<TConfig>>\n ): Promise<void> {\n this.log(\"Persisting state\");\n let wasPersisted = false;\n for (const key in state || this.serviceState) {\n const item = this.config[key] as ConfigItem<any>;\n const persistence = item.persist || \"none\";\n const value = state\n ? state[key as keyof DerivedServiceState<TConfig>]\n : this.serviceState[key];\n switch (persistence) {\n case \"session\":\n await browser.storage.session.set({\n [this.storagePrefix + (key as string)]: value,\n });\n wasPersisted = true;\n break;\n case \"local\":\n await browser.storage.local.set({\n [this.storagePrefix + (key as string)]: value,\n });\n wasPersisted = true;\n break;\n default:\n break;\n }\n }\n if (wasPersisted) {\n this.log(\"State was persisted\");\n } else {\n this.log(\"Nothing to persist\");\n }\n }\n\n public async clear(): Promise<void> {\n this.log(\"Clearing state\");\n this.serviceState = this.defaultServiceState;\n this.instances.forEach((_, key) => {\n this.instances.set(key, this.defaultInstanceState);\n });\n await this.persist();\n this.notify({});\n }\n\n public subscribe(\n listener: (\n state: DerivedInstanceState<TConfig> | DerivedState<TConfig>,\n changes: Partial<\n DerivedInstanceState<TConfig> & DerivedServiceState<TConfig>\n >,\n agent?: AgentInfo\n ) => void\n ): void {\n this.log(\"Subscribing to state\");\n this.stateChangeListeners.push(listener);\n }\n\n // Right now we notify the instance even if the state change came from the instance.\n // This should probably be skipped for instance state, since it already knows.\n private notify(changes: Partial<DerivedState<TConfig>>, key?: string): void {\n const agent = key ? getAgentById(key) : undefined;\n const state = key ? this.get(key) : this.get();\n\n if (this.stateChangeListeners.length > 0) {\n this.log(\"Notifying state change listeners in source\");\n this.stateChangeListeners.forEach((listener) => {\n listener(state, changes, agent?.info);\n });\n }\n\n if (key && agent?.info.location) {\n this.instanceLog(\"Notifying of state change.\", key);\n this.post(\n { action: \"stateUpdate\", payload: { state: changes } },\n agent.info.location\n );\n } else {\n console.log(\"Notifying everyone\");\n // for every key of this.instances, post the state update to the corresponding key\n this.instances.forEach((_, key) => {\n this.post({ action: \"stateUpdate\", payload: { state: changes } }, key);\n });\n }\n }\n\n public get(): DerivedState<TConfig>;\n public get(\n key: string\n ): DerivedInstanceState<TConfig> & DerivedServiceState<TConfig>;\n public get(\n key?: string\n ): DerivedServiceState<TConfig> | DerivedState<TConfig> {\n if (!key) {\n return { ...this.serviceState, ...({} as DerivedInstanceState<TConfig>) };\n }\n return { ...this.serviceState, ...this.instances.get(key) };\n }\n\n // Todo: Should we return the instance data? What is the point of this.\n public findInstance(location: BrowserLocation): string | null {\n const agent = getAgentByLocation(location);\n if (!agent) {\n this.log(\"Could not find agent for location: \", { location });\n return null;\n }\n for (const [key, instance] of this.instances) {\n if (key === agent.info.id) {\n this.log(\"Found instance for key: \", key);\n return key;\n }\n }\n this.log(\"Could not find instance for context and location: \", {\n location,\n });\n return null;\n }\n\n public async set(state: Partial<DerivedServiceState<TConfig>>): Promise<void>;\n public async set(\n state: Partial<\n DerivedInstanceState<TConfig> & DerivedServiceState<TConfig>\n >,\n key: string\n ): Promise<void>;\n public async set(\n state: Partial<\n DerivedInstanceState<TConfig> | DerivedServiceState<TConfig>\n >,\n key?: string\n ): Promise<void> {\n const instance = {} as Partial<DerivedInstanceState<TConfig>>;\n const worker = {} as Partial<DerivedServiceState<TConfig>>;\n\n for (const itemKey in state) {\n const item = this.config[itemKey as keyof TConfig] as ConfigItem<any>;\n if (item.partition === \"instance\") {\n const instanceItemKey = itemKey as keyof DerivedInstanceState<TConfig>;\n const instanceState = state as Partial<DerivedInstanceState<TConfig>>;\n instance[instanceItemKey] = instanceState[instanceItemKey];\n } else if (!item.partition || item.partition === Partition.Service) {\n const serviceItemKey = itemKey as keyof DerivedServiceState<TConfig>;\n const serviceState = state as Partial<DerivedServiceState<TConfig>>;\n worker[serviceItemKey] = serviceState[serviceItemKey]!;\n }\n }\n if (key && Object.keys(instance).length > 0) {\n this.instanceLog(\"Setting instance state: \", key, instance);\n this.setInstanceState(key, instance);\n }\n if (Object.keys(worker).length > 0) {\n this.log(\"Setting service state: \", worker);\n this.setServiceState(worker);\n }\n }\n\n private async hydrate(): Promise<void> {\n this.log(\"Hydrating state from storage.\");\n const local = await browser.storage.local.get(null);\n const session = await browser.storage.session.get(null);\n const combined = { ...local, ...session };\n const update: Partial<DerivedServiceState<TConfig>> = {}; // Cast update as Partial<DerivedState<TConfig>>\n let hadItems = false;\n for (const prefixedKey in combined) {\n const key = this.removePrefix(prefixedKey);\n if (this.config.hasOwnProperty(key)) {\n const value = combined[key];\n update[key as keyof DerivedServiceState<TConfig>] = value;\n hadItems = true;\n }\n }\n if (hadItems) {\n this.log(\"Hydrated some items.\");\n } else {\n this.log(\"No items found in storage.\");\n }\n this.serviceState = { ...this.defaultServiceState, ...update };\n }\n\n private removePrefix(key: string): string {\n if (key.startsWith(this.storagePrefix)) {\n return key.replace(this.storagePrefix, \"\");\n }\n return key;\n }\n\n private getAgentTag(agent: AgentInfo): string {\n return `${agent.location.context}:${agent.location.tabId}:${agent.location.frameId}`;\n }\n\n private initializeInstanceDefault(): DerivedInstanceState<TConfig> {\n const instanceState: any = {};\n Object.keys(this.config).forEach((key) => {\n const item: ConfigItem<any> = this.config[key];\n if (item.partition === \"instance\") {\n instanceState[key] = item.default;\n }\n });\n return instanceState;\n }\n\n private initializeServiceDefault(): DerivedServiceState<TConfig> {\n const serviceState: any = {};\n Object.keys(this.config).forEach((key) => {\n const item: ConfigItem<any> = this.config[key];\n if (item.partition === Partition.Service) {\n serviceState[key] = item.default;\n }\n });\n return serviceState;\n }\n\n private log(message: string, ...args: any[]) {\n if (this.debug) {\n console.log(`CrannSource [core], ` + message, ...args);\n }\n }\n private instanceLog(message: string, key: string, ...args: any[]) {\n if (this.debug) {\n console.log(`CrannSource [${key}], ` + message, ...args);\n }\n }\n private error(message: string, ...args: any[]) {\n console.error(`CrannSource [core], ` + message, ...args);\n }\n private warn(message: string, ...args: any[]) {\n console.warn(`CrannSource [core], ` + message, ...args);\n }\n}\n\nexport function create<TConfig extends Record<string, ConfigItem<any>>>(\n config: TConfig,\n options?: CrannOptions\n): [\n (key?: string) => DerivedState<TConfig>,\n (\n state: Partial<\n DerivedInstanceState<TConfig> & DerivedServiceState<TConfig>\n >,\n key?: string\n ) => Promise<void>,\n (\n listener: (\n state: DerivedInstanceState<TConfig> | DerivedState<TConfig>,\n changes: Partial<\n DerivedInstanceState<TConfig> & DerivedServiceState<TConfig>\n >,\n agent?: AgentInfo\n ) => void\n ) => void,\n (location: BrowserLocation) => string | null\n] {\n const instance = Crann.getInstance(config, options);\n return [\n instance.get.bind(instance),\n instance.set.bind(instance),\n instance.subscribe.bind(instance),\n instance.findInstance.bind(instance),\n ];\n}\n", "export const Partition = {\n Instance: \"instance\" as const,\n Service: \"service\" as const,\n};\n\nexport const Persistence = {\n Session: \"session\" as const,\n Local: \"local\" as const,\n None: \"none\" as const,\n};\n\ntype ConfigItem<T> = {\n default: T;\n partition?: (typeof Partition)[keyof typeof Partition];\n persist?: (typeof Persistence)[keyof typeof Persistence];\n};\n\ntype AnyConfig = Record<string, ConfigItem<any>>;\n\n// export type Config = typeof StateConfig;\n\ntype DerivedState<T extends AnyConfig> = {\n [P in keyof T]: T[P][\"default\"];\n};\n\ntype DerivedInstanceState<T extends AnyConfig> = {\n [P in keyof T as T[P][\"partition\"] extends \"instance\"\n ? P\n : never]: T[P][\"default\"];\n};\n\ntype DerivedServiceState<T extends AnyConfig> = {\n [P in keyof T as T[P][\"partition\"] extends \"service\"\n ? P\n : never]: T[P][\"default\"];\n};\n\ntype StateSubscriber<TConfig extends AnyConfig> = {\n keys?: Array<keyof DerivedState<TConfig>>;\n callback: (changes: StateUpdate<TConfig>) => void;\n};\n\ntype CrannAgent<TConfig extends AnyConfig> = {\n get: () => DerivedState<TConfig>;\n set: (update: StateUpdate<TConfig>) => void;\n subscribe: (\n callback: (changes: StateUpdate<TConfig>) => void,\n keys?: Array<keyof TConfig>\n ) => () => void;\n};\n\ntype UseCrann<TConfig extends AnyConfig> = <\n K extends keyof DerivedState<TConfig>\n>(\n key: K\n) => [\n DerivedState<TConfig>[K],\n (value: DerivedState<TConfig>[K]) => void,\n (callback: (value: DerivedState<TConfig>[K]) => void) => () => void\n];\n\ntype ConnectReturn<TConfig extends AnyConfig> = [\n UseCrann<TConfig>,\n CrannAgent<TConfig>[\"get\"],\n CrannAgent<TConfig>[\"set\"],\n CrannAgent<TConfig>[\"subscribe\"]\n];\n\ntype AgentSubscription<TConfig extends AnyConfig> = {\n (\n callback: (changes: StateUpdate<TConfig>) => void,\n key?: keyof DerivedState<TConfig>\n ): number;\n};\n\ntype StateUpdate<TConfig extends AnyConfig> = Partial<DerivedState<TConfig>>;\n\nexport type CrannOptions = {\n debug?: boolean;\n storagePrefix?: string;\n};\n\nexport {\n AnyConfig,\n ConfigItem,\n DerivedState,\n DerivedInstanceState,\n DerivedServiceState,\n StateSubscriber,\n CrannAgent,\n AgentSubscription,\n StateUpdate,\n DerivedState as State,\n ConnectReturn,\n UseCrann,\n};\n", "export function deepEqual(a: any, b: any): boolean {\n if (a === b) return true;\n\n if (a == null || typeof a !== 'object' || b == null || typeof b !== 'object') return false;\n\n const keysA = Object.keys(a);\n const keysB = Object.keys(b);\n\n if (keysA.length !== keysB.length) return false;\n\n keysA.sort();\n keysB.sort();\n\n for (let i = 0; i < keysA.length; i++) {\n const key = keysA[i];\n if (key !== keysB[i] || !deepEqual(a[key], b[key])) return false;\n }\n return true;\n}", "// Create a global debug state manager\nexport class DebugManager {\n private static _debug: boolean = false;\n\n static setDebug(value: boolean): void {\n DebugManager._debug = value;\n }\n\n static isDebugEnabled(): boolean {\n return DebugManager._debug;\n }\n}\n\n// Export a convenience function\nexport function isDebugEnabled(): boolean {\n return DebugManager.isDebugEnabled();\n}\n", "import { isDebugEnabled } from \"./debug\";\n\nexport type StateChangeMetadata = {\n source: string;\n timestamp: number;\n changes: any;\n instanceKey?: string;\n};\n\nexport function trackStateChange(\n target: any,\n propertyKey: string,\n descriptor: PropertyDescriptor\n): PropertyDescriptor {\n const originalMethod = descriptor.value;\n\n descriptor.value = function (...args: any[]) {\n // Only log if debugging is enabled\n if (isDebugEnabled()) {\n // Get the stack trace to find the actual caller\n const stack = new Error().stack;\n const lines = stack?.split(\"\\n\") || [];\n const callerMatch = lines[3]?.match(/at\\s+(\\S+)\\s+/);\n const caller = callerMatch ? callerMatch[1] : \"unknown\";\n\n const instanceKey = args.length > 1 ? args[1] : undefined;\n\n const metadata: StateChangeMetadata = {\n source: caller,\n timestamp: Date.now(),\n changes: args[0],\n instanceKey,\n };\n\n console.log(`Crann State Change:`, metadata);\n }\n return originalMethod.apply(this, args);\n };\n\n return descriptor;\n}\n", "import { match } from \"assert\";\nimport {\n ConfigItem,\n CrannAgent,\n DerivedState,\n StateSubscriber,\n DerivedInstanceState,\n DerivedServiceState,\n ConnectReturn,\n UseCrann,\n} from \"./model/crann.model\";\nimport { connect as connectPorter, PorterContext } from \"porter-source\";\n\nlet crannInstance: unknown = null;\n\nexport function connect<TConfig extends Record<string, ConfigItem<any>>>(\n config: TConfig,\n options?: { context?: string; debug?: boolean }\n): ConnectReturn<TConfig> {\n const debug = options?.debug || false;\n const context = options?.context;\n let _myKey = \"unset\";\n const log = (message: string, ...args: any[]) => {\n if (debug) {\n console.log(`CrannAgent [${_myKey}] ` + message, ...args);\n }\n };\n log(\"Initializing with context: \", context);\n if (crannInstance) {\n log(\"We had an instance already, returning\");\n return crannInstance as ConnectReturn<TConfig>;\n }\n log(\"No existing instance, creating a new one\");\n const [post, setMessages] = connectPorter({\n namespace: \"crann\",\n agentContext: context as PorterContext,\n });\n setMessages({\n initialState: (message) => {\n _state = message.payload.state;\n _myKey = message.payload.key;\n listeners.forEach((listener) => {\n listener.callback(_state);\n });\n log(`Initial state received and ${listeners.size} listeners notified`);\n },\n stateUpdate: (message) => {\n log(\"State updated: \", message);\n changes = message.payload.state;\n _state = { ..._state, ...changes };\n if (!!changes) {\n log(\"Notifying listeners of state update\");\n listeners.forEach((listener) => {\n if (listener.keys === undefined) {\n log(\"Found a universal listener, notifying\");\n listener.callback(changes!);\n } else {\n const matchFound = listener.keys.some((key) =>\n changes!.hasOwnProperty(key)\n );\n if (matchFound) {\n log(\"Found a specific listener for this item, notifying\");\n listener.callback(changes!);\n }\n }\n });\n }\n },\n });\n log(\"Porter connected. Setting up state and listeners\");\n let _state = getDerivedState(config);\n let changes: Partial<DerivedState<TConfig>> | null = null;\n const listeners = new Set<StateSubscriber<TConfig>>();\n\n log(\"Completed setup, returning instance\");\n\n const get = () => _state;\n const set = (newState: Partial<DerivedState<TConfig>>) => {\n console.log(\"CrannAgent, calling post with setState\");\n post({ action: \"setState\", payload: { state: newState } });\n };\n const subscribe = (\n callback: (changes: Partial<DerivedState<TConfig>>) => void,\n keys?: Array<keyof DerivedState<TConfig>>\n ): (() => void) => {\n const listener = { keys, callback };\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n };\n\n const useCrann: UseCrann<TConfig> = <K extends keyof DerivedState<TConfig>>(\n key: K\n ) => {\n const getValue = () => get()[key] as DerivedState<TConfig>;\n const setValue = (value: DerivedState<TConfig>[K]) =>\n set({ [key]: value } as Partial<DerivedState<TConfig>>);\n const subscribeToChanges = (\n callback: (value: DerivedState<TConfig>[K]) => void\n ) => {\n return subscribe(\n (changes) => {\n if (key in changes) {\n callback(changes[key] as DerivedState<TConfig>[K]);\n }\n },\n [key]\n );\n };\n\n return [getValue(), setValue, subscribeToChanges];\n };\n\n const instance: ConnectReturn<TConfig> = [useCrann, get, set, subscribe];\n crannInstance = instance;\n\n return crannInstance as ConnectReturn<TConfig>;\n}\n\nexport function connected(): boolean {\n return crannInstance !== null;\n}\n\nfunction getDerivedState<TConfig extends Record<string, ConfigItem<any>>>(\n config: TConfig\n): DerivedState<TConfig> {\n const instanceState = {} as DerivedInstanceState<TConfig>;\n\n Object.keys(config).forEach((key) => {\n const item: ConfigItem<any> = config[key];\n if (item.partition === \"instance\") {\n instanceState[key as keyof DerivedInstanceState<TConfig>] = item.default;\n }\n });\n\n const serviceState = {} as DerivedServiceState<TConfig>;\n Object.keys(config).forEach((key) => {\n const item: ConfigItem<any> = config[key];\n if (item.partition === \"instance\") {\n serviceState[key as keyof DerivedServiceState<TConfig>] = item.default;\n }\n });\n\n return {\n ...instanceState,\n ...serviceState,\n } as unknown as DerivedState<TConfig>;\n}\n", "import { useState, useEffect, useCallback, useMemo, useRef } from \"react\";\nimport { ConfigItem, DerivedState } from \"../model/crann.model\";\nimport { connect } from \"../crannAgent\";\n\nexport function createCrannStateHook<\n TConfig extends Record<string, ConfigItem<any>>\n>(config: TConfig) {\n return function useCrannState(context?: string) {\n const [useCrann, get, set, subscribe] = useMemo(() => {\n const instance = connect(config);\n return instance;\n }, [context]);\n\n const useStateItem = useCallback(\n <K extends keyof DerivedState<TConfig>>(key: K) => {\n const [value, setValue] = useState<DerivedState<TConfig>[K]>(\n get()[key]\n );\n const valueRef = useRef(value);\n\n useEffect(() => {\n valueRef.current = value;\n }, [value]);\n\n useEffect(() => {\n setValue(get()[key]);\n const unsubscribe = subscribe(\n (changes) => {\n if (key in changes) {\n setValue(changes[key] as DerivedState<TConfig>[K]);\n }\n },\n [key]\n );\n return unsubscribe;\n }, [key]);\n\n const updateValue = useCallback(\n (newValue: DerivedState<TConfig>[K]) => {\n set({ [key]: newValue } as Partial<DerivedState<TConfig>>);\n },\n [key]\n );\n\n return [value, updateValue] as const;\n },\n [get, set, subscribe]\n );\n\n const getState = useCallback(() => get(), [get]);\n\n const setState = useCallback(\n (newState: Partial<DerivedState<TConfig>>) => {\n set(newState);\n },\n [set]\n );\n\n return {\n useStateItem,\n getState,\n setState,\n useCrann,\n };\n };\n}\n"],
5
- "mappings": "wMAAA,OAAOA,MAAa,wBCAb,IAAMC,EAAY,CACvB,SAAU,WACV,QAAS,SACX,EAEaC,EAAc,CACzB,QAAS,UACT,MAAO,QACP,KAAM,MACR,EDAA,OAEE,UAAAC,EACA,gBAAAC,EACA,sBAAAC,MAEK,gBEfA,SAASC,EAAUC,EAAQC,EAAiB,CAC/C,GAAID,IAAMC,EAAG,MAAO,GAEpB,GAAID,GAAK,MAAQ,OAAOA,GAAM,UAAYC,GAAK,MAAQ,OAAOA,GAAM,SAAU,MAAO,GAErF,IAAMC,EAAQ,OAAO,KAAKF,CAAC,EACrBG,EAAQ,OAAO,KAAKF,CAAC,EAE3B,GAAIC,EAAM,SAAWC,EAAM,OAAQ,MAAO,GAE1CD,EAAM,KAAK,EACXC,EAAM,KAAK,EAEX,QAAS,EAAI,EAAG,EAAID,EAAM,OAAQ,IAAK,CACnC,IAAME,EAAMF,EAAM,CAAC,EACnB,GAAIE,IAAQD,EAAM,CAAC,GAAK,CAACJ,EAAUC,EAAEI,CAAG,EAAGH,EAAEG,CAAG,CAAC,EAAG,MAAO,EAC/D,CACA,MAAO,EACX,CCjBO,IAAMC,EAAN,MAAMA,CAAa,CAGxB,OAAO,SAASC,EAAsB,CACpCD,EAAa,OAASC,CACxB,CAEA,OAAO,gBAA0B,CAC/B,OAAOD,EAAa,MACtB,CACF,EAVaA,EACI,OAAkB,GAD5B,IAAME,EAANF,EAaA,SAASG,GAA0B,CACxC,OAAOD,EAAa,eAAe,CACrC,CCPO,SAASE,EACdC,EACAC,EACAC,EACoB,CACpB,IAAMC,EAAiBD,EAAW,MAElC,OAAAA,EAAW,MAAQ,YAAaE,EAAa,CAhB/C,IAAAC,EAkBI,GAAIC,EAAe,EAAG,CAEpB,IAAMC,EAAQ,IAAI,MAAM,EAAE,MAEpBC,GAAcH,IADNE,GAAA,YAAAA,EAAO,MAAM;AAAA,KAAS,CAAC,GACX,CAAC,IAAP,YAAAF,EAAU,MAAM,iBAC9BI,EAASD,EAAcA,EAAY,CAAC,EAAI,UAExCE,EAAcN,EAAK,OAAS,EAAIA,EAAK,CAAC,EAAI,OAE1CO,EAAgC,CACpC,OAAQF,EACR,UAAW,KAAK,IAAI,EACpB,QAASL,EAAK,CAAC,EACf,YAAAM,CACF,EAEA,QAAQ,IAAI,sBAAuBC,CAAQ,CAC7C,CACA,OAAOR,EAAe,MAAM,KAAMC,CAAI,CACxC,EAEOF,CACT,CJnBO,IAAMU,EAAN,MAAMA,CAAuD,CAoBlE,YAAoBC,EAAiBC,EAAwB,CAAzC,YAAAD,EAlBpB,KAAQ,UAAwD,IAAI,IAIpE,KAAQ,qBAQJ,CAAC,EACL,KAAQ,cAAgB,SACxB,KAAQ,KACN,IAAM,CAAC,EACT,KAAQ,MAAiB,GAvC3B,IAAAE,EA2CQD,GAAA,MAAAA,EAAS,OACXE,EAAa,SAAS,EAAI,EAE5B,KAAK,OAAQF,GAAA,YAAAA,EAAS,QAAS,GAC/B,KAAK,eAAgBC,EAAAD,GAAA,YAAAA,EAAS,gBAAT,KAAAC,EAA0B,KAAK,cACpD,KAAK,IAAI,cAAc,EACvB,KAAK,qBAAuB,KAAK,0BAA0B,EAC3D,KAAK,oBAAsB,KAAK,aAC9B,KAAK,yBAAyB,EAChC,KAAK,QAAQ,EACb,GAAM,CAACE,EAAMC,EAAaC,EAAWC,EAAcC,CAAa,EAC9DC,EAAO,OAAO,EAChB,KAAK,KAAOL,EACZC,EAAY,CACV,SAAU,CAACK,EAASC,IAAS,CAC3B,GAAI,CAACA,EAAM,CACT,KAAK,IAAI,2CAA2C,EACpD,MACF,CAEA,IAAMC,EAAW,KAAK,YAAYD,CAAI,EACtC,KAAK,YAAY,kBAAmBC,EAAUF,CAAO,EACrD,KAAK,IAAIA,EAAQ,QAAQ,MAAOC,EAAK,EAAE,CACzC,CACF,CAAC,EACDH,EAAeG,GAAoB,CACjC,KAAK,YACH,gDACA,KAAK,YAAYA,CAAI,EACrB,CAAE,KAAAA,CAAK,CACT,EACA,IAAME,EAAY,KAAK,IAAIF,EAAK,EAAE,EAClC,KAAK,KACH,CACE,OAAQ,eACR,QAAS,CAAE,MAAOE,EAAW,IAAKF,EAAK,EAAG,CAC5C,EACAA,EAAK,QACP,CACF,CAAC,EACDL,EAAWK,GAAoB,CAC7B,IAAMC,EAAW,KAAK,YAAYD,CAAI,EACtC,KAAK,YAAY,mBAAoBC,EAAU,CAAE,KAAAD,CAAK,CAAC,EACvD,KAAK,YAAYA,EAAK,EAAE,EACxBJ,EAAcI,GAAoB,CAChC,KAAK,YACH,kEACA,KAAK,YAAYA,CAAI,EACrB,CAAE,KAAAA,CAAK,CACT,EACA,KAAK,eAAeA,EAAK,EAAE,CAC7B,CAAC,CACH,CAAC,CACH,CAEA,OAAc,YACZX,EACAC,EACgB,CAChB,OAAKF,EAAM,SAEAE,GAAA,MAAAA,EAAS,OAClB,QAAQ,IACN,8EACF,EAJAF,EAAM,SAAW,IAAIA,EAAMC,EAAQC,CAAO,EAMrCF,EAAM,QACf,CAEA,MAAc,YAAYe,EAA4B,CACpD,GAAK,KAAK,UAAU,IAAIA,CAAG,EAOzB,KAAK,YACH,+DACAA,CACF,MAV4B,CAC5B,KAAK,YAAY,mCAAoCA,CAAG,EACxD,IAAMC,EAAuB,CAC3B,GAAG,KAAK,oBACV,EACA,KAAK,UAAU,IAAID,EAAKC,CAAoB,CAC9C,CAMF,CAEA,MAAc,eAAeD,EAA4B,CACnD,KAAK,UAAU,IAAIA,CAAG,GACxB,KAAK,YAAY,8BAA+BA,CAAG,EACnD,KAAK,UAAU,OAAOA,CAAG,GAEzB,KAAK,YACH,oDACAA,CACF,CAEJ,CAGA,MAAa,gBACXE,EACe,CACf,KAAK,IAAI,sCAAuCA,CAAK,EACrD,IAAMC,EAAS,CAAE,GAAG,KAAK,aAAc,GAAGD,CAAM,EAC3CE,EAAU,KAAK,aAAcD,CAAM,EAQtC,KAAK,IAAI,sDAAsD,GAP/D,KAAK,IACH,+GACF,EACA,KAAK,aAAeA,EACpB,MAAM,KAAK,QAAQD,CAAK,EACxB,KAAK,OAAOA,CAAuC,EAIvD,CAGA,MAAa,iBACXF,EACAE,EACe,CACf,KAAK,YAAY,6CAA8CF,EAAKE,CAAK,EACzE,IAAMG,EAAe,KAAK,UAAU,IAAIL,CAAG,GAAK,KAAK,qBAC/CG,EAAS,CAAE,GAAGE,EAAc,GAAGH,CAAM,EACtCE,EAAUC,EAAcF,CAAM,EAQjC,KAAK,YACH,4DACAH,CACF,GAVA,KAAK,YACH,+DACAA,CACF,EACA,KAAK,UAAU,IAAIA,EAAKG,CAAM,EAC9B,KAAK,OAAOD,EAAyCF,CAAG,EAO5D,CAIA,MAAc,QACZE,EACe,CACf,KAAK,IAAI,kBAAkB,EAC3B,IAAII,EAAe,GACnB,QAAWN,KAAOE,GAAS,KAAK,aAAc,CAE5C,IAAMK,EADO,KAAK,OAAOP,CAAG,EACH,SAAW,OAC9BQ,EAAQN,EACVA,EAAMF,CAAyC,EAC/C,KAAK,aAAaA,CAAG,EACzB,OAAQO,EAAa,CACnB,IAAK,UACH,MAAME,EAAQ,QAAQ,QAAQ,IAAI,CAChC,CAAC,KAAK,cAAiBT,CAAc,EAAGQ,CAC1C,CAAC,EACDF,EAAe,GACf,MACF,IAAK,QACH,MAAMG,EAAQ,QAAQ,MAAM,IAAI,CAC9B,CAAC,KAAK,cAAiBT,CAAc,EAAGQ,CAC1C,CAAC,EACDF,EAAe,GACf,MACF,QACE,KACJ,CACF,CACIA,EACF,KAAK,IAAI,qBAAqB,EAE9B,KAAK,IAAI,oBAAoB,CAEjC,CAEA,MAAa,OAAuB,CAClC,KAAK,IAAI,gBAAgB,EACzB,KAAK,aAAe,KAAK,oBACzB,KAAK,UAAU,QAAQ,CAACI,EAAGV,IAAQ,CACjC,KAAK,UAAU,IAAIA,EAAK,KAAK,oBAAoB,CACnD,CAAC,EACD,MAAM,KAAK,QAAQ,EACnB,KAAK,OAAO,CAAC,CAAC,CAChB,CAEO,UACLW,EAOM,CACN,KAAK,IAAI,sBAAsB,EAC/B,KAAK,qBAAqB,KAAKA,CAAQ,CACzC,CAIQ,OAAOC,EAAyCZ,EAAoB,CAC1E,IAAMa,EAAQb,EAAMc,EAAad,CAAG,EAAI,OAClCE,EAAQF,EAAM,KAAK,IAAIA,CAAG,EAAI,KAAK,IAAI,EAEzC,KAAK,qBAAqB,OAAS,IACrC,KAAK,IAAI,4CAA4C,EACrD,KAAK,qBAAqB,QAASW,GAAa,CAC9CA,EAAST,EAAOU,EAASC,GAAA,YAAAA,EAAO,IAAI,CACtC,CAAC,GAGCb,IAAOa,GAAA,MAAAA,EAAO,KAAK,WACrB,KAAK,YAAY,6BAA8Bb,CAAG,EAClD,KAAK,KACH,CAAE,OAAQ,cAAe,QAAS,CAAE,MAAOY,CAAQ,CAAE,EACrDC,EAAM,KAAK,QACb,IAEA,QAAQ,IAAI,oBAAoB,EAEhC,KAAK,UAAU,QAAQ,CAACH,EAAGV,IAAQ,CACjC,KAAK,KAAK,CAAE,OAAQ,cAAe,QAAS,CAAE,MAAOY,CAAQ,CAAE,EAAGZ,CAAG,CACvE,CAAC,EAEL,CAMO,IACLA,EACsD,CACtD,OAAKA,EAGE,CAAE,GAAG,KAAK,aAAc,GAAG,KAAK,UAAU,IAAIA,CAAG,CAAE,EAFjD,CAAE,GAAG,KAAK,YAAuD,CAG5E,CAGO,aAAae,EAA0C,CAC5D,IAAMF,EAAQG,EAAmBD,CAAQ,EACzC,GAAI,CAACF,EACH,YAAK,IAAI,sCAAuC,CAAE,SAAAE,CAAS,CAAC,EACrD,KAET,OAAW,CAACf,EAAKiB,CAAQ,IAAK,KAAK,UACjC,GAAIjB,IAAQa,EAAM,KAAK,GACrB,YAAK,IAAI,2BAA4Bb,CAAG,EACjCA,EAGX,YAAK,IAAI,qDAAsD,CAC7D,SAAAe,CACF,CAAC,EACM,IACT,CASA,MAAa,IACXb,EAGAF,EACe,CACf,IAAMiB,EAAW,CAAC,EACZC,EAAS,CAAC,EAEhB,QAAWC,KAAWjB,EAAO,CAC3B,IAAMkB,EAAO,KAAK,OAAOD,CAAwB,EACjD,GAAIC,EAAK,YAAc,WAAY,CACjC,IAAMC,EAAkBF,EAClBG,EAAgBpB,EACtBe,EAASI,CAAe,EAAIC,EAAcD,CAAe,CAC3D,SAAW,CAACD,EAAK,WAAaA,EAAK,YAAcG,EAAU,QAAS,CAClE,IAAMC,EAAiBL,EACjBM,EAAevB,EACrBgB,EAAOM,CAAc,EAAIC,EAAaD,CAAc,CACtD,CACF,CACIxB,GAAO,OAAO,KAAKiB,CAAQ,EAAE,OAAS,IACxC,KAAK,YAAY,2BAA4BjB,EAAKiB,CAAQ,EAC1D,KAAK,iBAAiBjB,EAAKiB,CAAQ,GAEjC,OAAO,KAAKC,CAAM,EAAE,OAAS,IAC/B,KAAK,IAAI,0BAA2BA,CAAM,EAC1C,KAAK,gBAAgBA,CAAM,EAE/B,CAEA,MAAc,SAAyB,CACrC,KAAK,IAAI,+BAA+B,EACxC,IAAMQ,EAAQ,MAAMjB,EAAQ,QAAQ,MAAM,IAAI,IAAI,EAC5CkB,EAAU,MAAMlB,EAAQ,QAAQ,QAAQ,IAAI,IAAI,EAChDmB,EAAW,CAAE,GAAGF,EAAO,GAAGC,CAAQ,EAClCxB,EAAgD,CAAC,EACnD0B,EAAW,GACf,QAAWC,KAAeF,EAAU,CAClC,IAAM5B,EAAM,KAAK,aAAa8B,CAAW,EACzC,GAAI,KAAK,OAAO,eAAe9B,CAAG,EAAG,CACnC,IAAMQ,EAAQoB,EAAS5B,CAAG,EAC1BG,EAAOH,CAAyC,EAAIQ,EACpDqB,EAAW,EACb,CACF,CACIA,EACF,KAAK,IAAI,sBAAsB,EAE/B,KAAK,IAAI,4BAA4B,EAEvC,KAAK,aAAe,CAAE,GAAG,KAAK,oBAAqB,GAAG1B,CAAO,CAC/D,CAEQ,aAAaH,EAAqB,CACxC,OAAIA,EAAI,WAAW,KAAK,aAAa,EAC5BA,EAAI,QAAQ,KAAK,cAAe,EAAE,EAEpCA,CACT,CAEQ,YAAYa,EAA0B,CAC5C,MAAO,GAAGA,EAAM,SAAS,OAAO,IAAIA,EAAM,SAAS,KAAK,IAAIA,EAAM,SAAS,OAAO,EACpF,CAEQ,2BAA2D,CACjE,IAAMS,EAAqB,CAAC,EAC5B,cAAO,KAAK,KAAK,MAAM,EAAE,QAAStB,GAAQ,CACxC,IAAMoB,EAAwB,KAAK,OAAOpB,CAAG,EACzCoB,EAAK,YAAc,aACrBE,EAActB,CAAG,EAAIoB,EAAK,QAE9B,CAAC,EACME,CACT,CAEQ,0BAAyD,CAC/D,IAAMG,EAAoB,CAAC,EAC3B,cAAO,KAAK,KAAK,MAAM,EAAE,QAASzB,GAAQ,CACxC,IAAMoB,EAAwB,KAAK,OAAOpB,CAAG,EACzCoB,EAAK,YAAcG,EAAU,UAC/BE,EAAazB,CAAG,EAAIoB,EAAK,QAE7B,CAAC,EACMK,CACT,CAEQ,IAAI7B,KAAoBmC,EAAa,CACvC,KAAK,OACP,QAAQ,IAAI,uBAAyBnC,EAAS,GAAGmC,CAAI,CAEzD,CACQ,YAAYnC,EAAiBI,KAAgB+B,EAAa,CAC5D,KAAK,OACP,QAAQ,IAAI,gBAAgB/B,CAAG,MAAQJ,EAAS,GAAGmC,CAAI,CAE3D,CACQ,MAAMnC,KAAoBmC,EAAa,CAC7C,QAAQ,MAAM,uBAAyBnC,EAAS,GAAGmC,CAAI,CACzD,CACQ,KAAKnC,KAAoBmC,EAAa,CAC5C,QAAQ,KAAK,uBAAyBnC,EAAS,GAAGmC,CAAI,CACxD,CACF,EArYa9C,EACI,SAA8B,KAsHhC+C,EAAA,CADZC,GAtHUhD,EAuHE,+BAkBA+C,EAAA,CADZC,GAxIUhD,EAyIE,gCAzIR,IAAMiD,EAANjD,EAuYA,SAASkD,EACdjD,EACAC,EAmBA,CACA,IAAM8B,EAAWiB,EAAM,YAAYhD,EAAQC,CAAO,EAClD,MAAO,CACL8B,EAAS,IAAI,KAAKA,CAAQ,EAC1BA,EAAS,IAAI,KAAKA,CAAQ,EAC1BA,EAAS,UAAU,KAAKA,CAAQ,EAChCA,EAAS,aAAa,KAAKA,CAAQ,CACrC,CACF,CK9aA,OAAS,WAAWmB,MAAoC,gBAExD,IAAIC,EAAyB,KAEtB,SAASC,EACdC,EACAC,EACwB,CACxB,IAAMC,GAAQD,GAAA,YAAAA,EAAS,QAAS,GAC1BE,EAAUF,GAAA,YAAAA,EAAS,QACrBG,EAAS,QACPC,EAAM,CAACC,KAAoBC,IAAgB,CAC3CL,GACF,QAAQ,IAAI,eAAeE,CAAM,KAAOE,EAAS,GAAGC,CAAI,CAE5D,EAEA,GADAF,EAAI,8BAA+BF,CAAO,EACtCL,EACF,OAAAO,EAAI,uCAAuC,EACpCP,EAETO,EAAI,0CAA0C,EAC9C,GAAM,CAACG,EAAMC,CAAW,EAAIZ,EAAc,CACxC,UAAW,QACX,aAAcM,CAChB,CAAC,EACDM,EAAY,CACV,aAAeH,GAAY,CACzBI,EAASJ,EAAQ,QAAQ,MACzBF,EAASE,EAAQ,QAAQ,IACzBK,EAAU,QAASC,GAAa,CAC9BA,EAAS,SAASF,CAAM,CAC1B,CAAC,EACDL,EAAI,+BAA+BM,EAAU,IAAI,qBAAqB,CACxE,EACA,YAAcL,GAAY,CACxBD,EAAI,kBAAmBC,CAAO,EAC9BO,EAAUP,EAAQ,QAAQ,MAC1BI,EAAS,CAAE,GAAGA,EAAQ,GAAGG,CAAQ,EAC3BA,IACJR,EAAI,qCAAqC,EACzCM,EAAU,QAASC,GAAa,CAC1BA,EAAS,OAAS,QACpBP,EAAI,uCAAuC,EAC3CO,EAAS,SAASC,CAAQ,GAEPD,EAAS,KAAK,KAAME,GACrCD,EAAS,eAAeC,CAAG,CAC7B,IAEET,EAAI,oDAAoD,EACxDO,EAAS,SAASC,CAAQ,EAGhC,CAAC,EAEL,CACF,CAAC,EACDR,EAAI,kDAAkD,EACtD,IAAIK,EAASK,EAAgBf,CAAM,EAC/Ba,EAAiD,KAC/CF,EAAY,IAAI,IAEtBN,EAAI,qCAAqC,EAEzC,IAAMW,EAAM,IAAMN,EACZO,EAAOC,GAA6C,CACxD,QAAQ,IAAI,wCAAwC,EACpDV,EAAK,CAAE,OAAQ,WAAY,QAAS,CAAE,MAAOU,CAAS,CAAE,CAAC,CAC3D,EACMC,EAAY,CAChBC,EACAC,IACiB,CACjB,IAAMT,EAAW,CAAE,KAAAS,EAAM,SAAAD,CAAS,EAClC,OAAAT,EAAU,IAAIC,CAAQ,EACf,IAAM,CACXD,EAAU,OAAOC,CAAQ,CAC3B,CACF,EAyBA,OAAAd,EADyC,CArBvCgB,GACG,CACH,IAAMQ,EAAW,IAAMN,EAAI,EAAEF,CAAG,EAC1BS,EAAYC,GAChBP,EAAI,CAAE,CAACH,CAAG,EAAGU,CAAM,CAAmC,EAClDC,EACJL,GAEOD,EACJN,GAAY,CACPC,KAAOD,GACTO,EAASP,EAAQC,CAAG,CAA6B,CAErD,EACA,CAACA,CAAG,CACN,EAGF,MAAO,CAACQ,EAAS,EAAGC,EAAUE,CAAkB,CAClD,EAEoDT,EAAKC,EAAKE,CAAS,EAGhErB,CACT,CAEO,SAAS4B,GAAqB,CACnC,OAAO5B,IAAkB,IAC3B,CAEA,SAASiB,EACPf,EACuB,CACvB,IAAM2B,EAAgB,CAAC,EAEvB,OAAO,KAAK3B,CAAM,EAAE,QAASc,GAAQ,CACnC,IAAMc,EAAwB5B,EAAOc,CAAG,EACpCc,EAAK,YAAc,aACrBD,EAAcb,CAA0C,EAAIc,EAAK,QAErE,CAAC,EAED,IAAMC,EAAe,CAAC,EACtB,cAAO,KAAK7B,CAAM,EAAE,QAASc,GAAQ,CACnC,IAAMc,EAAwB5B,EAAOc,CAAG,EACpCc,EAAK,YAAc,aACrBC,EAAaf,CAAyC,EAAIc,EAAK,QAEnE,CAAC,EAEM,CACL,GAAGD,EACH,GAAGE,CACL,CACF,CCpJA,OAAS,YAAAC,EAAU,aAAAC,EAAW,eAAAC,EAAa,WAAAC,EAAS,UAAAC,MAAc,QAI3D,SAASC,EAEdC,EAAiB,CACjB,OAAO,SAAuBC,EAAkB,CAC9C,GAAM,CAACC,EAAUC,EAAKC,EAAKC,CAAS,EAAIC,EAAQ,IAC7BC,EAAQP,CAAM,EAE9B,CAACC,CAAO,CAAC,EAENO,EAAeC,EACqBC,GAAW,CACjD,GAAM,CAACC,EAAOC,CAAQ,EAAIC,EACxBV,EAAI,EAAEO,CAAG,CACX,EACMI,EAAWC,EAAOJ,CAAK,EAE7BK,EAAU,IAAM,CACdF,EAAS,QAAUH,CACrB,EAAG,CAACA,CAAK,CAAC,EAEVK,EAAU,KACRJ,EAAST,EAAI,EAAEO,CAAG,CAAC,EACCL,EACjBY,GAAY,CACPP,KAAOO,GACTL,EAASK,EAAQP,CAAG,CAA6B,CAErD,EACA,CAACA,CAAG,CACN,GAEC,CAACA,CAAG,CAAC,EAER,IAAMQ,EAAcT,EACjBU,GAAuC,CACtCf,EAAI,CAAE,CAACM,CAAG,EAAGS,CAAS,CAAmC,CAC3D,EACA,CAACT,CAAG,CACN,EAEA,MAAO,CAACC,EAAOO,CAAW,CAC5B,EACA,CAACf,EAAKC,EAAKC,CAAS,CACtB,EAEMe,EAAWX,EAAY,IAAMN,EAAI,EAAG,CAACA,CAAG,CAAC,EAEzCkB,EAAWZ,EACda,GAA6C,CAC5ClB,EAAIkB,CAAQ,CACd,EACA,CAAClB,CAAG,CACN,EAEA,MAAO,CACL,aAAAI,EACA,SAAAY,EACA,SAAAC,EACA,SAAAnB,CACF,CACF,CACF",
4
+ "sourcesContent": ["import browser from \"webextension-polyfill\";\nimport {\n DerivedInstanceState,\n DerivedServiceState,\n ConfigItem,\n DerivedState,\n Partition,\n CrannOptions,\n} from \"./model/crann.model\";\nimport {\n AgentInfo,\n source,\n getAgentById,\n getAgentByLocation,\n MessageTarget,\n} from \"porter-source\";\nimport { deepEqual } from \"./utils/deepEqual\";\nimport { Message, BrowserLocation } from \"porter-source\";\nimport { trackStateChange } from \"./utils/tracking\";\nimport { DebugManager } from \"./utils/debug\";\n\nexport class Crann<TConfig extends Record<string, ConfigItem<any>>> {\n private static instance: Crann<any> | null = null;\n private instances: Map<string, DerivedInstanceState<TConfig>> = new Map();\n private defaultServiceState: DerivedServiceState<TConfig>;\n private defaultInstanceState: DerivedInstanceState<TConfig>;\n private serviceState: DerivedServiceState<TConfig>;\n private stateChangeListeners: Array<\n (\n state: DerivedInstanceState<TConfig> | DerivedState<TConfig>,\n changes: Partial<\n DerivedServiceState<TConfig> & DerivedInstanceState<TConfig>\n >,\n agent?: AgentInfo\n ) => void\n > = [];\n private storagePrefix = \"crann_\";\n private post: (message: Message<any>, target?: MessageTarget) => void =\n () => {};\n private debug: boolean = false;\n\n constructor(private config: TConfig, options?: CrannOptions) {\n // Set the debug flag globally\n if (options?.debug) {\n DebugManager.setDebug(true);\n }\n this.debug = options?.debug || false;\n this.storagePrefix = options?.storagePrefix ?? this.storagePrefix;\n this.log(\"Constructing\");\n this.defaultInstanceState = this.initializeInstanceDefault();\n this.defaultServiceState = this.serviceState =\n this.initializeServiceDefault();\n this.hydrate();\n const [post, setMessages, onConnect, onDisconnect, onMessagesSet] =\n source(\"crann\");\n this.post = post;\n setMessages({\n setState: (message, info) => {\n if (!info) {\n this.log(\"setState message heard from unknown agent\");\n return;\n }\n\n const agentTag = this.getAgentTag(info);\n this.instanceLog(\"Setting state: \", agentTag, message);\n this.set(message.payload.state, info.id);\n },\n });\n onMessagesSet((info: AgentInfo) => {\n this.instanceLog(\n \"Messages set received. Sending initial state.\",\n this.getAgentTag(info),\n { info }\n );\n const fullState = this.get(info.id);\n this.post(\n {\n action: \"initialState\",\n payload: { state: fullState, key: info.id },\n },\n info.location\n );\n });\n onConnect((info: AgentInfo) => {\n const agentTag = this.getAgentTag(info);\n this.instanceLog(\"Agent connected \", agentTag, { info });\n this.addInstance(info.id);\n onDisconnect((info: AgentInfo) => {\n this.instanceLog(\n \"Agent disconnect heard. Connection type, context and location: \",\n this.getAgentTag(info),\n { info }\n );\n this.removeInstance(info.id);\n });\n });\n }\n\n public static getInstance<TConfig extends Record<string, ConfigItem<any>>>(\n config: TConfig,\n options?: CrannOptions\n ): Crann<TConfig> {\n if (!Crann.instance) {\n Crann.instance = new Crann(config, options);\n } else if (options?.debug) {\n console.log(\n \"CrannSource [static-core], Instance requested and already existed, returning\"\n );\n }\n return Crann.instance;\n }\n\n private async addInstance(key: string): Promise<void> {\n if (!this.instances.has(key)) {\n this.instanceLog(\"Adding instance from agent key: \", key);\n const initialInstanceState = {\n ...this.defaultInstanceState,\n } as DerivedInstanceState<TConfig>;\n this.instances.set(key, initialInstanceState);\n } else {\n this.instanceLog(\n \"Instance was already registered, ignoring request from key: \",\n key\n );\n }\n }\n\n private async removeInstance(key: string): Promise<void> {\n if (this.instances.has(key)) {\n this.instanceLog(\"Remove instance requested. \", key);\n this.instances.delete(key);\n } else {\n this.instanceLog(\n \"Remove instance requested but it did not exist!. \",\n key\n );\n }\n }\n\n @trackStateChange\n public async setServiceState(\n state: Partial<DerivedServiceState<TConfig>>\n ): Promise<void> {\n this.log(\"Request to set service state with: \", state);\n const update = { ...this.serviceState, ...state };\n if (!deepEqual(this.serviceState, update)) {\n this.log(\n \"Confirmed new state was different than existing so proceeding to persist then notify all connected instances.\"\n );\n this.serviceState = update;\n await this.persist(state);\n this.notify(state as Partial<DerivedState<TConfig>>);\n } else {\n this.log(\"New state seems to be the same as existing, skipping\");\n }\n }\n\n @trackStateChange\n public async setInstanceState(\n key: string,\n state: Partial<DerivedInstanceState<TConfig>>\n ): Promise<void> {\n this.instanceLog(\"Request to update instance state, update: \", key, state);\n const currentState = this.instances.get(key) || this.defaultInstanceState;\n const update = { ...currentState, ...state };\n if (!deepEqual(currentState, update)) {\n this.instanceLog(\n \"Instance state update is different, updating and notifying. \",\n key\n );\n this.instances.set(key, update);\n this.notify(state as Partial<DerivedState<TConfig>>, key);\n } else {\n this.instanceLog(\n \"Instance state update is not different, skipping update. \",\n key\n );\n }\n }\n\n // If we pass in specific state to persist, it only persists that state.\n // Otherwise persists all of the worker state.\n private async persist(\n state?: Partial<DerivedServiceState<TConfig>>\n ): Promise<void> {\n this.log(\"Persisting state\");\n let wasPersisted = false;\n for (const key in state || this.serviceState) {\n const item = this.config[key] as ConfigItem<any>;\n const persistence = item.persist || \"none\";\n const value = state\n ? state[key as keyof DerivedServiceState<TConfig>]\n : this.serviceState[key];\n switch (persistence) {\n case \"session\":\n await browser.storage.session.set({\n [this.storagePrefix + (key as string)]: value,\n });\n wasPersisted = true;\n break;\n case \"local\":\n await browser.storage.local.set({\n [this.storagePrefix + (key as string)]: value,\n });\n wasPersisted = true;\n break;\n default:\n break;\n }\n }\n if (wasPersisted) {\n this.log(\"State was persisted\");\n } else {\n this.log(\"Nothing to persist\");\n }\n }\n\n public async clear(): Promise<void> {\n this.log(\"Clearing state\");\n this.serviceState = this.defaultServiceState;\n this.instances.forEach((_, key) => {\n this.instances.set(key, this.defaultInstanceState);\n });\n await this.persist();\n this.notify({});\n }\n\n public subscribe(\n listener: (\n state: DerivedInstanceState<TConfig> | DerivedState<TConfig>,\n changes: Partial<\n DerivedInstanceState<TConfig> & DerivedServiceState<TConfig>\n >,\n agent?: AgentInfo\n ) => void\n ): void {\n this.log(\"Subscribing to state\");\n this.stateChangeListeners.push(listener);\n }\n\n // Right now we notify the instance even if the state change came from the instance.\n // This should probably be skipped for instance state, since it already knows.\n private notify(changes: Partial<DerivedState<TConfig>>, key?: string): void {\n const agent = key ? getAgentById(key) : undefined;\n const state = key ? this.get(key) : this.get();\n\n if (this.stateChangeListeners.length > 0) {\n this.log(\"Notifying state change listeners in source\");\n this.stateChangeListeners.forEach((listener) => {\n listener(state, changes, agent?.info);\n });\n }\n\n if (key && agent?.info.location) {\n this.instanceLog(\"Notifying of state change.\", key);\n this.post(\n { action: \"stateUpdate\", payload: { state: changes } },\n agent.info.location\n );\n } else {\n console.log(\"Notifying everyone\");\n // for every key of this.instances, post the state update to the corresponding key\n this.instances.forEach((_, key) => {\n this.post({ action: \"stateUpdate\", payload: { state: changes } }, key);\n });\n }\n }\n\n public get(): DerivedState<TConfig>;\n public get(\n key: string\n ): DerivedInstanceState<TConfig> & DerivedServiceState<TConfig>;\n public get(\n key?: string\n ): DerivedServiceState<TConfig> | DerivedState<TConfig> {\n if (!key) {\n return { ...this.serviceState, ...({} as DerivedInstanceState<TConfig>) };\n }\n return { ...this.serviceState, ...this.instances.get(key) };\n }\n\n // Todo: Should we return the instance data? What is the point of this.\n public findInstance(location: BrowserLocation): string | null {\n const agent = getAgentByLocation(location);\n if (!agent) {\n this.log(\"Could not find agent for location: \", { location });\n return null;\n }\n for (const [key, instance] of this.instances) {\n if (key === agent.info.id) {\n this.log(\"Found instance for key: \", key);\n return key;\n }\n }\n this.log(\"Could not find instance for context and location: \", {\n location,\n });\n return null;\n }\n\n public async set(state: Partial<DerivedServiceState<TConfig>>): Promise<void>;\n public async set(\n state: Partial<\n DerivedInstanceState<TConfig> & DerivedServiceState<TConfig>\n >,\n key: string\n ): Promise<void>;\n public async set(\n state: Partial<\n DerivedInstanceState<TConfig> | DerivedServiceState<TConfig>\n >,\n key?: string\n ): Promise<void> {\n const instance = {} as Partial<DerivedInstanceState<TConfig>>;\n const worker = {} as Partial<DerivedServiceState<TConfig>>;\n\n for (const itemKey in state) {\n const item = this.config[itemKey as keyof TConfig] as ConfigItem<any>;\n if (item.partition === \"instance\") {\n const instanceItemKey = itemKey as keyof DerivedInstanceState<TConfig>;\n const instanceState = state as Partial<DerivedInstanceState<TConfig>>;\n instance[instanceItemKey] = instanceState[instanceItemKey];\n } else if (!item.partition || item.partition === Partition.Service) {\n const serviceItemKey = itemKey as keyof DerivedServiceState<TConfig>;\n const serviceState = state as Partial<DerivedServiceState<TConfig>>;\n worker[serviceItemKey] = serviceState[serviceItemKey]!;\n }\n }\n if (key && Object.keys(instance).length > 0) {\n this.instanceLog(\"Setting instance state: \", key, instance);\n this.setInstanceState(key, instance);\n }\n if (Object.keys(worker).length > 0) {\n this.log(\"Setting service state: \", worker);\n this.setServiceState(worker);\n }\n }\n\n private async hydrate(): Promise<void> {\n this.log(\"Hydrating state from storage.\");\n const local = await browser.storage.local.get(null);\n const session = await browser.storage.session.get(null);\n const combined = { ...local, ...session };\n const update: Partial<DerivedServiceState<TConfig>> = {}; // Cast update as Partial<DerivedState<TConfig>>\n let hadItems = false;\n for (const prefixedKey in combined) {\n const key = this.removePrefix(prefixedKey);\n if (this.config.hasOwnProperty(key)) {\n const value = combined[key];\n update[key as keyof DerivedServiceState<TConfig>] = value;\n hadItems = true;\n }\n }\n if (hadItems) {\n this.log(\"Hydrated some items.\");\n } else {\n this.log(\"No items found in storage.\");\n }\n this.serviceState = { ...this.defaultServiceState, ...update };\n }\n\n private removePrefix(key: string): string {\n if (key.startsWith(this.storagePrefix)) {\n return key.replace(this.storagePrefix, \"\");\n }\n return key;\n }\n\n private getAgentTag(agent: AgentInfo): string {\n return `${agent.location.context}:${agent.location.tabId}:${agent.location.frameId}`;\n }\n\n private initializeInstanceDefault(): DerivedInstanceState<TConfig> {\n const instanceState: any = {};\n Object.keys(this.config).forEach((key) => {\n const item: ConfigItem<any> = this.config[key];\n if (item.partition === \"instance\") {\n instanceState[key] = item.default;\n }\n });\n return instanceState;\n }\n\n private initializeServiceDefault(): DerivedServiceState<TConfig> {\n const serviceState: any = {};\n Object.keys(this.config).forEach((key) => {\n const item: ConfigItem<any> = this.config[key];\n if (item.partition === Partition.Service) {\n serviceState[key] = item.default;\n }\n });\n return serviceState;\n }\n\n private log(message: string, ...args: any[]) {\n if (this.debug) {\n console.log(`CrannSource [core], ` + message, ...args);\n }\n }\n private instanceLog(message: string, key: string, ...args: any[]) {\n if (this.debug) {\n console.log(`CrannSource [${key}], ` + message, ...args);\n }\n }\n private error(message: string, ...args: any[]) {\n console.error(`CrannSource [core], ` + message, ...args);\n }\n private warn(message: string, ...args: any[]) {\n console.warn(`CrannSource [core], ` + message, ...args);\n }\n}\n\nexport function create<TConfig extends Record<string, ConfigItem<any>>>(\n config: TConfig,\n options?: CrannOptions\n): [\n (key?: string) => DerivedState<TConfig>,\n (\n state: Partial<\n DerivedInstanceState<TConfig> & DerivedServiceState<TConfig>\n >,\n key?: string\n ) => Promise<void>,\n (\n listener: (\n state: DerivedInstanceState<TConfig> | DerivedState<TConfig>,\n changes: Partial<\n DerivedInstanceState<TConfig> & DerivedServiceState<TConfig>\n >,\n agent?: AgentInfo\n ) => void\n ) => void,\n (location: BrowserLocation) => string | null\n] {\n const instance = Crann.getInstance(config, options);\n return [\n instance.get.bind(instance),\n instance.set.bind(instance),\n instance.subscribe.bind(instance),\n instance.findInstance.bind(instance),\n ];\n}\n", "export const Partition = {\n Instance: \"instance\" as const,\n Service: \"service\" as const,\n};\n\nexport const Persistence = {\n Session: \"session\" as const,\n Local: \"local\" as const,\n None: \"none\" as const,\n};\n\ntype ConfigItem<T> = {\n default: T;\n partition?: (typeof Partition)[keyof typeof Partition];\n persist?: (typeof Persistence)[keyof typeof Persistence];\n};\n\ntype AnyConfig = Record<string, ConfigItem<any>>;\n\n// export type Config = typeof StateConfig;\n\ntype DerivedState<T extends AnyConfig> = {\n [P in keyof T]: T[P][\"default\"];\n};\n\ntype DerivedInstanceState<T extends AnyConfig> = {\n [P in keyof T as T[P][\"partition\"] extends \"instance\"\n ? P\n : never]: T[P][\"default\"];\n};\n\ntype DerivedServiceState<T extends AnyConfig> = {\n [P in keyof T as T[P][\"partition\"] extends \"service\"\n ? P\n : never]: T[P][\"default\"];\n};\n\ntype StateSubscriber<TConfig extends AnyConfig> = {\n keys?: Array<keyof DerivedState<TConfig>>;\n callback: (changes: StateUpdate<TConfig>) => void;\n};\n\ntype CrannAgent<TConfig extends AnyConfig> = {\n get: () => DerivedState<TConfig>;\n set: (update: StateUpdate<TConfig>) => void;\n subscribe: (\n callback: (changes: StateUpdate<TConfig>) => void,\n keys?: Array<keyof TConfig>\n ) => () => void;\n};\n\ntype UseCrann<TConfig extends AnyConfig> = <\n K extends keyof DerivedState<TConfig>\n>(\n key: K\n) => [\n DerivedState<TConfig>[K],\n (value: DerivedState<TConfig>[K]) => void,\n (callback: (value: DerivedState<TConfig>[K]) => void) => () => void\n];\n\ntype ConnectReturn<TConfig extends AnyConfig> = [\n UseCrann<TConfig>,\n CrannAgent<TConfig>[\"get\"],\n CrannAgent<TConfig>[\"set\"],\n CrannAgent<TConfig>[\"subscribe\"]\n];\n\ntype AgentSubscription<TConfig extends AnyConfig> = {\n (\n callback: (changes: StateUpdate<TConfig>) => void,\n key?: keyof DerivedState<TConfig>\n ): number;\n};\n\ntype StateUpdate<TConfig extends AnyConfig> = Partial<DerivedState<TConfig>>;\n\nexport type CrannOptions = {\n debug?: boolean;\n storagePrefix?: string;\n};\n\nexport {\n AnyConfig,\n ConfigItem,\n DerivedState,\n DerivedInstanceState,\n DerivedServiceState,\n StateSubscriber,\n CrannAgent,\n AgentSubscription,\n StateUpdate,\n DerivedState as State,\n ConnectReturn,\n UseCrann,\n};\n", "export function deepEqual(a: any, b: any): boolean {\n if (a === b) return true;\n\n if (a == null || typeof a !== 'object' || b == null || typeof b !== 'object') return false;\n\n const keysA = Object.keys(a);\n const keysB = Object.keys(b);\n\n if (keysA.length !== keysB.length) return false;\n\n keysA.sort();\n keysB.sort();\n\n for (let i = 0; i < keysA.length; i++) {\n const key = keysA[i];\n if (key !== keysB[i] || !deepEqual(a[key], b[key])) return false;\n }\n return true;\n}", "// Create a global debug state manager\nexport class DebugManager {\n private static _debug: boolean = false;\n\n static setDebug(value: boolean): void {\n DebugManager._debug = value;\n }\n\n static isDebugEnabled(): boolean {\n return DebugManager._debug;\n }\n}\n\n// Export a convenience function\nexport function isDebugEnabled(): boolean {\n return DebugManager.isDebugEnabled();\n}\n", "import { isDebugEnabled } from \"./debug\";\n\nexport type StateChangeMetadata = {\n source: string;\n timestamp: number;\n changes: any;\n instanceKey?: string;\n};\n\nexport function trackStateChange(\n target: any,\n propertyKey: string,\n descriptor: PropertyDescriptor\n): PropertyDescriptor {\n const originalMethod = descriptor.value;\n\n descriptor.value = function (...args: any[]) {\n // Only log if debugging is enabled\n if (isDebugEnabled()) {\n // Get the stack trace to find the actual caller\n const stack = new Error().stack;\n const lines = stack?.split(\"\\n\") || [];\n const callerMatch = lines[3]?.match(/at\\s+(\\S+)\\s+/);\n const caller = callerMatch ? callerMatch[1] : \"unknown\";\n\n const instanceKey = args.length > 1 ? args[1] : undefined;\n\n const metadata: StateChangeMetadata = {\n source: caller,\n timestamp: Date.now(),\n changes: args[0],\n instanceKey,\n };\n\n console.log(`Crann State Change:`, metadata);\n }\n return originalMethod.apply(this, args);\n };\n\n return descriptor;\n}\n", "import {\n ConfigItem,\n DerivedState,\n StateSubscriber,\n DerivedInstanceState,\n DerivedServiceState,\n ConnectReturn,\n UseCrann,\n} from \"./model/crann.model\";\nimport { connect as connectPorter, PorterContext } from \"porter-source\";\n\nlet crannInstance: unknown = null;\n\nexport function connect<TConfig extends Record<string, ConfigItem<any>>>(\n config: TConfig,\n options?: { context?: string; debug?: boolean }\n): ConnectReturn<TConfig> {\n const debug = options?.debug || false;\n const context = options?.context;\n let _myKey = \"unset\";\n const log = (message: string, ...args: any[]) => {\n if (debug) {\n console.log(`CrannAgent [${_myKey}] ` + message, ...args);\n }\n };\n log(\"Initializing with context: \", context);\n if (crannInstance) {\n log(\"We had an instance already, returning\");\n return crannInstance as ConnectReturn<TConfig>;\n }\n log(\"No existing instance, creating a new one\");\n const [post, setMessages] = connectPorter({\n namespace: \"crann\",\n agentContext: context as PorterContext,\n });\n setMessages({\n initialState: (message) => {\n _state = message.payload.state;\n _myKey = message.payload.key;\n listeners.forEach((listener) => {\n listener.callback(_state);\n });\n log(`Initial state received and ${listeners.size} listeners notified`);\n },\n stateUpdate: (message) => {\n log(\"State updated: \", message);\n changes = message.payload.state;\n _state = { ..._state, ...changes };\n if (!!changes) {\n log(\"Notifying listeners of state update\");\n listeners.forEach((listener) => {\n if (listener.keys === undefined) {\n log(\"Found a universal listener, notifying\");\n listener.callback(changes!);\n } else {\n const matchFound = listener.keys.some((key) =>\n changes!.hasOwnProperty(key)\n );\n if (matchFound) {\n log(\"Found a specific listener for this item, notifying\");\n listener.callback(changes!);\n }\n }\n });\n }\n },\n });\n log(\"Porter connected. Setting up state and listeners\");\n let _state = getDerivedState(config);\n let changes: Partial<DerivedState<TConfig>> | null = null;\n const listeners = new Set<StateSubscriber<TConfig>>();\n\n log(\"Completed setup, returning instance\");\n\n const get = () => _state;\n const set = (newState: Partial<DerivedState<TConfig>>) => {\n console.log(\"CrannAgent, calling post with setState\");\n post({ action: \"setState\", payload: { state: newState } });\n };\n const subscribe = (\n callback: (changes: Partial<DerivedState<TConfig>>) => void,\n keys?: Array<keyof DerivedState<TConfig>>\n ): (() => void) => {\n const listener = { keys, callback };\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n };\n\n const useCrann: UseCrann<TConfig> = <K extends keyof DerivedState<TConfig>>(\n key: K\n ) => {\n const getValue = () => get()[key] as DerivedState<TConfig>;\n const setValue = (value: DerivedState<TConfig>[K]) =>\n set({ [key]: value } as Partial<DerivedState<TConfig>>);\n const subscribeToChanges = (\n callback: (value: DerivedState<TConfig>[K]) => void\n ) => {\n return subscribe(\n (changes) => {\n if (key in changes) {\n callback(changes[key] as DerivedState<TConfig>[K]);\n }\n },\n [key]\n );\n };\n\n return [getValue(), setValue, subscribeToChanges];\n };\n\n const instance: ConnectReturn<TConfig> = [useCrann, get, set, subscribe];\n crannInstance = instance;\n\n return crannInstance as ConnectReturn<TConfig>;\n}\n\nexport function connected(): boolean {\n return crannInstance !== null;\n}\n\nfunction getDerivedState<TConfig extends Record<string, ConfigItem<any>>>(\n config: TConfig\n): DerivedState<TConfig> {\n const instanceState = {} as DerivedInstanceState<TConfig>;\n\n Object.keys(config).forEach((key) => {\n const item: ConfigItem<any> = config[key];\n if (item.partition === \"instance\") {\n instanceState[key as keyof DerivedInstanceState<TConfig>] = item.default;\n }\n });\n\n const serviceState = {} as DerivedServiceState<TConfig>;\n Object.keys(config).forEach((key) => {\n const item: ConfigItem<any> = config[key];\n if (item.partition === \"instance\") {\n serviceState[key as keyof DerivedServiceState<TConfig>] = item.default;\n }\n });\n\n return {\n ...instanceState,\n ...serviceState,\n } as unknown as DerivedState<TConfig>;\n}\n", "import { useState, useEffect, useCallback, useMemo, useRef } from \"react\";\nimport { ConfigItem, DerivedState } from \"../model/crann.model\";\nimport { connect } from \"../crannAgent\";\n\nexport function createCrannStateHook<\n TConfig extends Record<string, ConfigItem<any>>\n>(config: TConfig) {\n return function useCrannState(context?: string) {\n const [useCrann, get, set, subscribe] = useMemo(() => {\n const instance = connect(config);\n return instance;\n }, [context]);\n\n const useStateItem = useCallback(\n <K extends keyof DerivedState<TConfig>>(key: K) => {\n const [value, setValue] = useState<DerivedState<TConfig>[K]>(\n get()[key]\n );\n const valueRef = useRef(value);\n\n useEffect(() => {\n valueRef.current = value;\n }, [value]);\n\n useEffect(() => {\n setValue(get()[key]);\n const unsubscribe = subscribe(\n (changes) => {\n if (key in changes) {\n setValue(changes[key] as DerivedState<TConfig>[K]);\n }\n },\n [key]\n );\n return unsubscribe;\n }, [key]);\n\n const updateValue = useCallback(\n (newValue: DerivedState<TConfig>[K]) => {\n set({ [key]: newValue } as Partial<DerivedState<TConfig>>);\n },\n [key]\n );\n\n return [value, updateValue] as const;\n },\n [get, set, subscribe]\n );\n\n const getState = useCallback(() => get(), [get]);\n\n const setState = useCallback(\n (newState: Partial<DerivedState<TConfig>>) => {\n set(newState);\n },\n [set]\n );\n\n return {\n useStateItem,\n getState,\n setState,\n useCrann,\n };\n };\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["browser", "Partition", "Persistence", "source", "getAgentById", "getAgentByLocation", "deepEqual", "a", "b", "keysA", "keysB", "key", "_DebugManager", "value", "DebugManager", "isDebugEnabled", "trackStateChange", "target", "propertyKey", "descriptor", "originalMethod", "args", "_a", "isDebugEnabled", "stack", "callerMatch", "caller", "instanceKey", "metadata", "_Crann", "config", "options", "_a", "DebugManager", "post", "setMessages", "onConnect", "onDisconnect", "onMessagesSet", "source", "message", "info", "agentTag", "fullState", "key", "initialInstanceState", "state", "update", "deepEqual", "currentState", "wasPersisted", "persistence", "value", "browser", "_", "listener", "changes", "agent", "getAgentById", "location", "getAgentByLocation", "instance", "worker", "itemKey", "item", "instanceItemKey", "instanceState", "Partition", "serviceItemKey", "serviceState", "local", "session", "combined", "hadItems", "prefixedKey", "args", "__decorateClass", "trackStateChange", "Crann", "create", "connectPorter", "crannInstance", "connect", "config", "options", "debug", "context", "_myKey", "log", "message", "args", "post", "setMessages", "_state", "listeners", "listener", "changes", "key", "getDerivedState", "get", "set", "newState", "subscribe", "callback", "keys", "getValue", "setValue", "value", "subscribeToChanges", "connected", "instanceState", "item", "serviceState", "useState", "useEffect", "useCallback", "useMemo", "useRef", "createCrannStateHook", "config", "context", "useCrann", "get", "set", "subscribe", "useMemo", "connect", "useStateItem", "useCallback", "key", "value", "setValue", "useState", "valueRef", "useRef", "useEffect", "changes", "updateValue", "newValue", "getState", "setState", "newState"]
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "crann",
3
- "version": "1.0.21",
3
+ "version": "1.0.22",
4
4
  "description": "",
5
5
  "main": "dist/cjs/index.js",
6
6
  "module": "dist/esm/index.js",
@@ -33,17 +33,17 @@
33
33
  "devDependencies": {
34
34
  "@types/jest": "^29.5.12",
35
35
  "@types/node": "^22.2.0",
36
+ "@types/react": "^18.2.32",
37
+ "@types/react-dom": "^18.2.10",
36
38
  "@types/webextension-polyfill": "^0.10.7",
37
39
  "esbuild": "^0.23.0",
38
40
  "esbuild-node-externals": "^1.14.0",
39
41
  "jest": "^29.7.0",
40
- "typescript": "^5.5.4",
41
- "webextension-polyfill": "^0.12.0",
42
+ "porter-source": "^1.1.8",
42
43
  "react": "^18.2.0",
43
44
  "react-dom": "^18.2.0",
44
- "porter-source": "^1.1.6",
45
- "@types/react": "^18.2.32",
46
- "@types/react-dom": "^18.2.10"
45
+ "typescript": "^5.5.4",
46
+ "webextension-polyfill": "^0.12.0"
47
47
  },
48
48
  "repository": {
49
49
  "type": "git",