crann 1.0.8 → 1.0.14

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,2 +1,2 @@
1
- "use strict";var k=Object.create;var S=Object.defineProperty;var w=Object.getOwnPropertyDescriptor;var A=Object.getOwnPropertyNames;var R=Object.getPrototypeOf,E=Object.prototype.hasOwnProperty;var U=(o,t)=>{for(var e in t)S(o,e,{get:t[e],enumerable:!0})},h=(o,t,e,i)=>{if(t&&typeof t=="object"||typeof t=="function")for(let n of A(t))!E.call(o,n)&&n!==e&&S(o,n,{get:()=>t[n],enumerable:!(i=w(t,n))||i.enumerable});return o};var O=(o,t,e)=>(e=o!=null?k(R(o)):{},h(t||!o||!o.__esModule?S(e,"default",{value:o,enumerable:!0}):e,o)),j=o=>h(S({},"__esModule",{value:!0}),o);var M={};U(M,{Crann:()=>C,Partition:()=>g,Persistence:()=>y,connect:()=>b,create:()=>I});module.exports=j(M);var d=O(require("webextension-polyfill"));var g={Instance:"instance",Common:"common"},y={Session:"session",Local:"local",None:"none"};var D=require("porter-source");function l(o,t){if(o===t)return!0;if(o==null||typeof o!="object"||t==null||typeof t!="object")return!1;let e=Object.keys(o),i=Object.keys(t);if(e.length!==i.length)return!1;e.sort(),i.sort();for(let n=0;n<e.length;n++){let a=e[n];if(a!==i[n]||!l(o[a],t[a]))return!1}return!0}var C=class{constructor(t,e){this.config=t;this.instances=new Map;this.stateChangeListeners=[];this.storagePrefix="crann_";this.post=()=>{};console.log("Crann constructor"),this.defaultInstanceState=this.initializeInstanceDefault(),this.defaultCommonState=this.commonState=this.initializeCommonDefault(),this.hydrate();let[i,n,a,s]=(0,D.source)("crann");this.post=i,a(({key:r,connectionType:m,context:p,location:u})=>{console.log("Crann porter connect",r,m,p,u),this.addInstance(r),s(({key:v,connectionType:c,context:f,location:T})=>{console.log("Crann porter connect",v,c,f,T),this.removeInstance(v)})}),this.storagePrefix=e??this.storagePrefix}async addInstance(t){if(this.instances.has(t))console.warn("Crann instance already exists",t);else{let e={...this.defaultInstanceState};this.instances.set(t,e)}}async removeInstance(t){this.instances.has(t)?this.instances.delete(t):console.warn("Crann instance does not exist",t)}async setCommonState(t){let e={...this.commonState,...t};l(this.commonState,e)||(this.commonState=e,await this.persist(t),this.notify(t))}async setInstanceState(t,e){let i=this.instances.get(t)||this.defaultInstanceState,n={...i,...e};l(i,n)||(this.instances.set(t,n),this.notify(e,t))}async persist(t){for(let e in t||this.commonState){let n=this.config[e].persist||"none",a=t?t[e]:this.commonState[e];switch(n){case"session":await d.default.storage.session.set({[this.storagePrefix+e]:a});break;case"local":await d.default.storage.local.set({[this.storagePrefix+e]:a});break;default:break}}}async clear(){this.commonState=this.defaultCommonState,this.instances.forEach((t,e)=>{this.instances.set(e,this.defaultInstanceState)}),await this.persist(),this.notify({})}subscribe(t){this.stateChangeListeners.push(t)}notify(t,e){let i=e?this.get(e):this.get();this.stateChangeListeners.forEach(n=>n(i,t,e)),e?this.post({action:"stateUpdate",payload:{state:t}},e):this.instances.forEach((n,a)=>{this.post({action:"stateUpdate",payload:{state:t}},a)})}get(t){return t?{...this.commonState,...this.instances.get(t)}:{...this.commonState}}async set(t,e){let i={},n={};for(let a in t){let s=this.config[a];if(s.partition==="instance"){let r=a,m=t;i[r]=m[r]}else if(!s.partition||s.partition===g.Common){let r=a,m=t;n[r]=m[r]}}e&&this.setInstanceState(e,i),this.setCommonState(n)}async hydrate(){let t=await d.default.storage.local.get(null),e=await d.default.storage.session.get(null),i={...t,...e},n={};for(let a in i){let s=this.removePrefix(a);if(this.config.hasOwnProperty(s)){let r=i[s];n[s]=r}}this.commonState={...this.defaultCommonState,...n}}removePrefix(t){return t.startsWith(this.storagePrefix)?t.replace(this.storagePrefix,""):t}initializeInstanceDefault(){let t={};return Object.keys(this.config).forEach(e=>{let i=this.config[e];i.partition==="instance"&&(t[e]=i.default)}),t}initializeCommonDefault(){let t={};return Object.keys(this.config).forEach(e=>{let i=this.config[e];i.partition===g.Common&&(t[e]=i.default)}),t}};function I(o,t){return new C(o,t)}var P=require("porter-source");function b(o,t){let[e,i]=(0,P.connect)({namespace:"crann"}),n=L(o),a=null,s=new Map,r=0;return i({stateUpdate:c=>{a=c.payload.state,n={...n,...a},a&&s.forEach(f=>{(f.keys===void 0||f.keys.some(x=>a.hasOwnProperty(x)))&&f.callback(a)})}}),{get:()=>n,set:c=>{e({action:"setState",payload:{state:c}})},subscribe:(c,f)=>(s.set(++r,{keys:f,callback:c}),r),unsubscribe:c=>{s.delete(c)}}}function L(o){let t={};Object.keys(o).forEach(i=>{let n=o[i];n.partition==="instance"&&(t[i]=n.default)});let e={};return Object.keys(o).forEach(i=>{let n=o[i];n.partition==="instance"&&(e[i]=n.default)}),{...t,...e}}0&&(module.exports={Crann,Partition,Persistence,connect,create});
1
+ "use strict";var M=Object.create;var p=Object.defineProperty;var R=Object.getOwnPropertyDescriptor;var E=Object.getOwnPropertyNames;var j=Object.getPrototypeOf,O=Object.prototype.hasOwnProperty;var L=(o,t)=>{for(var e in t)p(o,e,{get:t[e],enumerable:!0})},b=(o,t,e,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of E(t))!O.call(o,i)&&i!==e&&p(o,i,{get:()=>t[i],enumerable:!(n=R(t,i))||n.enumerable});return o};var z=(o,t,e)=>(e=o!=null?M(j(o)):{},b(t||!o||!o.__esModule?p(e,"default",{value:o,enumerable:!0}):e,o)),F=o=>b(p({},"__esModule",{value:!0}),o);var V={};L(V,{Crann:()=>S,Partition:()=>m,Persistence:()=>x,connect:()=>w,connected:()=>K,create:()=>k});module.exports=F(V);var v=z(require("webextension-polyfill"));var m={Instance:"instance",Common:"common"},x={Session:"session",Local:"local",None:"none"};var g=require("porter-source");function T(o,t){if(o===t)return!0;if(o==null||typeof o!="object"||t==null||typeof t!="object")return!1;let e=Object.keys(o),n=Object.keys(t);if(e.length!==n.length)return!1;e.sort(),n.sort();for(let i=0;i<e.length;i++){let a=e[i];if(a!==n[i]||!T(o[a],t[a]))return!1}return!0}var C=class C{constructor(t,e){this.config=t;this.instances=new Map;this.stateChangeListeners=[];this.storagePrefix="crann_";this.post=()=>{};this.defaultInstanceState=this.initializeInstanceDefault(),this.defaultCommonState=this.commonState=this.initializeCommonDefault(),this.hydrate();let[n,i,a,s]=(0,g.source)("crann");this.post=n,a(({key:r,connectionType:d,context:y,location:U})=>{this.addInstance(r),s(({key:P,connectionType:c,context:f,location:l})=>{this.removeInstance(P)})}),this.storagePrefix=e??this.storagePrefix}static getInstance(t,e){return C.instance||(C.instance=new C(t,e)),C.instance}async addInstance(t){if(!this.instances.has(t)){let e={...this.defaultInstanceState};this.instances.set(t,e)}}async removeInstance(t){this.instances.has(t)&&this.instances.delete(t)}async setCommonState(t){let e={...this.commonState,...t};T(this.commonState,e)||(this.commonState=e,await this.persist(t),this.notify(t))}async setInstanceState(t,e){let n=this.instances.get(t)||this.defaultInstanceState,i={...n,...e};T(n,i)||(this.instances.set(t,i),this.notify(e,t))}async persist(t){for(let e in t||this.commonState){let i=this.config[e].persist||"none",a=t?t[e]:this.commonState[e];switch(i){case"session":await v.default.storage.session.set({[this.storagePrefix+e]:a});break;case"local":await v.default.storage.local.set({[this.storagePrefix+e]:a});break;default:break}}}async clear(){this.commonState=this.defaultCommonState,this.instances.forEach((t,e)=>{this.instances.set(e,this.defaultInstanceState)}),await this.persist(),this.notify({})}subscribe(t){this.stateChangeListeners.push(t)}notify(t,e){let n=e?(0,g.getMetadata)(e):void 0,i=n?(0,g.getTarget)(n):void 0,a=e?this.get(e):this.get();this.stateChangeListeners.forEach(s=>s(a,t,n||void 0)),i?this.post({action:"stateUpdate",payload:{state:t}},i):this.instances.forEach((s,r)=>{this.post({action:"stateUpdate",payload:{state:t}},r)})}get(t){return t?{...this.commonState,...this.instances.get(t)}:{...this.commonState}}findInstance(t,e){let n=(0,g.getKey)({context:t,...e});for(let[i,a]of this.instances)if(i===n)return i;return null}async set(t,e){let n={},i={};for(let a in t){let s=this.config[a];if(s.partition==="instance"){let r=a,d=t;n[r]=d[r]}else if(!s.partition||s.partition===m.Common){let r=a,d=t;i[r]=d[r]}}e&&this.setInstanceState(e,n),this.setCommonState(i)}async hydrate(){let t=await v.default.storage.local.get(null),e=await v.default.storage.session.get(null),n={...t,...e},i={};for(let a in n){let s=this.removePrefix(a);if(this.config.hasOwnProperty(s)){let r=n[s];i[s]=r}}this.commonState={...this.defaultCommonState,...i}}removePrefix(t){return t.startsWith(this.storagePrefix)?t.replace(this.storagePrefix,""):t}initializeInstanceDefault(){let t={};return Object.keys(this.config).forEach(e=>{let n=this.config[e];n.partition==="instance"&&(t[e]=n.default)}),t}initializeCommonDefault(){let t={};return Object.keys(this.config).forEach(e=>{let n=this.config[e];n.partition===m.Common&&(t[e]=n.default)}),t}};C.instance=null;var S=C;function k(o,t){let e=S.getInstance(o,t);return[e.get.bind(e),e.set.bind(e),e.subscribe.bind(e),e.findInstance.bind(e)]}var A=require("porter-source"),u=null;function w(o,t){if(u)return u;let[e,n]=(0,A.connect)({namespace:"crann"}),i=q(o),a=null,s=new Set;n({stateUpdate:c=>{a=c.payload.state,i={...i,...a},a&&s.forEach(f=>{(f.keys===void 0||f.keys.some(h=>a.hasOwnProperty(h)))&&f.callback(a)})}});let r=()=>i,d=c=>{e({action:"setState",payload:{state:c}})},y=(c,f)=>{let l={keys:f,callback:c};return s.add(l),()=>{s.delete(l)}};return u=[c=>{let f=()=>r()[c],l=D=>d({[c]:D}),h=D=>y(I=>{c in I&&D(I[c])},[c]);return[f(),l,h]},r,d,y],u}function K(){return u!==null}function q(o){let t={};Object.keys(o).forEach(n=>{let i=o[n];i.partition==="instance"&&(t[n]=i.default)});let e={};return Object.keys(o).forEach(n=>{let i=o[n];i.partition==="instance"&&(e[n]=i.default)}),{...t,...e}}0&&(module.exports={Crann,Partition,Persistence,connect,connected,create});
2
2
  //# 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/crannAgent.ts"],
