crann 1.0.6 → 1.0.9

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 E=Object.getPrototypeOf,R=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))!R.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(E(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 v(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]||!this.deepEqual(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:l,connectionType:c,context:f,location:T})=>{console.log("Crann porter connect",l,c,f,T),this.removeInstance(l)})}),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};v(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};v(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 k=Object.create;var l=Object.defineProperty;var w=Object.getOwnPropertyDescriptor;var A=Object.getOwnPropertyNames;var R=Object.getPrototypeOf,E=Object.prototype.hasOwnProperty;var U=(a,t)=>{for(var e in t)l(a,e,{get:t[e],enumerable:!0})},h=(a,t,e,i)=>{if(t&&typeof t=="object"||typeof t=="function")for(let n of A(t))!E.call(a,n)&&n!==e&&l(a,n,{get:()=>t[n],enumerable:!(i=w(t,n))||i.enumerable});return a};var O=(a,t,e)=>(e=a!=null?k(R(a)):{},h(t||!a||!a.__esModule?l(e,"default",{value:a,enumerable:!0}):e,a)),j=a=>h(l({},"__esModule",{value:!0}),a);var M={};U(M,{Crann:()=>C,Partition:()=>m,Persistence:()=>y,connect:()=>b,create:()=>I});module.exports=j(M);var d=O(require("webextension-polyfill"));var m={Instance:"instance",Common:"common"},y={Session:"session",Local:"local",None:"none"};var D=require("porter-source");function S(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),i=Object.keys(t);if(e.length!==i.length)return!1;e.sort(),i.sort();for(let n=0;n<e.length;n++){let o=e[n];if(o!==i[n]||!S(a[o],t[o]))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,o,s]=(0,D.source)("crann");this.post=i,o(({key:r,connectionType:g,context:p,location:u})=>{console.log("Crann porter connect",r,g,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};S(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};S(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",o=t?t[e]:this.commonState[e];switch(n){case"session":await d.default.storage.session.set({[this.storagePrefix+e]:o});break;case"local":await d.default.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 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,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 i={},n={};for(let o in t){let s=this.config[o];if(s.partition==="instance"){let r=o,g=t;i[r]=g[r]}else if(!s.partition||s.partition===m.Common){let r=o,g=t;n[r]=g[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 o in i){let s=this.removePrefix(o);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===m.Common&&(t[e]=i.default)}),t}};function I(a,t){return new C(a,t)}var P=require("porter-source");function b(a,t){let[e,i]=(0,P.connect)({namespace:"crann"}),n=L(a),o=null,s=new Map,r=0;return i({stateUpdate:c=>{o=c.payload.state,n={...n,...o},o&&s.forEach(f=>{(f.keys===void 0||f.keys.some(x=>o.hasOwnProperty(x)))&&f.callback(o)})}}),{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(a){let t={};Object.keys(a).forEach(i=>{let n=a[i];n.partition==="instance"&&(t[i]=n.default)});let e={};return Object.keys(a).forEach(i=>{let n=a[i];n.partition==="instance"&&(e[i]=n.default)}),{...t,...e}}0&&(module.exports={Crann,Partition,Persistence,connect,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] || !this.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 } 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: (DerivedInstanceState<TConfig> | DerivedState<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: (DerivedInstanceState<TConfig> | DerivedState<TConfig>), changes: Partial<DerivedInstanceState<TConfig> & DerivedCommonState<TConfig>>, key?: string) => void): void {\n this.stateChangeListeners.push(listener);\n }\n\n private notify(changes: Partial<DerivedState<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(): 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 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", "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"]
7
7
  }
package/dist/esm/index.js CHANGED
@@ -1,2 +1,2 @@
1
- import d from"webextension-polyfill";var g={Instance:"instance",Common:"common"},h={Session:"session",Local:"local",None:"none"};import{source as y}from"porter-source";function l(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]||!this.deepEqual(a[o],t[o]))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[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:S,connectionType:c,context:f,location:u})=>{console.log("Crann porter connect",S,c,f,u),this.removeInstance(S)})}),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};l(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};l(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 d.storage.session.set({[this.storagePrefix+e]:o});break;case"local":await d.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 d.storage.local.get(null),e=await d.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 C(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{C as Crann,g as Partition,h as Persistence,b as connect,D as create};
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(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]||!d(o[a],t[a]))return!1}return!0}var l=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,a,s]=y("crann");this.post=n,a(({key:r,connectionType:m,context:v,location:p})=>{console.log("Crann porter connect",r,m,v,p),this.addInstance(r),s(({key:S,connectionType:c,context:f,location:u})=>{console.log("Crann porter connect",S,c,f,u),this.removeInstance(S)})}),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",a=t?t[e]:this.commonState[e];switch(i){case"session":await C.storage.session.set({[this.storagePrefix+e]:a});break;case"local":await C.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?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,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 n={},i={};for(let a in t){let s=this.config[a];if(s.partition==="instance"){let r=a,m=t;n[r]=m[r]}else if(!s.partition||s.partition===g.Common){let r=a,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 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===g.Common&&(t[e]=n.default)}),t}};function D(o,t){return new l(o,t)}import{connect as I}from"porter-source";function b(o,t){let[e,n]=I({namespace:"crann"}),i=P(o),a=null,s=new Map,r=0;return n({stateUpdate:c=>{a=c.payload.state,i={...i,...a},a&&s.forEach(f=>{(f.keys===void 0||f.keys.some(T=>a.hasOwnProperty(T)))&&f.callback(a)})}}),{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(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}}export{l as Crann,g as Partition,h as Persistence,b as connect,D 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] || !this.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, 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: (DerivedInstanceState<TConfig> | DerivedState<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: (DerivedInstanceState<TConfig> | DerivedState<TConfig>), changes: Partial<DerivedInstanceState<TConfig> & DerivedCommonState<TConfig>>, key?: string) => void): void {\n this.stateChangeListeners.push(listener);\n }\n\n private notify(changes: Partial<DerivedState<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(): 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 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", "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", "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"]
7
7
  }