4
- "sourcesContent": ["export { create, Crann } from './crann';\nexport { connect } from './crannAgent';\nexport { CrannAgent, StateUpdate, State, Partition, Persistence } from './model/crann.model';", "import browser from 'webextension-polyfill';\nimport { DerivedInstanceState, DerivedCommonState, ConfigItem, DerivedState, Partition, CrannAgent, StateSubscriber } from './model/crann.model';\nimport { source, } from 'porter-source';\nimport { deepEqual } from './utils/deepEqual';\nimport { AgentLocation, AgentMetadata } from 'porter-source/dist/types/porter.model';\n\nexport class Crann<TConfig extends Record<string, ConfigItem<any>>> {\n private instances: Map<string, DerivedInstanceState<TConfig>> = new Map();\n private defaultCommonState: DerivedCommonState<TConfig>;\n private defaultInstanceState: DerivedInstanceState<TConfig>;\n private commonState: DerivedCommonState<TConfig>;\n private stateChangeListeners: Array<(state: (DerivedCommonState<TConfig>) | (DerivedCommonState<TConfig> & DerivedInstanceState<TConfig>), changes: Partial<DerivedCommonState<TConfig> & DerivedInstanceState<TConfig>>, key?: string) => void> = [];\n private storagePrefix = 'crann_';\n private post: (message: any, contextOrKey: string, location?: Partial<AgentLocation>) => void = () => { };\n\n constructor(private config: TConfig, storagePrefix?: string) {\n console.log('Crann constructor');\n this.defaultInstanceState = this.initializeInstanceDefault();\n this.defaultCommonState = this.commonState = this.initializeCommonDefault();\n this.hydrate();\n const [post, _setMessages, onConnect, onDisconnect] = source('crann');\n this.post = post;\n onConnect(({ key, connectionType, context, location }) => {\n console.log('Crann porter connect', key, connectionType, context, location);\n this.addInstance(key);\n onDisconnect(({ key, connectionType, context, location }) => {\n console.log('Crann porter connect', key, connectionType, context, location);\n this.removeInstance(key);\n });\n });\n this.storagePrefix = storagePrefix ?? this.storagePrefix;\n }\n\n private async addInstance(key: string): Promise<void> {\n if (!this.instances.has(key)) {\n const initialInstanceState = { ...this.defaultInstanceState } as DerivedInstanceState<TConfig>;\n this.instances.set(key, initialInstanceState);\n } else {\n console.warn('Crann instance already exists', key);\n }\n }\n\n private async removeInstance(key: string): Promise<void> {\n if (this.instances.has(key)) {\n this.instances.delete(key);\n } else {\n console.warn('Crann instance does not exist', key);\n }\n }\n\n public async setCommonState(state: Partial<DerivedCommonState<TConfig>>): Promise<void> {\n const update = { ...this.commonState, ...state };\n if (!deepEqual(this.commonState, update)) {\n this.commonState = update;\n await this.persist(state);\n this.notify(state as Partial<DerivedState<TConfig>>);\n }\n }\n\n public async setInstanceState(key: string, state: Partial<DerivedInstanceState<TConfig>>): Promise<void> {\n const currentState = this.instances.get(key) || this.defaultInstanceState;\n const update = { ...currentState, ...state };\n if (!deepEqual(currentState, update)) {\n this.instances.set(key, update);\n this.notify(state as Partial<DerivedState<TConfig>>, key);\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(state?: Partial<DerivedCommonState<TConfig>>): Promise<void> {\n for (const key in (state || this.commonState)) {\n const item = this.config[key] as ConfigItem<any>;\n const persistence = item.persist || 'none';\n const value = state ? state[key as keyof DerivedCommonState<TConfig>] : this.commonState[key];\n switch (persistence) {\n case 'session':\n await browser.storage.session.set({ [this.storagePrefix + (key as string)]: value });\n break;\n case 'local':\n await browser.storage.local.set({ [this.storagePrefix + (key as string)]: value });\n break;\n default:\n break;\n }\n }\n }\n\n public async clear(): Promise<void> {\n this.commonState = this.defaultCommonState;\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(listener: (state: (DerivedCommonState<TConfig>) | (DerivedInstanceState<TConfig> & DerivedCommonState<TConfig>), changes: Partial<DerivedInstanceState<TConfig> & DerivedCommonState<TConfig>>, key?: string) => void): void {\n this.stateChangeListeners.push(listener);\n }\n\n private notify(changes: Partial<DerivedCommonState<TConfig> & DerivedInstanceState<TConfig>>, key?: string): void {\n const state = key ? this.get(key) : this.get();\n this.stateChangeListeners.forEach(listener => listener(state, changes, key));\n if (key) {\n this.post({ action: 'stateUpdate', payload: { state: changes } }, key);\n } else {\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(): DerivedCommonState<TConfig>;\n public get(key: string): DerivedInstanceState<TConfig> & DerivedCommonState<TConfig>;\n public get(key?: string): ((DerivedInstanceState<TConfig> & DerivedCommonState<TConfig>) | DerivedCommonState<TConfig>) {\n if (!key) {\n return { ...this.commonState, ...{} as DerivedInstanceState<TConfig> };\n }\n return { ...this.commonState, ...this.instances.get(key) };\n }\n\n public async set(state: Partial<DerivedCommonState<TConfig>>): Promise<void>\n public async set(state: Partial<DerivedInstanceState<TConfig> & DerivedCommonState<TConfig>>, key: string): Promise<void>\n public async set(state: Partial<DerivedInstanceState<TConfig> | DerivedCommonState<TConfig>>, key?: string): Promise<void> {\n const instance = {} as Partial<DerivedInstanceState<TConfig>>;\n const worker = {} as Partial<DerivedCommonState<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.Common) {\n const commonItemKey = itemKey as keyof DerivedCommonState<TConfig>;\n const commonState = state as Partial<DerivedCommonState<TConfig>>;\n worker[commonItemKey] = commonState[commonItemKey]!;\n }\n }\n if (key) this.setInstanceState(key, instance);\n this.setCommonState(worker);\n }\n\n private async hydrate(): Promise<void> {\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<DerivedCommonState<TConfig>> = {}; // Cast update as Partial<DerivedState<TConfig>>\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 DerivedCommonState<TConfig>] = value;\n }\n }\n this.commonState = { ...this.defaultCommonState, ...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 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 initializeCommonDefault(): DerivedCommonState<TConfig> {\n const commonState: any = {};\n Object.keys(this.config).forEach(key => {\n const item: ConfigItem<any> = this.config[key];\n if (item.partition === Partition.Common) {\n commonState[key] = item.default;\n }\n });\n return commonState;\n }\n}\n\n\nexport function create<TConfig extends Record<string, ConfigItem<any>>>(config: TConfig, storagePrefix?: string): Crann<TConfig> {\n return new Crann(config, storagePrefix);\n}\n\n", "import browser from 'webextension-polyfill';\n\nexport const Partition = {\n Instance: 'instance' as const,\n Common: 'common' as const\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\n// export type Config = typeof StateConfig;\n\ntype DerivedState<T extends Record<string, ConfigItem<any>>> = {\n [P in keyof T]: T[P]['default'];\n};\ntype DerivedInstanceState<T extends Record<string, ConfigItem<any>>> = {\n [P in keyof T as T[P]['partition'] extends 'instance' ? P : never]: T[P]['default'];\n};\ntype DerivedCommonState<T extends Record<string, ConfigItem<any>>> = {\n [P in keyof T as T[P]['partition'] extends 'common' ? P : never]: T[P]['default'];\n};\n\ntype StateSubscriber<TConfig extends Record<string, ConfigItem<any>>> = {\n keys?: Array<keyof DerivedState<TConfig>>;\n callback: (changes: StateUpdate<TConfig>) => void;\n}\n\ntype CrannAgent<TConfig extends Record<string, ConfigItem<any>>> = {\n get: () => DerivedCommonState<TConfig> & DerivedInstanceState<TConfig>;\n set: (update: StateUpdate<TConfig>) => void;\n subscribe: (callback: (changes: StateUpdate<TConfig>) => void, keys?: Array<keyof TConfig>) => number;\n unsubscribe: (id: number) => void;\n}\n\ntype AgentSubscription<TConfig extends Record<string, ConfigItem<any>>> = {\n (callback: (changes: StateUpdate<TConfig>) => void, key?: keyof DerivedState<TConfig>): number;\n}\n\ntype StateUpdate<TConfig extends Record<string, ConfigItem<any>>> = Partial<DerivedState<TConfig>>;\n\nexport { ConfigItem, DerivedState, DerivedInstanceState, DerivedCommonState, StateSubscriber, CrannAgent, AgentSubscription, StateUpdate, DerivedState as State };\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}", "import { ConfigItem, CrannAgent, DerivedState, StateSubscriber, DerivedInstanceState, DerivedCommonState } from \"./model/crann.model\";\nimport { connect as connectPorter } from 'porter-source'\n\nexport function connect<TConfig extends Record<string, ConfigItem<any>>>(config: TConfig, context?: string): CrannAgent<TConfig> {\n const [post, setMessages] = connectPorter({ namespace: 'crann' });\n let _state = getDerivedState(config);\n let changes: Partial<DerivedState<TConfig>> | null = null;\n const listeners = new Map<number, StateSubscriber<TConfig>>();\n let listenerId = 0;\n setMessages({\n stateUpdate: (message) => {\n changes = message.payload.state;\n _state = { ..._state, ...changes };\n if (!!changes) {\n listeners.forEach(listener => {\n if (listener.keys === undefined) {\n listener.callback(changes!);\n } else {\n const matchFound = listener.keys.some(key => changes!.hasOwnProperty(key))\n matchFound && listener.callback(changes!);\n }\n });\n }\n }\n });\n\n const get = () => _state;\n const set = (newState: Partial<DerivedState<TConfig>>) => {\n post({ action: 'setState', payload: { state: newState } });\n }\n const subscribe = (callback: (changes: Partial<DerivedState<TConfig>>) => void, keys?: Array<keyof DerivedState<TConfig>>): number => {\n listeners.set(++listenerId, { keys, callback });\n return listenerId;\n }\n const unsubscribe = (id: number) => {\n listeners.delete(id);\n }\n return { get, set, subscribe, unsubscribe };\n}\n\nfunction getDerivedState<TConfig extends Record<string, ConfigItem<any>>>(config: TConfig): (DerivedInstanceState<TConfig> & DerivedCommonState<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 commonState = {} as DerivedCommonState<TConfig>;\n Object.keys(config).forEach(key => {\n const item: ConfigItem<any> = config[key];\n if (item.partition === 'instance') {\n commonState[key as keyof DerivedCommonState<TConfig>] = item.default;\n }\n });\n\n return { ...instanceState, ...commonState } as (DerivedInstanceState<TConfig> & DerivedCommonState<TConfig>);\n}\n"],
5
- "mappings": "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",
6
- "names": ["src_exports", "__export", "Crann", "Partition", "Persistence", "connect", "create", "__toCommonJS", "import_webextension_polyfill", "Partition", "Persistence", "import_porter_source", "deepEqual", "a", "b", "keysA", "keysB", "i", "key", "Crann", "config", "storagePrefix", "post", "_setMessages", "onConnect", "onDisconnect", "key", "connectionType", "context", "location", "initialInstanceState", "state", "update", "deepEqual", "currentState", "persistence", "value", "browser", "_", "listener", "changes", "instance", "worker", "itemKey", "item", "instanceItemKey", "instanceState", "Partition", "commonItemKey", "commonState", "local", "session", "combined", "prefixedKey", "create", "import_porter_source", "connect", "config", "context", "post", "setMessages", "connectPorter", "_state", "getDerivedState", "changes", "listeners", "listenerId", "message", "listener", "key", "newState", "callback", "keys", "id", "instanceState", "item", "commonState"]
4
+ "sourcesContent": ["export { create, Crann } from './crann';\nexport { connect, connected } from './crannAgent';\nexport { CrannAgent, StateUpdate, State, Partition, Persistence } from './model/crann.model';", "import browser from 'webextension-polyfill';\nimport { DerivedInstanceState, DerivedCommonState, ConfigItem, DerivedState, Partition } from './model/crann.model';\nimport { source, getMetadata, getKey, getTarget } from 'porter-source';\nimport { deepEqual } from './utils/deepEqual';\nimport { AgentLocation, AgentMetadata, Message, PorterContext, PostTarget } from 'porter-source/dist/types/porter.model';\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 defaultCommonState: DerivedCommonState<TConfig>;\n private defaultInstanceState: DerivedInstanceState<TConfig>;\n private commonState: DerivedCommonState<TConfig>;\n private stateChangeListeners: Array<(state: (DerivedInstanceState<TConfig> | DerivedState<TConfig>), changes: Partial<DerivedCommonState<TConfig> & DerivedInstanceState<TConfig>>, agent?: AgentMetadata) => void> = [];\n private storagePrefix = 'crann_';\n private post: (message: Message<any>, target?: PostTarget) => void = () => { };\n\n constructor(private config: TConfig, storagePrefix?: string) {\n console.log('Crann constructor');\n this.defaultInstanceState = this.initializeInstanceDefault();\n this.defaultCommonState = this.commonState = this.initializeCommonDefault();\n this.hydrate();\n const [post, _setMessages, onConnect, onDisconnect] = source('crann');\n this.post = post;\n onConnect(({ key, connectionType, context, location }) => {\n console.log('Crann porter connect', key, connectionType, context, location);\n this.addInstance(key);\n onDisconnect(({ key, connectionType, context, location }) => {\n console.log('Crann porter connect', key, connectionType, context, location);\n this.removeInstance(key);\n });\n });\n this.storagePrefix = storagePrefix ?? this.storagePrefix;\n }\n\n\n public static getInstance<TConfig extends Record<string, ConfigItem<any>>>(config: TConfig, storagePrefix?: string): Crann<TConfig> {\n if (!Crann.instance) {\n Crann.instance = new Crann(config, storagePrefix);\n }\n return Crann.instance;\n }\n\n private async addInstance(key: string): Promise<void> {\n if (!this.instances.has(key)) {\n const initialInstanceState = { ...this.defaultInstanceState } as DerivedInstanceState<TConfig>;\n this.instances.set(key, initialInstanceState);\n } else {\n console.warn('Crann instance already exists', key);\n }\n }\n\n private async removeInstance(key: string): Promise<void> {\n if (this.instances.has(key)) {\n this.instances.delete(key);\n } else {\n console.warn('Crann instance does not exist', key);\n }\n }\n\n public async setCommonState(state: Partial<DerivedCommonState<TConfig>>): Promise<void> {\n const update = { ...this.commonState, ...state };\n if (!deepEqual(this.commonState, update)) {\n this.commonState = update;\n await this.persist(state);\n this.notify(state as Partial<DerivedState<TConfig>>);\n }\n }\n\n public async setInstanceState(key: string, state: Partial<DerivedInstanceState<TConfig>>): Promise<void> {\n const currentState = this.instances.get(key) || this.defaultInstanceState;\n const update = { ...currentState, ...state };\n if (!deepEqual(currentState, update)) {\n this.instances.set(key, update);\n this.notify(state as Partial<DerivedState<TConfig>>, key);\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(state?: Partial<DerivedCommonState<TConfig>>): Promise<void> {\n for (const key in (state || this.commonState)) {\n const item = this.config[key] as ConfigItem<any>;\n const persistence = item.persist || 'none';\n const value = state ? state[key as keyof DerivedCommonState<TConfig>] : this.commonState[key];\n switch (persistence) {\n case 'session':\n await browser.storage.session.set({ [this.storagePrefix + (key as string)]: value });\n break;\n case 'local':\n await browser.storage.local.set({ [this.storagePrefix + (key as string)]: value });\n break;\n default:\n break;\n }\n }\n }\n\n public async clear(): Promise<void> {\n this.commonState = this.defaultCommonState;\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(listener: (state: (DerivedInstanceState<TConfig> | DerivedState<TConfig>), changes: Partial<DerivedInstanceState<TConfig> & DerivedCommonState<TConfig>>, agent?: AgentMetadata) => void): void {\n this.stateChangeListeners.push(listener);\n }\n\n private notify(changes: Partial<DerivedState<TConfig>>, key?: string): void {\n const agentMeta = key ? getMetadata(key) : undefined;\n const target = agentMeta ? getTarget(agentMeta) : undefined;\n const state = key ? this.get(key) : this.get();\n this.stateChangeListeners.forEach(listener => listener(state, changes, agentMeta || undefined));\n if (target) {\n this.post({ action: 'stateUpdate', payload: { state: changes } }, target);\n } else {\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(key: string): DerivedInstanceState<TConfig> & DerivedCommonState<TConfig>;\n public get(key?: string): (DerivedCommonState<TConfig> | DerivedState<TConfig>) {\n if (!key) {\n return { ...this.commonState, ...{} as DerivedInstanceState<TConfig> };\n }\n return { ...this.commonState, ...this.instances.get(key) };\n }\n\n public findInstance(context: PorterContext, location: AgentLocation): string | null {\n // Todo: This feels like too-tight coupleing between porter and crann. Should be a better way.\n const searchKey = getKey({ context, ...location })\n for (const [key, instance] of this.instances) {\n if (key === searchKey) {\n console.log('Crann found instance for key: ', key);\n return key\n }\n }\n return null;\n }\n\n public async set(state: Partial<DerivedCommonState<TConfig>>): Promise<void>\n public async set(state: Partial<DerivedInstanceState<TConfig> & DerivedCommonState<TConfig>>, key: string): Promise<void>\n public async set(state: Partial<DerivedInstanceState<TConfig> | DerivedCommonState<TConfig>>, key?: string): Promise<void> {\n const instance = {} as Partial<DerivedInstanceState<TConfig>>;\n const worker = {} as Partial<DerivedCommonState<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.Common) {\n const commonItemKey = itemKey as keyof DerivedCommonState<TConfig>;\n const commonState = state as Partial<DerivedCommonState<TConfig>>;\n worker[commonItemKey] = commonState[commonItemKey]!;\n }\n }\n if (key) this.setInstanceState(key, instance);\n this.setCommonState(worker);\n }\n\n private async hydrate(): Promise<void> {\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<DerivedCommonState<TConfig>> = {}; // Cast update as Partial<DerivedState<TConfig>>\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 DerivedCommonState<TConfig>] = value;\n }\n }\n this.commonState = { ...this.defaultCommonState, ...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 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 initializeCommonDefault(): DerivedCommonState<TConfig> {\n const commonState: any = {};\n Object.keys(this.config).forEach(key => {\n const item: ConfigItem<any> = this.config[key];\n if (item.partition === Partition.Common) {\n commonState[key] = item.default;\n }\n });\n return commonState;\n }\n}\n\n\nexport function create<TConfig extends Record<string, ConfigItem<any>>>(config: TConfig, storagePrefix?: string): [\n (key?: string) => (DerivedState<TConfig>),\n (state: Partial<DerivedInstanceState<TConfig> & DerivedCommonState<TConfig>>, key?: string) => Promise<void>,\n (listener: (state: (DerivedInstanceState<TConfig> | DerivedState<TConfig>), changes: Partial<DerivedInstanceState<TConfig> & DerivedCommonState<TConfig>>, agent?: AgentMetadata) => void) => void,\n (context: PorterContext, location: AgentLocation) => string | null,\n] {\n const instance = Crann.getInstance(config, storagePrefix);\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\n\n", "import browser from 'webextension-polyfill';\n\nexport const Partition = {\n Instance: 'instance' as const,\n Common: 'common' as const\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};\ntype DerivedInstanceState<T extends AnyConfig> = {\n [P in keyof T as T[P]['partition'] extends 'instance' ? P : never]: T[P]['default'];\n};\ntype DerivedCommonState<T extends AnyConfig> = {\n [P in keyof T as T[P]['partition'] extends 'common' ? P : 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: (callback: (changes: StateUpdate<TConfig>) => void, keys?: Array<keyof TConfig>) => () => void;\n}\n\ntype UseCrann<TConfig extends AnyConfig> = <K extends keyof DerivedState<TConfig>>(\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 (callback: (changes: StateUpdate<TConfig>) => void, key?: keyof DerivedState<TConfig>): number;\n}\n\ntype StateUpdate<TConfig extends AnyConfig> = Partial<DerivedState<TConfig>>;\n\nexport { AnyConfig, ConfigItem, DerivedState, DerivedInstanceState, DerivedCommonState, StateSubscriber, CrannAgent, AgentSubscription, StateUpdate, DerivedState as State, ConnectReturn, UseCrann };\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}", "import { ConfigItem, CrannAgent, DerivedState, StateSubscriber, DerivedInstanceState, DerivedCommonState, ConnectReturn, UseCrann } from \"./model/crann.model\";\nimport { connect as connectPorter } from 'porter-source'\n\nlet crannInstance: unknown = null;\n\nexport function connect<TConfig extends Record<string, ConfigItem<any>>>(config: TConfig, context?: string): ConnectReturn<TConfig> {\n if (crannInstance) {\n return crannInstance as ConnectReturn<TConfig>;\n }\n console.log('Crann connect, connecting porter');\n const [post, setMessages] = connectPorter({ namespace: 'crann' });\n console.log('Crann connect, porter connected (hopefully)');\n let _state = getDerivedState(config);\n let changes: Partial<DerivedState<TConfig>> | null = null;\n const listeners = new Set<StateSubscriber<TConfig>>();\n setMessages({\n stateUpdate: (message) => {\n console.log('Crann, handleMessage, state update message received');\n changes = message.payload.state;\n _state = { ..._state, ...changes };\n if (!!changes) {\n console.log('Crann, handle state update message, notifying listeners: ', listeners);\n listeners.forEach(listener => {\n if (listener.keys === undefined) {\n console.log('Crann, listener keys undefined, calling callback function');\n listener.callback(changes!);\n } else {\n console.log('Crann, checking if we havev a listener match');\n const matchFound = listener.keys.some(key => changes!.hasOwnProperty(key))\n console.log('Crann, state update, matchFound? ', matchFound);\n matchFound && listener.callback(changes!);\n }\n });\n }\n }\n });\n\n console.log('Crann connect, messages set on porter');\n\n const get = () => _state;\n const set = (newState: Partial<DerivedState<TConfig>>) => {\n post({ action: 'setState', payload: { state: newState } });\n }\n const subscribe = (callback: (changes: Partial<DerivedState<TConfig>>) => void, keys?: Array<keyof DerivedState<TConfig>>): () => 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 = (callback: (value: DerivedState<TConfig>[K]) => void) => {\n return subscribe((changes) => {\n if (key in changes) {\n callback(changes[key] as DerivedState<TConfig>[K]);\n }\n }, [key]);\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>>>(config: TConfig): (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 commonState = {} as DerivedCommonState<TConfig>;\n Object.keys(config).forEach(key => {\n const item: ConfigItem<any> = config[key];\n if (item.partition === 'instance') {\n commonState[key as keyof DerivedCommonState<TConfig>] = item.default;\n }\n });\n\n return { ...instanceState, ...commonState } as unknown as (DerivedState<TConfig>);\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["src_exports", "__export", "Crann", "Partition", "Persistence", "connect", "connected", "create", "__toCommonJS", "import_webextension_polyfill", "Partition", "Persistence", "import_porter_source", "deepEqual", "a", "b", "keysA", "keysB", "key", "_Crann", "config", "storagePrefix", "post", "_setMessages", "onConnect", "onDisconnect", "key", "connectionType", "context", "location", "initialInstanceState", "state", "update", "deepEqual", "currentState", "persistence", "value", "browser", "_", "listener", "changes", "agentMeta", "target", "searchKey", "instance", "worker", "itemKey", "item", "instanceItemKey", "instanceState", "Partition", "commonItemKey", "commonState", "local", "session", "combined", "prefixedKey", "Crann", "create", "import_porter_source", "crannInstance", "connect", "config", "context", "post", "setMessages", "connectPorter", "_state", "getDerivedState", "changes", "listeners", "message", "listener", "key", "get", "set", "newState", "subscribe", "callback", "keys", "getValue", "setValue", "value", "subscribeToChanges", "connected", "instanceState", "item", "commonState"]
7
7
  }
package/dist/esm/index.js CHANGED
@@ -1,2 +1,2 @@
1
- import C from"webextension-polyfill";var g={Instance:"instance",Common:"common"},h={Session:"session",Local:"local",None:"none"};import{source as y}from"porter-source";function d(a,t){if(a===t)return!0;if(a==null||typeof a!="object"||t==null||typeof t!="object")return!1;let e=Object.keys(a),n=Object.keys(t);if(e.length!==n.length)return!1;e.sort(),n.sort();for(let i=0;i<e.length;i++){let o=e[i];if(o!==n[i]||!d(a[o],t[o]))return!1}return!0}var S=class{constructor(t,e){this.config=t;this.instances=new Map;this.stateChangeListeners=[];this.storagePrefix="crann_";this.post=()=>{};console.log("Crann constructor"),this.defaultInstanceState=this.initializeInstanceDefault(),this.defaultCommonState=this.commonState=this.initializeCommonDefault(),this.hydrate();let[n,i,o,s]=y("crann");this.post=n,o(({key:r,connectionType:m,context:v,location:p})=>{console.log("Crann porter connect",r,m,v,p),this.addInstance(r),s(({key:l,connectionType:c,context:f,location:u})=>{console.log("Crann porter connect",l,c,f,u),this.removeInstance(l)})}),this.storagePrefix=e!=null?e:this.storagePrefix}async addInstance(t){if(this.instances.has(t))console.warn("Crann instance already exists",t);else{let e={...this.defaultInstanceState};this.instances.set(t,e)}}async removeInstance(t){this.instances.has(t)?this.instances.delete(t):console.warn("Crann instance does not exist",t)}async setCommonState(t){let e={...this.commonState,...t};d(this.commonState,e)||(this.commonState=e,await this.persist(t),this.notify(t))}async setInstanceState(t,e){let n=this.instances.get(t)||this.defaultInstanceState,i={...n,...e};d(n,i)||(this.instances.set(t,i),this.notify(e,t))}async persist(t){for(let e in t||this.commonState){let i=this.config[e].persist||"none",o=t?t[e]:this.commonState[e];switch(i){case"session":await C.storage.session.set({[this.storagePrefix+e]:o});break;case"local":await C.storage.local.set({[this.storagePrefix+e]:o});break;default:break}}}async clear(){this.commonState=this.defaultCommonState,this.instances.forEach((t,e)=>{this.instances.set(e,this.defaultInstanceState)}),await this.persist(),this.notify({})}subscribe(t){this.stateChangeListeners.push(t)}notify(t,e){let n=e?this.get(e):this.get();this.stateChangeListeners.forEach(i=>i(n,t,e)),e?this.post({action:"stateUpdate",payload:{state:t}},e):this.instances.forEach((i,o)=>{this.post({action:"stateUpdate",payload:{state:t}},o)})}get(t){return t?{...this.commonState,...this.instances.get(t)}:{...this.commonState}}async set(t,e){let n={},i={};for(let o in t){let s=this.config[o];if(s.partition==="instance"){let r=o,m=t;n[r]=m[r]}else if(!s.partition||s.partition===g.Common){let r=o,m=t;i[r]=m[r]}}e&&this.setInstanceState(e,n),this.setCommonState(i)}async hydrate(){let t=await C.storage.local.get(null),e=await C.storage.session.get(null),n={...t,...e},i={};for(let o in n){let s=this.removePrefix(o);if(this.config.hasOwnProperty(s)){let r=n[s];i[s]=r}}this.commonState={...this.defaultCommonState,...i}}removePrefix(t){return t.startsWith(this.storagePrefix)?t.replace(this.storagePrefix,""):t}initializeInstanceDefault(){let t={};return Object.keys(this.config).forEach(e=>{let n=this.config[e];n.partition==="instance"&&(t[e]=n.default)}),t}initializeCommonDefault(){let t={};return Object.keys(this.config).forEach(e=>{let n=this.config[e];n.partition===g.Common&&(t[e]=n.default)}),t}};function D(a,t){return new S(a,t)}import{connect as I}from"porter-source";function b(a,t){let[e,n]=I({namespace:"crann"}),i=P(a),o=null,s=new Map,r=0;return n({stateUpdate:c=>{o=c.payload.state,i={...i,...o},o&&s.forEach(f=>{(f.keys===void 0||f.keys.some(T=>o.hasOwnProperty(T)))&&f.callback(o)})}}),{get:()=>i,set:c=>{e({action:"setState",payload:{state:c}})},subscribe:(c,f)=>(s.set(++r,{keys:f,callback:c}),r),unsubscribe:c=>{s.delete(c)}}}function P(a){let t={};Object.keys(a).forEach(n=>{let i=a[n];i.partition==="instance"&&(t[n]=i.default)});let e={};return Object.keys(a).forEach(n=>{let i=a[n];i.partition==="instance"&&(e[n]=i.default)}),{...t,...e}}export{S as Crann,g as Partition,h as Persistence,b as connect,D as create};
1
+ import S from"webextension-polyfill";var m={Instance:"instance",Common:"common"},I={Session:"session",Local:"local",None:"none"};import{source as b,getMetadata as x,getKey as k,getTarget as A}from"porter-source";function v(s,t){if(s===t)return!0;if(s==null||typeof s!="object"||t==null||typeof t!="object")return!1;let e=Object.keys(s),n=Object.keys(t);if(e.length!==n.length)return!1;e.sort(),n.sort();for(let i=0;i<e.length;i++){let o=e[i];if(o!==n[i]||!v(s[o],t[o]))return!1}return!0}var d=class d{constructor(t,e){this.config=t;this.instances=new Map;this.stateChangeListeners=[];this.storagePrefix="crann_";this.post=()=>{};this.defaultInstanceState=this.initializeInstanceDefault(),this.defaultCommonState=this.commonState=this.initializeCommonDefault(),this.hydrate();let[n,i,o,a]=b("crann");this.post=n,o(({key:r,connectionType:g,context:p,location:P})=>{this.addInstance(r),a(({key:h,connectionType:c,context:f,location:C})=>{this.removeInstance(h)})}),this.storagePrefix=e!=null?e:this.storagePrefix}static getInstance(t,e){return d.instance||(d.instance=new d(t,e)),d.instance}async addInstance(t){if(!this.instances.has(t)){let e={...this.defaultInstanceState};this.instances.set(t,e)}}async removeInstance(t){this.instances.has(t)&&this.instances.delete(t)}async setCommonState(t){let e={...this.commonState,...t};v(this.commonState,e)||(this.commonState=e,await this.persist(t),this.notify(t))}async setInstanceState(t,e){let n=this.instances.get(t)||this.defaultInstanceState,i={...n,...e};v(n,i)||(this.instances.set(t,i),this.notify(e,t))}async persist(t){for(let e in t||this.commonState){let i=this.config[e].persist||"none",o=t?t[e]:this.commonState[e];switch(i){case"session":await S.storage.session.set({[this.storagePrefix+e]:o});break;case"local":await S.storage.local.set({[this.storagePrefix+e]:o});break;default:break}}}async clear(){this.commonState=this.defaultCommonState,this.instances.forEach((t,e)=>{this.instances.set(e,this.defaultInstanceState)}),await this.persist(),this.notify({})}subscribe(t){this.stateChangeListeners.push(t)}notify(t,e){let n=e?x(e):void 0,i=n?A(n):void 0,o=e?this.get(e):this.get();this.stateChangeListeners.forEach(a=>a(o,t,n||void 0)),i?this.post({action:"stateUpdate",payload:{state:t}},i):this.instances.forEach((a,r)=>{this.post({action:"stateUpdate",payload:{state:t}},r)})}get(t){return t?{...this.commonState,...this.instances.get(t)}:{...this.commonState}}findInstance(t,e){let n=k({context:t,...e});for(let[i,o]of this.instances)if(i===n)return i;return null}async set(t,e){let n={},i={};for(let o in t){let a=this.config[o];if(a.partition==="instance"){let r=o,g=t;n[r]=g[r]}else if(!a.partition||a.partition===m.Common){let r=o,g=t;i[r]=g[r]}}e&&this.setInstanceState(e,n),this.setCommonState(i)}async hydrate(){let t=await S.storage.local.get(null),e=await S.storage.session.get(null),n={...t,...e},i={};for(let o in n){let a=this.removePrefix(o);if(this.config.hasOwnProperty(a)){let r=n[a];i[a]=r}}this.commonState={...this.defaultCommonState,...i}}removePrefix(t){return t.startsWith(this.storagePrefix)?t.replace(this.storagePrefix,""):t}initializeInstanceDefault(){let t={};return Object.keys(this.config).forEach(e=>{let n=this.config[e];n.partition==="instance"&&(t[e]=n.default)}),t}initializeCommonDefault(){let t={};return Object.keys(this.config).forEach(e=>{let n=this.config[e];n.partition===m.Common&&(t[e]=n.default)}),t}};d.instance=null;var u=d;function w(s,t){let e=u.getInstance(s,t);return[e.get.bind(e),e.set.bind(e),e.subscribe.bind(e),e.findInstance.bind(e)]}import{connect as K}from"porter-source";var l=null;function U(s,t){if(l)return l;let[e,n]=K({namespace:"crann"}),i=R(s),o=null,a=new Set;n({stateUpdate:c=>{o=c.payload.state,i={...i,...o},o&&a.forEach(f=>{(f.keys===void 0||f.keys.some(T=>o.hasOwnProperty(T)))&&f.callback(o)})}});let r=()=>i,g=c=>{e({action:"setState",payload:{state:c}})},p=(c,f)=>{let C={keys:f,callback:c};return a.add(C),()=>{a.delete(C)}};return l=[c=>{let f=()=>r()[c],C=y=>g({[c]:y}),T=y=>p(D=>{c in D&&y(D[c])},[c]);return[f(),C,T]},r,g,p],l}function M(){return l!==null}function R(s){let t={};Object.keys(s).forEach(n=>{let i=s[n];i.partition==="instance"&&(t[n]=i.default)});let e={};return Object.keys(s).forEach(n=>{let i=s[n];i.partition==="instance"&&(e[n]=i.default)}),{...t,...e}}export{u as Crann,m as Partition,I as Persistence,U as connect,M as connected,w as create};
2
2
  //# 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/crannAgent.ts"],