@@ -0,0 +1,29 @@
1
+ import { DerivedInstanceState, DerivedCommonState, ConfigItem, DerivedState } from './model/crann.model';
2
+ export declare class Crann<TConfig extends Record<string, ConfigItem<any>>> {
3
+ private config;
4
+ private instances;
5
+ private defaultCommonState;
6
+ private defaultInstanceState;
7
+ private commonState;
8
+ private stateChangeListeners;
9
+ private storagePrefix;
10
+ private post;
11
+ constructor(config: TConfig, storagePrefix?: string);
12
+ private addInstance;
13
+ private removeInstance;
14
+ setCommonState(state: Partial<DerivedCommonState<TConfig>>): Promise<void>;
15
+ setInstanceState(key: string, state: Partial<DerivedInstanceState<TConfig>>): Promise<void>;
16
+ private persist;
17
+ clear(): Promise<void>;
18
+ subscribe(listener: (state: (DerivedInstanceState<TConfig> | DerivedState<TConfig>), changes: Partial<DerivedInstanceState<TConfig> & DerivedCommonState<TConfig>>, key?: string) => void): void;
19
+ private notify;
20
+ get(): DerivedState<TConfig>;
21
+ get(key: string): DerivedInstanceState<TConfig> & DerivedCommonState<TConfig>;
22
+ set(state: Partial<DerivedCommonState<TConfig>>): Promise<void>;
23
+ set(state: Partial<DerivedInstanceState<TConfig> & DerivedCommonState<TConfig>>, key: string): Promise<void>;
24
+ private hydrate;
25
+ private removePrefix;
26
+ private initializeInstanceDefault;
27
+ private initializeCommonDefault;
28
+ }
29
+ export declare function create<TConfig extends Record<string, ConfigItem<any>>>(config: TConfig, storagePrefix?: string): Crann<TConfig>;
@@ -0,0 +1,2 @@
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>;
@@ -0,0 +1,3 @@
1
+ export { create, Crann } from './crann';
2
+ export { connect } from './crannAgent';
3
+ export { CrannAgent, StateUpdate, State, Partition, Persistence } from './model/crann.model';
@@ -0,0 +1,38 @@
1
+ export declare const Partition: {
2
+ Instance: "instance";
3
+ Common: "common";
4
+ };
5
+ export declare const Persistence: {
6
+ Session: "session";
7
+ Local: "local";
8
+ None: "none";
9
+ };
10
+ type ConfigItem<T> = {
11
+ default: T;
12
+ partition?: typeof Partition[keyof typeof Partition];
13
+ persist?: typeof Persistence[keyof typeof Persistence];
14
+ };
15
+ type DerivedState<T extends Record<string, ConfigItem<any>>> = {
16
+ [P in keyof T]: T[P]['default'];
17
+ };
18
+ type DerivedInstanceState<T extends Record<string, ConfigItem<any>>> = {
19
+ [P in keyof T as T[P]['partition'] extends 'instance' ? P : never]: T[P]['default'];
20
+ };
21
+ type DerivedCommonState<T extends Record<string, ConfigItem<any>>> = {
22
+ [P in keyof T as T[P]['partition'] extends 'common' ? P : never]: T[P]['default'];
23
+ };
24
+ type StateSubscriber<TConfig extends Record<string, ConfigItem<any>>> = {
25
+ keys?: Array<keyof DerivedState<TConfig>>;
26
+ callback: (changes: StateUpdate<TConfig>) => void;
27
+ };
28
+ type CrannAgent<TConfig extends Record<string, ConfigItem<any>>> = {
29
+ get: () => DerivedCommonState<TConfig> & DerivedInstanceState<TConfig>;
30
+ 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>>> = {
35
+ (callback: (changes: StateUpdate<TConfig>) => void, key?: keyof DerivedState<TConfig>): number;
36
+ };
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 };
@@ -0,0 +1 @@
1
+ export declare function deepEqual(a: any, b: any): boolean;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "crann",
3
- "version": "1.0.6",
3
+ "version": "1.0.9",
4
4
  "description": "",
5
5
  "main": "dist/cjs/index.js",
6
6
  "module": "dist/esm/index.js",
@@ -9,7 +9,9 @@
9
9
  "dist"
10
10
  ],
11
11
  "scripts": {
12
- "build": "node esbuild.config.js",
12
+ "build": "npm run build:ts && npm run build:js",
13
+ "build:ts": "tsc --emitDeclarationOnly --outDir dist",
14
+ "build:js": "node esbuild.config.js",
13
15
  "test": "jest",
14
16
  "prepublishOnly": "npm run build"
15
17
  },