4
- "sourcesContent": ["import browser from 'webextension-polyfill';\nimport { DerivedInstanceState, DerivedCommonState, ConfigItem, DerivedState, Partition, CrannAgent, StateSubscriber } from './model/crann.model';\nimport { source, } from 'porter-source';\nimport { deepEqual } from './utils/deepEqual';\nimport { AgentLocation, AgentMetadata } from 'porter-source/dist/types/porter.model';\n\nexport class Crann<TConfig extends Record<string, ConfigItem<any>>> {\n private instances: Map<string, DerivedInstanceState<TConfig>> = new Map();\n private defaultCommonState: DerivedCommonState<TConfig>;\n private defaultInstanceState: DerivedInstanceState<TConfig>;\n private commonState: DerivedCommonState<TConfig>;\n private stateChangeListeners: Array<(state: (DerivedCommonState<TConfig>) | (DerivedCommonState<TConfig> & DerivedInstanceState<TConfig>), changes: Partial<DerivedCommonState<TConfig> & DerivedInstanceState<TConfig>>, key?: string) => void> = [];\n private storagePrefix = 'crann_';\n private post: (message: any, contextOrKey: string, location?: Partial<AgentLocation>) => void = () => { };\n\n constructor(private config: TConfig, storagePrefix?: string) {\n console.log('Crann constructor');\n this.defaultInstanceState = this.initializeInstanceDefault();\n this.defaultCommonState = this.commonState = this.initializeCommonDefault();\n this.hydrate();\n const [post, _setMessages, onConnect, onDisconnect] = source('crann');\n this.post = post;\n onConnect(({ key, connectionType, context, location }) => {\n console.log('Crann porter connect', key, connectionType, context, location);\n this.addInstance(key);\n onDisconnect(({ key, connectionType, context, location }) => {\n console.log('Crann porter connect', key, connectionType, context, location);\n this.removeInstance(key);\n });\n });\n this.storagePrefix = storagePrefix ?? this.storagePrefix;\n }\n\n private async addInstance(key: string): Promise<void> {\n if (!this.instances.has(key)) {\n const initialInstanceState = { ...this.defaultInstanceState } as DerivedInstanceState<TConfig>;\n this.instances.set(key, initialInstanceState);\n } else {\n console.warn('Crann instance already exists', key);\n }\n }\n\n private async removeInstance(key: string): Promise<void> {\n if (this.instances.has(key)) {\n this.instances.delete(key);\n } else {\n console.warn('Crann instance does not exist', key);\n }\n }\n\n public async setCommonState(state: Partial<DerivedCommonState<TConfig>>): Promise<void> {\n const update = { ...this.commonState, ...state };\n if (!deepEqual(this.commonState, update)) {\n this.commonState = update;\n await this.persist(state);\n this.notify(state as Partial<DerivedState<TConfig>>);\n }\n }\n\n public async setInstanceState(key: string, state: Partial<DerivedInstanceState<TConfig>>): Promise<void> {\n const currentState = this.instances.get(key) || this.defaultInstanceState;\n const update = { ...currentState, ...state };\n if (!deepEqual(currentState, update)) {\n this.instances.set(key, update);\n this.notify(state as Partial<DerivedState<TConfig>>, key);\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(state?: Partial<DerivedCommonState<TConfig>>): Promise<void> {\n for (const key in (state || this.commonState)) {\n const item = this.config[key] as ConfigItem<any>;\n const persistence = item.persist || 'none';\n const value = state ? state[key as keyof DerivedCommonState<TConfig>] : this.commonState[key];\n switch (persistence) {\n case 'session':\n await browser.storage.session.set({ [this.storagePrefix + (key as string)]: value });\n break;\n case 'local':\n await browser.storage.local.set({ [this.storagePrefix + (key as string)]: value });\n break;\n default:\n break;\n }\n }\n }\n\n public async clear(): Promise<void> {\n this.commonState = this.defaultCommonState;\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(listener: (state: (DerivedCommonState<TConfig>) | (DerivedInstanceState<TConfig> & DerivedCommonState<TConfig>), changes: Partial<DerivedInstanceState<TConfig> & DerivedCommonState<TConfig>>, key?: string) => void): void {\n this.stateChangeListeners.push(listener);\n }\n\n private notify(changes: Partial<DerivedCommonState<TConfig> & DerivedInstanceState<TConfig>>, key?: string): void {\n const state = key ? this.get(key) : this.get();\n this.stateChangeListeners.forEach(listener => listener(state, changes, key));\n if (key) {\n this.post({ action: 'stateUpdate', payload: { state: changes } }, key);\n } else {\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(): DerivedCommonState<TConfig>;\n public get(key: string): DerivedInstanceState<TConfig> & DerivedCommonState<TConfig>;\n public get(key?: string): ((DerivedInstanceState<TConfig> & DerivedCommonState<TConfig>) | DerivedCommonState<TConfig>) {\n if (!key) {\n return { ...this.commonState, ...{} as DerivedInstanceState<TConfig> };\n }\n return { ...this.commonState, ...this.instances.get(key) };\n }\n\n public async set(state: Partial<DerivedCommonState<TConfig>>): Promise<void>\n public async set(state: Partial<DerivedInstanceState<TConfig> & DerivedCommonState<TConfig>>, key: string): Promise<void>\n public async set(state: Partial<DerivedInstanceState<TConfig> | DerivedCommonState<TConfig>>, key?: string): Promise<void> {\n const instance = {} as Partial<DerivedInstanceState<TConfig>>;\n const worker = {} as Partial<DerivedCommonState<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.Common) {\n const commonItemKey = itemKey as keyof DerivedCommonState<TConfig>;\n const commonState = state as Partial<DerivedCommonState<TConfig>>;\n worker[commonItemKey] = commonState[commonItemKey]!;\n }\n }\n if (key) this.setInstanceState(key, instance);\n this.setCommonState(worker);\n }\n\n private async hydrate(): Promise<void> {\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<DerivedCommonState<TConfig>> = {}; // Cast update as Partial<DerivedState<TConfig>>\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 DerivedCommonState<TConfig>] = value;\n }\n }\n this.commonState = { ...this.defaultCommonState, ...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 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 initializeCommonDefault(): DerivedCommonState<TConfig> {\n const commonState: any = {};\n Object.keys(this.config).forEach(key => {\n const item: ConfigItem<any> = this.config[key];\n if (item.partition === Partition.Common) {\n commonState[key] = item.default;\n }\n });\n return commonState;\n }\n}\n\n\nexport function create<TConfig extends Record<string, ConfigItem<any>>>(config: TConfig, storagePrefix?: string): Crann<TConfig> {\n return new Crann(config, storagePrefix);\n}\n\n", "import browser from 'webextension-polyfill';\n\nexport const Partition = {\n Instance: 'instance' as const,\n Common: 'common' as const\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\n// export type Config = typeof StateConfig;\n\ntype DerivedState<T extends Record<string, ConfigItem<any>>> = {\n [P in keyof T]: T[P]['default'];\n};\ntype DerivedInstanceState<T extends Record<string, ConfigItem<any>>> = {\n [P in keyof T as T[P]['partition'] extends 'instance' ? P : never]: T[P]['default'];\n};\ntype DerivedCommonState<T extends Record<string, ConfigItem<any>>> = {\n [P in keyof T as T[P]['partition'] extends 'common' ? P : never]: T[P]['default'];\n};\n\ntype StateSubscriber<TConfig extends Record<string, ConfigItem<any>>> = {\n keys?: Array<keyof DerivedState<TConfig>>;\n callback: (changes: StateUpdate<TConfig>) => void;\n}\n\ntype CrannAgent<TConfig extends Record<string, ConfigItem<any>>> = {\n get: () => DerivedCommonState<TConfig> & DerivedInstanceState<TConfig>;\n set: (update: StateUpdate<TConfig>) => void;\n subscribe: (callback: (changes: StateUpdate<TConfig>) => void, keys?: Array<keyof TConfig>) => number;\n unsubscribe: (id: number) => void;\n}\n\ntype AgentSubscription<TConfig extends Record<string, ConfigItem<any>>> = {\n (callback: (changes: StateUpdate<TConfig>) => void, key?: keyof DerivedState<TConfig>): number;\n}\n\ntype StateUpdate<TConfig extends Record<string, ConfigItem<any>>> = Partial<DerivedState<TConfig>>;\n\nexport { ConfigItem, DerivedState, DerivedInstanceState, DerivedCommonState, StateSubscriber, CrannAgent, AgentSubscription, StateUpdate, DerivedState as State };\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}", "import { ConfigItem, CrannAgent, DerivedState, StateSubscriber, DerivedInstanceState, DerivedCommonState } from \"./model/crann.model\";\nimport { connect as connectPorter } from 'porter-source'\n\nexport function connect<TConfig extends Record<string, ConfigItem<any>>>(config: TConfig, context?: string): CrannAgent<TConfig> {\n const [post, setMessages] = connectPorter({ namespace: 'crann' });\n let _state = getDerivedState(config);\n let changes: Partial<DerivedState<TConfig>> | null = null;\n const listeners = new Map<number, StateSubscriber<TConfig>>();\n let listenerId = 0;\n setMessages({\n stateUpdate: (message) => {\n changes = message.payload.state;\n _state = { ..._state, ...changes };\n if (!!changes) {\n listeners.forEach(listener => {\n if (listener.keys === undefined) {\n listener.callback(changes!);\n } else {\n const matchFound = listener.keys.some(key => changes!.hasOwnProperty(key))\n matchFound && listener.callback(changes!);\n }\n });\n }\n }\n });\n\n const get = () => _state;\n const set = (newState: Partial<DerivedState<TConfig>>) => {\n post({ action: 'setState', payload: { state: newState } });\n }\n const subscribe = (callback: (changes: Partial<DerivedState<TConfig>>) => void, keys?: Array<keyof DerivedState<TConfig>>): number => {\n listeners.set(++listenerId, { keys, callback });\n return listenerId;\n }\n const unsubscribe = (id: number) => {\n listeners.delete(id);\n }\n return { get, set, subscribe, unsubscribe };\n}\n\nfunction getDerivedState<TConfig extends Record<string, ConfigItem<any>>>(config: TConfig): (DerivedInstanceState<TConfig> & DerivedCommonState<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 commonState = {} as DerivedCommonState<TConfig>;\n Object.keys(config).forEach(key => {\n const item: ConfigItem<any> = config[key];\n if (item.partition === 'instance') {\n commonState[key as keyof DerivedCommonState<TConfig>] = item.default;\n }\n });\n\n return { ...instanceState, ...commonState } as (DerivedInstanceState<TConfig> & DerivedCommonState<TConfig>);\n}\n"],
5
- "mappings": "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",
6
- "names": ["browser", "Partition", "Persistence", "source", "deepEqual", "b", "keysA", "keysB", "key", "Crann", "config", "storagePrefix", "post", "_setMessages", "onConnect", "onDisconnect", "source", "key", "connectionType", "context", "location", "initialInstanceState", "state", "update", "deepEqual", "currentState", "persistence", "value", "browser", "_", "listener", "changes", "instance", "worker", "itemKey", "item", "instanceItemKey", "instanceState", "Partition", "commonItemKey", "commonState", "local", "session", "combined", "prefixedKey", "create", "connectPorter", "connect", "config", "context", "post", "setMessages", "_state", "getDerivedState", "changes", "listeners", "listenerId", "message", "listener", "key", "newState", "callback", "keys", "id", "instanceState", "item", "commonState"]
4
+ "sourcesContent": ["import browser from 'webextension-polyfill';\nimport { DerivedInstanceState, DerivedCommonState, ConfigItem, DerivedState, Partition } from './model/crann.model';\nimport { source, getMetadata, getKey, getTarget } from 'porter-source';\nimport { deepEqual } from './utils/deepEqual';\nimport { AgentLocation, AgentMetadata, Message, PorterContext, PostTarget } from 'porter-source/dist/types/porter.model';\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 defaultCommonState: DerivedCommonState<TConfig>;\n private defaultInstanceState: DerivedInstanceState<TConfig>;\n private commonState: DerivedCommonState<TConfig>;\n private stateChangeListeners: Array<(state: (DerivedInstanceState<TConfig> | DerivedState<TConfig>), changes: Partial<DerivedCommonState<TConfig> & DerivedInstanceState<TConfig>>, agent?: AgentMetadata) => void> = [];\n private storagePrefix = 'crann_';\n private post: (message: Message<any>, target?: PostTarget) => void = () => { };\n\n constructor(private config: TConfig, storagePrefix?: string) {\n console.log('Crann constructor');\n this.defaultInstanceState = this.initializeInstanceDefault();\n this.defaultCommonState = this.commonState = this.initializeCommonDefault();\n this.hydrate();\n const [post, _setMessages, onConnect, onDisconnect] = source('crann');\n this.post = post;\n onConnect(({ key, connectionType, context, location }) => {\n console.log('Crann porter connect', key, connectionType, context, location);\n this.addInstance(key);\n onDisconnect(({ key, connectionType, context, location }) => {\n console.log('Crann porter connect', key, connectionType, context, location);\n this.removeInstance(key);\n });\n });\n this.storagePrefix = storagePrefix ?? this.storagePrefix;\n }\n\n\n public static getInstance<TConfig extends Record<string, ConfigItem<any>>>(config: TConfig, storagePrefix?: string): Crann<TConfig> {\n if (!Crann.instance) {\n Crann.instance = new Crann(config, storagePrefix);\n }\n return Crann.instance;\n }\n\n private async addInstance(key: string): Promise<void> {\n if (!this.instances.has(key)) {\n const initialInstanceState = { ...this.defaultInstanceState } as DerivedInstanceState<TConfig>;\n this.instances.set(key, initialInstanceState);\n } else {\n console.warn('Crann instance already exists', key);\n }\n }\n\n private async removeInstance(key: string): Promise<void> {\n if (this.instances.has(key)) {\n this.instances.delete(key);\n } else {\n console.warn('Crann instance does not exist', key);\n }\n }\n\n public async setCommonState(state: Partial<DerivedCommonState<TConfig>>): Promise<void> {\n const update = { ...this.commonState, ...state };\n if (!deepEqual(this.commonState, update)) {\n this.commonState = update;\n await this.persist(state);\n this.notify(state as Partial<DerivedState<TConfig>>);\n }\n }\n\n public async setInstanceState(key: string, state: Partial<DerivedInstanceState<TConfig>>): Promise<void> {\n const currentState = this.instances.get(key) || this.defaultInstanceState;\n const update = { ...currentState, ...state };\n if (!deepEqual(currentState, update)) {\n this.instances.set(key, update);\n this.notify(state as Partial<DerivedState<TConfig>>, key);\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(state?: Partial<DerivedCommonState<TConfig>>): Promise<void> {\n for (const key in (state || this.commonState)) {\n const item = this.config[key] as ConfigItem<any>;\n const persistence = item.persist || 'none';\n const value = state ? state[key as keyof DerivedCommonState<TConfig>] : this.commonState[key];\n switch (persistence) {\n case 'session':\n await browser.storage.session.set({ [this.storagePrefix + (key as string)]: value });\n break;\n case 'local':\n await browser.storage.local.set({ [this.storagePrefix + (key as string)]: value });\n break;\n default:\n break;\n }\n }\n }\n\n public async clear(): Promise<void> {\n this.commonState = this.defaultCommonState;\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(listener: (state: (DerivedInstanceState<TConfig> | DerivedState<TConfig>), changes: Partial<DerivedInstanceState<TConfig> & DerivedCommonState<TConfig>>, agent?: AgentMetadata) => void): void {\n this.stateChangeListeners.push(listener);\n }\n\n private notify(changes: Partial<DerivedState<TConfig>>, key?: string): void {\n const agentMeta = key ? getMetadata(key) : undefined;\n const target = agentMeta ? getTarget(agentMeta) : undefined;\n const state = key ? this.get(key) : this.get();\n this.stateChangeListeners.forEach(listener => listener(state, changes, agentMeta || undefined));\n if (target) {\n this.post({ action: 'stateUpdate', payload: { state: changes } }, target);\n } else {\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(key: string): DerivedInstanceState<TConfig> & DerivedCommonState<TConfig>;\n public get(key?: string): (DerivedCommonState<TConfig> | DerivedState<TConfig>) {\n if (!key) {\n return { ...this.commonState, ...{} as DerivedInstanceState<TConfig> };\n }\n return { ...this.commonState, ...this.instances.get(key) };\n }\n\n public findInstance(context: PorterContext, location: AgentLocation): string | null {\n // Todo: This feels like too-tight coupleing between porter and crann. Should be a better way.\n const searchKey = getKey({ context, ...location })\n for (const [key, instance] of this.instances) {\n if (key === searchKey) {\n console.log('Crann found instance for key: ', key);\n return key\n }\n }\n return null;\n }\n\n public async set(state: Partial<DerivedCommonState<TConfig>>): Promise<void>\n public async set(state: Partial<DerivedInstanceState<TConfig> & DerivedCommonState<TConfig>>, key: string): Promise<void>\n public async set(state: Partial<DerivedInstanceState<TConfig> | DerivedCommonState<TConfig>>, key?: string): Promise<void> {\n const instance = {} as Partial<DerivedInstanceState<TConfig>>;\n const worker = {} as Partial<DerivedCommonState<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.Common) {\n const commonItemKey = itemKey as keyof DerivedCommonState<TConfig>;\n const commonState = state as Partial<DerivedCommonState<TConfig>>;\n worker[commonItemKey] = commonState[commonItemKey]!;\n }\n }\n if (key) this.setInstanceState(key, instance);\n this.setCommonState(worker);\n }\n\n private async hydrate(): Promise<void> {\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<DerivedCommonState<TConfig>> = {}; // Cast update as Partial<DerivedState<TConfig>>\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 DerivedCommonState<TConfig>] = value;\n }\n }\n this.commonState = { ...this.defaultCommonState, ...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 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 initializeCommonDefault(): DerivedCommonState<TConfig> {\n const commonState: any = {};\n Object.keys(this.config).forEach(key => {\n const item: ConfigItem<any> = this.config[key];\n if (item.partition === Partition.Common) {\n commonState[key] = item.default;\n }\n });\n return commonState;\n }\n}\n\n\nexport function create<TConfig extends Record<string, ConfigItem<any>>>(config: TConfig, storagePrefix?: string): [\n (key?: string) => (DerivedState<TConfig>),\n (state: Partial<DerivedInstanceState<TConfig> & DerivedCommonState<TConfig>>, key?: string) => Promise<void>,\n (listener: (state: (DerivedInstanceState<TConfig> | DerivedState<TConfig>), changes: Partial<DerivedInstanceState<TConfig> & DerivedCommonState<TConfig>>, agent?: AgentMetadata) => void) => void,\n (context: PorterContext, location: AgentLocation) => string | null,\n] {\n const instance = Crann.getInstance(config, storagePrefix);\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\n\n", "import browser from 'webextension-polyfill';\n\nexport const Partition = {\n Instance: 'instance' as const,\n Common: 'common' as const\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};\ntype DerivedInstanceState<T extends AnyConfig> = {\n [P in keyof T as T[P]['partition'] extends 'instance' ? P : never]: T[P]['default'];\n};\ntype DerivedCommonState<T extends AnyConfig> = {\n [P in keyof T as T[P]['partition'] extends 'common' ? P : 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: (callback: (changes: StateUpdate<TConfig>) => void, keys?: Array<keyof TConfig>) => () => void;\n}\n\ntype UseCrann<TConfig extends AnyConfig> = <K extends keyof DerivedState<TConfig>>(\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 (callback: (changes: StateUpdate<TConfig>) => void, key?: keyof DerivedState<TConfig>): number;\n}\n\ntype StateUpdate<TConfig extends AnyConfig> = Partial<DerivedState<TConfig>>;\n\nexport { AnyConfig, ConfigItem, DerivedState, DerivedInstanceState, DerivedCommonState, StateSubscriber, CrannAgent, AgentSubscription, StateUpdate, DerivedState as State, ConnectReturn, UseCrann };\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}", "import { ConfigItem, CrannAgent, DerivedState, StateSubscriber, DerivedInstanceState, DerivedCommonState, ConnectReturn, UseCrann } from \"./model/crann.model\";\nimport { connect as connectPorter } from 'porter-source'\n\nlet crannInstance: unknown = null;\n\nexport function connect<TConfig extends Record<string, ConfigItem<any>>>(config: TConfig, context?: string): ConnectReturn<TConfig> {\n if (crannInstance) {\n return crannInstance as ConnectReturn<TConfig>;\n }\n console.log('Crann connect, connecting porter');\n const [post, setMessages] = connectPorter({ namespace: 'crann' });\n console.log('Crann connect, porter connected (hopefully)');\n let _state = getDerivedState(config);\n let changes: Partial<DerivedState<TConfig>> | null = null;\n const listeners = new Set<StateSubscriber<TConfig>>();\n setMessages({\n stateUpdate: (message) => {\n console.log('Crann, handleMessage, state update message received');\n changes = message.payload.state;\n _state = { ..._state, ...changes };\n if (!!changes) {\n console.log('Crann, handle state update message, notifying listeners: ', listeners);\n listeners.forEach(listener => {\n if (listener.keys === undefined) {\n console.log('Crann, listener keys undefined, calling callback function');\n listener.callback(changes!);\n } else {\n console.log('Crann, checking if we havev a listener match');\n const matchFound = listener.keys.some(key => changes!.hasOwnProperty(key))\n console.log('Crann, state update, matchFound? ', matchFound);\n matchFound && listener.callback(changes!);\n }\n });\n }\n }\n });\n\n console.log('Crann connect, messages set on porter');\n\n const get = () => _state;\n const set = (newState: Partial<DerivedState<TConfig>>) => {\n post({ action: 'setState', payload: { state: newState } });\n }\n const subscribe = (callback: (changes: Partial<DerivedState<TConfig>>) => void, keys?: Array<keyof DerivedState<TConfig>>): () => 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 = (callback: (value: DerivedState<TConfig>[K]) => void) => {\n return subscribe((changes) => {\n if (key in changes) {\n callback(changes[key] as DerivedState<TConfig>[K]);\n }\n }, [key]);\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>>>(config: TConfig): (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 commonState = {} as DerivedCommonState<TConfig>;\n Object.keys(config).forEach(key => {\n const item: ConfigItem<any> = config[key];\n if (item.partition === 'instance') {\n commonState[key as keyof DerivedCommonState<TConfig>] = item.default;\n }\n });\n\n return { ...instanceState, ...commonState } as unknown as (DerivedState<TConfig>);\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["browser", "Partition", "Persistence", "source", "getMetadata", "getKey", "getTarget", "deepEqual", "a", "b", "keysA", "keysB", "key", "_Crann", "config", "storagePrefix", "post", "_setMessages", "onConnect", "onDisconnect", "source", "key", "connectionType", "context", "location", "initialInstanceState", "state", "update", "deepEqual", "currentState", "persistence", "value", "browser", "_", "listener", "changes", "agentMeta", "getMetadata", "target", "getTarget", "searchKey", "getKey", "instance", "worker", "itemKey", "item", "instanceItemKey", "instanceState", "Partition", "commonItemKey", "commonState", "local", "session", "combined", "prefixedKey", "Crann", "create", "connectPorter", "crannInstance", "connect", "config", "context", "post", "setMessages", "_state", "getDerivedState", "changes", "listeners", "message", "listener", "key", "get", "set", "newState", "subscribe", "callback", "keys", "getValue", "setValue", "value", "subscribeToChanges", "connected", "instanceState", "item", "commonState"]
7
7
  }
@@ -1,6 +1,8 @@
1
- import { DerivedInstanceState, DerivedCommonState, ConfigItem } from './model/crann.model';
1
+ import { DerivedInstanceState, DerivedCommonState, ConfigItem, DerivedState } from './model/crann.model';
2
+ import { AgentLocation, AgentMetadata, PorterContext } from 'porter-source/dist/types/porter.model';
2
3
  export declare class Crann<TConfig extends Record<string, ConfigItem<any>>> {
3
4
  private config;
5
+ private static instance;
4
6
  private instances;
5
7
  private defaultCommonState;
6
8
  private defaultInstanceState;
@@ -9,16 +11,18 @@ export declare class Crann<TConfig extends Record<string, ConfigItem<any>>> {
9
11
  private storagePrefix;
10
12
  private post;
11
13
  constructor(config: TConfig, storagePrefix?: string);
14
+ static getInstance<TConfig extends Record<string, ConfigItem<any>>>(config: TConfig, storagePrefix?: string): Crann<TConfig>;
12
15
  private addInstance;
13
16
  private removeInstance;
14
17
  setCommonState(state: Partial<DerivedCommonState<TConfig>>): Promise<void>;
15
18
  setInstanceState(key: string, state: Partial<DerivedInstanceState<TConfig>>): Promise<void>;
16
19
  private persist;
17
20
  clear(): Promise<void>;
18
- subscribe(listener: (state: (DerivedCommonState<TConfig>) | (DerivedInstanceState<TConfig> & DerivedCommonState<TConfig>), changes: Partial<DerivedInstanceState<TConfig> & DerivedCommonState<TConfig>>, key?: string) => void): void;
21
+ subscribe(listener: (state: (DerivedInstanceState<TConfig> | DerivedState<TConfig>), changes: Partial<DerivedInstanceState<TConfig> & DerivedCommonState<TConfig>>, agent?: AgentMetadata) => void): void;
19
22
  private notify;
20
- get(): DerivedCommonState<TConfig>;
23
+ get(): DerivedState<TConfig>;
21
24
  get(key: string): DerivedInstanceState<TConfig> & DerivedCommonState<TConfig>;
25
+ findInstance(context: PorterContext, location: AgentLocation): string | null;
22
26
  set(state: Partial<DerivedCommonState<TConfig>>): Promise<void>;
23
27
  set(state: Partial<DerivedInstanceState<TConfig> & DerivedCommonState<TConfig>>, key: string): Promise<void>;
24
28
  private hydrate;
@@ -26,4 +30,9 @@ export declare class Crann<TConfig extends Record<string, ConfigItem<any>>> {
26
30
  private initializeInstanceDefault;
27
31
  private initializeCommonDefault;
28
32
  }
29
- export declare function create<TConfig extends Record<string, ConfigItem<any>>>(config: TConfig, storagePrefix?: string): Crann<TConfig>;
33
+ export declare function create<TConfig extends Record<string, ConfigItem<any>>>(config: TConfig, storagePrefix?: string): [
34
+ (key?: string) => (DerivedState<TConfig>),
35
+ (state: Partial<DerivedInstanceState<TConfig> & DerivedCommonState<TConfig>>, key?: string) => Promise<void>,
36
+ (listener: (state: (DerivedInstanceState<TConfig> | DerivedState<TConfig>), changes: Partial<DerivedInstanceState<TConfig> & DerivedCommonState<TConfig>>, agent?: AgentMetadata) => void) => void,
37
+ (context: PorterContext, location: AgentLocation) => string | null
38
+ ];
@@ -1,2 +1,3 @@
1
- import { ConfigItem, CrannAgent } from "./model/crann.model";
2
- export declare function connect<TConfig extends Record<string, ConfigItem<any>>>(config: TConfig, context?: string): CrannAgent<TConfig>;
1
+ import { ConfigItem, ConnectReturn } from "./model/crann.model";
2
+ export declare function connect<TConfig extends Record<string, ConfigItem<any>>>(config: TConfig, context?: string): ConnectReturn<TConfig>;
3
+ export declare function connected(): boolean;
@@ -1,3 +1,3 @@
1
1
  export { create, Crann } from './crann';
2
- export { connect } from './crannAgent';
2
+ export { connect, connected } from './crannAgent';
3
3
  export { CrannAgent, StateUpdate, State, Partition, Persistence } from './model/crann.model';
@@ -12,27 +12,38 @@ type ConfigItem<T> = {
12
12
  partition?: typeof Partition[keyof typeof Partition];
13
13
  persist?: typeof Persistence[keyof typeof Persistence];
14
14
  };
15
- type DerivedState<T extends Record<string, ConfigItem<any>>> = {
15
+ type AnyConfig = Record<string, ConfigItem<any>>;
16
+ type DerivedState<T extends AnyConfig> = {
16
17
  [P in keyof T]: T[P]['default'];
17
18
  };
18
- type DerivedInstanceState<T extends Record<string, ConfigItem<any>>> = {
19
+ type DerivedInstanceState<T extends AnyConfig> = {
19
20
  [P in keyof T as T[P]['partition'] extends 'instance' ? P : never]: T[P]['default'];
20
21
  };
21
- type DerivedCommonState<T extends Record<string, ConfigItem<any>>> = {
22
+ type DerivedCommonState<T extends AnyConfig> = {
22
23
  [P in keyof T as T[P]['partition'] extends 'common' ? P : never]: T[P]['default'];
23
24
  };
24
- type StateSubscriber<TConfig extends Record<string, ConfigItem<any>>> = {
25
+ type StateSubscriber<TConfig extends AnyConfig> = {
25
26
  keys?: Array<keyof DerivedState<TConfig>>;
26
27
  callback: (changes: StateUpdate<TConfig>) => void;
27
28
  };
28
- type CrannAgent<TConfig extends Record<string, ConfigItem<any>>> = {
29
- get: () => DerivedCommonState<TConfig> & DerivedInstanceState<TConfig>;
29
+ type CrannAgent<TConfig extends AnyConfig> = {
30
+ get: () => DerivedState<TConfig>;
30
31
  set: (update: StateUpdate<TConfig>) => void;
31
- subscribe: (callback: (changes: StateUpdate<TConfig>) => void, keys?: Array<keyof TConfig>) => number;
32
- unsubscribe: (id: number) => void;
33
- };
34
- type AgentSubscription<TConfig extends Record<string, ConfigItem<any>>> = {
32
+ subscribe: (callback: (changes: StateUpdate<TConfig>) => void, keys?: Array<keyof TConfig>) => () => void;
33
+ };
34
+ type UseCrann<TConfig extends AnyConfig> = <K extends keyof DerivedState<TConfig>>(key: K) => [
35
+ DerivedState<TConfig>[K],
36
+ (value: DerivedState<TConfig>[K]) => void,
37
+ (callback: (value: DerivedState<TConfig>[K]) => void) => () => void
38
+ ];
39
+ type ConnectReturn<TConfig extends AnyConfig> = [
40
+ UseCrann<TConfig>,
41
+ CrannAgent<TConfig>['get'],
42
+ CrannAgent<TConfig>['set'],
43
+ CrannAgent<TConfig>['subscribe']
44
+ ];
45
+ type AgentSubscription<TConfig extends AnyConfig> = {
35
46
  (callback: (changes: StateUpdate<TConfig>) => void, key?: keyof DerivedState<TConfig>): number;
36
47
  };
37
- type StateUpdate<TConfig extends Record<string, ConfigItem<any>>> = Partial<DerivedState<TConfig>>;
38
- export { ConfigItem, DerivedState, DerivedInstanceState, DerivedCommonState, StateSubscriber, CrannAgent, AgentSubscription, StateUpdate, DerivedState as State };
48
+ type StateUpdate<TConfig extends AnyConfig> = Partial<DerivedState<TConfig>>;
49
+ export { AnyConfig, ConfigItem, DerivedState, DerivedInstanceState, DerivedCommonState, StateSubscriber, CrannAgent, AgentSubscription, StateUpdate, DerivedState as State, ConnectReturn, UseCrann };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "crann",
3
- "version": "1.0.8",
3
+ "version": "1.0.14",
4
4
  "description": "",
5
5
  "main": "dist/cjs/index.js",
6
6
  "module": "dist/esm/index.js",
@@ -49,6 +49,7 @@
49
49
  },
50
50
  "homepage": "https://github.com/moclei/crann#readme",
51
51
  "dependencies": {
52
- "porter-source": "^1.0.13"
52
+ "crann": "^1.0.9",
53
+ "porter-source": "^1.0.22"
53
54
  }
54
55
  }