@unbndl/store 1.0.0

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.
@@ -0,0 +1 @@
1
+ (function(e,t){typeof exports==`object`&&typeof module<`u`?t(exports):typeof define==`function`&&define.amd?define([`exports`],t):(e=typeof globalThis<`u`?globalThis:e||self,t(e.store={}))})(this,function(e){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});var t=Object.defineProperty,n=(e,n)=>{let r={};for(var i in e)t(r,i,{get:e[i],enumerable:!0});return n||t(r,Symbol.toStringTag,{value:`Module`}),r},r=class extends Error{};r.prototype.name=`InvalidTokenError`;function i(e){return decodeURIComponent(atob(e).replace(/(.)/g,(e,t)=>{let n=t.charCodeAt(0).toString(16).toUpperCase();return n.length<2&&(n=`0`+n),`%`+n}))}function a(e){let t=e.replace(/-/g,`+`).replace(/_/g,`/`);switch(t.length%4){case 0:break;case 2:t+=`==`;break;case 3:t+=`=`;break;default:throw Error(`base64 string is not of the correct length`)}try{return i(t)}catch{return atob(t)}}function o(e,t){if(typeof e!=`string`)throw new r(`Invalid token specified: must be a string`);t||={};let n=t.header===!0?0:1,i=e.split(`.`)[n];if(typeof i!=`string`)throw new r(`Invalid token specified: missing part #${n+1}`);let o;try{o=a(i)}catch(e){throw new r(`Invalid token specified: invalid base64 for part #${n+1} (${e.message})`)}try{return JSON.parse(o)}catch(e){throw new r(`Invalid token specified: invalid json for part #${n+1} (${e.message})`)}}var s=Object.defineProperty,c=((e,t)=>{let n={};for(var r in e)s(n,r,{get:e[r],enumerable:!0});return t||s(n,Symbol.toStringTag,{value:`Module`}),n})({Dispatch:()=>u,None:()=>l,dispatch:()=>ee,dispatcher:()=>d}),l=[],u=class extends CustomEvent{constructor(e,t=`un:message`){super(t,{bubbles:!0,composed:!0,detail:e})}};function d(e=`un:message`){return(t,...n)=>t.dispatchEvent(new u(n,e))}var ee=d(),te=class extends CustomEvent{constructor(e,t){super(e,{bubbles:!0,cancelable:!0,composed:!0,detail:t})}};function f(e,...t){let n={execute(){e(...t.map(e=>e instanceof m?e.open(n):e)),t.forEach(e=>e instanceof m&&e.close())}};n.execute()}var p=class e{constructor(){this.signals=new WeakMap,this.scheduled=new WeakSet}static{this.scheduler=new e}subscribe(e,t,n){let r=this.signals.get(e);r||(r=new Map,this.signals.set(e,r));let i=r.get(t);i||(i=new Set,r.set(t,i)),i.add(n)}scheduleEffects(e,t){let n=this.signals.get(e);if(!n)return;let r=n.get(t);if(r)for(let e of r)this.scheduled.has(e)||(this.scheduled.add(e),setTimeout(()=>{this.scheduled.delete(e),e.execute()}))}},ne=class{constructor(){this.running=[],this.eventType=`un-effect:change`}isRunning(){return this.running.length>0}push(e){this.running.push(e)}pop(){this.running.pop()}current(){let e=this.running.length;return e?this.running[e-1]:void 0}subscribe(e,t){let n=this.current();n&&p.scheduler.subscribe(t,e,n)}runEffects(e,t){if(p.scheduler.scheduleEffects(t,e),this.host){let n=new te(this.eventType,{property:e,value:t[e]});this.host.dispatchEvent(n)}}setHost(e,t){this.host=e,t&&(this.eventType=t)}},m=class{static{this.CHANGE_EVENT_TYPE=`un-context:change`}constructor(e,t){t?(this.manager=t.manager,this.object=t.object,this.proxy=t.proxy,this.update(e)):(this.manager=new ne,this.object=e,this.proxy=re(this.object,this.manager))}get(e){return this.proxy[e]}set(e,t){this.proxy[e]=t}toObject(){return this.object}update(e){Object.assign(this.proxy,e)}apply(e){this.update(e(this.proxy))}createEffect(e){f(e,this)}setHost(e,t){this.manager.setHost(e,t)}open(e){return this.manager.push(e),this.proxy}close(){this.manager.pop()}};function re(e,t){return new Proxy(e,{get:(e,n,r)=>{let i=Reflect.get(e,n,r);return t.isRunning()&&h(i)&&t.subscribe(n,e),i},set:(e,n,r,i)=>{let a=Reflect.set(e,n,r,i);return a&&h(r)&&t.runEffects(n,e),a}})}function h(e){switch(typeof e){case`object`:case`number`:case`string`:case`symbol`:case`boolean`:case`undefined`:return!0;default:return!1}}var g=class{constructor(e,...t){this.effectFn=()=>e(...t)}execute(){this.effectFn()}};function _(e,t){return Object.assign(e,{render:t}),e}function v(e,t,...n){let r=e.cloneNode(!0);return Array.from(t.entries()).forEach(([e,t])=>{let i=r.querySelector(`[data-${e}]`);i&&t.forEach(e=>e(i,r,...n))}),r}var ie=class e{static{this.parser=new DOMParser}constructor(e){this.docType=`text/html`,this.plugins=[],e&&(this.docType=e)}use(e){this.plugins=this.plugins.concat(e)}parse(t,n){let r={},i=t.map((e,i)=>{if(i>=n.length)return[e];let a=n[i],o=this.classifyPlace(i,t),s=this.tryReplacements(o,a);if(s){let t=r[o.nodeLabel];switch(t?t.push(s):r[o.nodeLabel]=[s],o.kind){case`attr value`:return[e,`"" data-${o.nodeLabel}`];case`tag content`:return[e,`data-${o.nodeLabel}`];case`element content`:return[e,`<ins data-${o.nodeLabel}></ins>`]}}else throw console.error(`No match for template parameter`,o,a),`Failed to render template parameter ${i} around ${e}`;return[e]}).flat().join(``),a=e.parser.parseFromString(i,this.docType),o=a.head.childElementCount?a.head.children:a.body.children,s=new DocumentFragment;s.replaceChildren(...o);let c=new Map;for(let e in r){let t=s.querySelector(`[data-${e}]`);t&&r[e].forEach(n=>{let r=n.apply(t,s);if(r){let t=c.get(e);t?t.push(r):c.set(e,[r])}})}return _(s,(...e)=>v(s,c,...e))}static{this.OPEN_RE=/<([a-zA-z][$a-zA-Z0-9.-]*)\s+[^>]*$/}static{this.IN_TAG_RE=/^(\s+|[^<>]*|"[^"]*")*$/}static{this.ATTR_RE=/([$.]?[a-zA-Z][$a-zA-Z0-9.-]*)=\s*$/}static{this.CLOSE_RE=/[/]?>[^<]*$/}classifyPlace(t,n){let r=null;for(let i=t;i>=0&&!(n[i].match(e.CLOSE_RE)||(r=n[i].match(e.OPEN_RE),r)||!n[i].match(e.IN_TAG_RE));i--);if(r){let i=n[t].match(e.ATTR_RE);return i?{kind:`attr value`,nodeLabel:`node${t}`,tagName:r[1],attrName:i[1]}:{kind:`tag content`,nodeLabel:`node${t}`,tagName:r[1]}}return{kind:`element content`,nodeLabel:`node${t}`}}tryReplacements(e,t){let n=this.plugins;for(let r=0;r<n.length;r++){let i=n[r];if(e.kind===i.place&&ae(t,i))return i.mutator(e,t)}}};function ae(e,t){return typeof t.types==`function`?t.types(e,t):t.types.includes(typeof e)}var y=class{constructor(e){this.place=e}apply(e,t){throw`abstract method 'apply' called`}},b=class extends y{constructor(e,t){super(e),this.content=t}apply(e,t){(e.parentNode||t).replaceChild(this.content,e)}},oe=class extends y{constructor(e,t){super(e),this.text=t,this.name=e.attrName}apply(e){e.setAttribute(this.name,this.text)}},se=class extends y{constructor(e,t){super(e),this.fn=t}apply(e,t){let n=this.place.nodeLabel;return(e,t,...r)=>{let i=new Comment(` <<< ${n} `),a=new Comment(` >>> ${n} `),o=new DocumentFragment;o.replaceChildren(i,a),(e.parentNode||t).replaceChild(o,e),f((...e)=>{ce(this.fn(...e),i,a)},...r)}}};function ce(e,t,n){let r=t.parentNode;if(!r)throw Error(`No parent for placeholder`);let i=e=>{if(Array.isArray(e)){let t=new DocumentFragment,n=e.map(i);return t.replaceChildren(...n),t}else if(e instanceof Node)return e;else return new Text(e?.toString()||``)},a=i(e);console.log(`📸 Rendered for view:`,e,a);let o=t.nextSibling;for(;o&&o!==n;){let e=o;o=o.nextSibling,r.removeChild(e)}a&&r.insertBefore(a,n)}var le=class extends y{constructor(e,t){super(e),this.fn=t,this.name=e.attrName}apply(e,t){return(e,t,...n)=>f((...t)=>{ue(this.fn(...t),e,this.name)},...n)}};function ue(e,t,n){let r=n.match(/^([.$])(.+)$/);if(r){let[n,i,a]=r;switch(i){case`.`:t[a]=e;break;case`$`:`viewModel`in t&&t.viewModel instanceof m&&t.viewModel.set(a,e);break}}else switch(typeof e){case`string`:t.setAttribute(n,e);break;case`undefined`:case`object`:case`boolean`:e?t.setAttribute(n,n):t.removeAttribute(n);break;default:t.setAttribute(n,e?.toString())}}var de=class extends y{constructor(e,t){super(e),this.fn=t}apply(e,t){return(e,t,...n)=>f((...t)=>{let n=this.fn(...t);typeof n==`function`&&n(e)},...n)}};new ie().use([{place:`element content`,types:[`string`,`number`,`bigint`,`symbol`,`boolean`],mutator:(e,t)=>new b(e,new Text(t?.toString()||``))},{place:`attr value`,types:[`string`,`number`,`bigint`,`symbol`],mutator:(e,t)=>new oe(e,t?.toString()||``)},{place:`element content`,types:e=>e instanceof Node,mutator:(e,t)=>new b(e,t)},{place:`element content`,types:[`function`],mutator:(e,t)=>new se(e,t)},{place:`attr value`,types:[`function`],mutator:(e,t)=>new le(e,t)},{place:`tag content`,types:[`function`],mutator:(e,t)=>new de(e,t)}]);var fe=class e extends HTMLElement{static{this.DISCOVERY_EVENT=`un-provider:discover`}static{this.REGISTRY_EVENT=`un-provider:register`}static{this.CHANGE_EVENT=`un-provider:change`}static{document.addEventListener(e.DISCOVERY_EVENT,e=>{let[t,n]=e.detail,r=he(t);r&&n(r)}),document.addEventListener(e.REGISTRY_EVENT,e=>{let[t,n]=e.detail;me(t,n)})}constructor(t,n){super(),this.contextLabel=n,this.context=new m(t),this.context.setHost(this,e.CHANGE_EVENT),this.addEventListener(e.DISCOVERY_EVENT,e=>{let[t,n]=e.detail;t===this.contextLabel&&(e.stopPropagation(),n(this))});let r=new CustomEvent(e.REGISTRY_EVENT,{bubbles:!0,composed:!0,detail:[this.contextLabel,this]});this.dispatchEvent(r)}attach(t){return this.addEventListener(e.CHANGE_EVENT,t),this.context.toObject()}detach(t){this.removeEventListener(e.CHANGE_EVENT,t)}};function pe(e,t){return new Promise((n,r)=>{let i=new CustomEvent(fe.DISCOVERY_EVENT,{bubbles:!0,composed:!0,detail:[t,e=>e?n(e):r()]});e.isConnected?e.dispatchEvent(i):document.dispatchEvent(i)})}var x={};function me(e,t){x[e]=t}function he(e){return x[e]}var ge=class{constructor(e){this.contextLabel=e}observe(e,t){return new Promise((n,r)=>{this.provider?n(this.attachObserver(t)):pe(e,this.contextLabel).then(e=>{this.provider=e,n(this.attachObserver(t))}).catch(e=>r(e))})}attachObserver(e){let t=this.provider.attach(t=>{let{property:n,value:r}=t.detail,i=new g(e,{property:n,value:r});this.observed&&(this.observed[n]=r,i.execute())});return this.observed=t,t}},_e=class{constructor(e,t,n=`service:message`,r=!0){this._pending=[],this._context=t,this._update=e,this._eventType=n,this._running=r}attach(e){e.addEventListener(this._eventType,e=>{e.stopPropagation();let t=e.detail;this.consume(t)})}start(){this._running||(this._running=!0,this._pending.forEach(e=>this.process(e)))}consume(e){if(e.length===0){let t=e;this._running?this.process(t):this._pending.push(t)}}process(e){let t=this._update(e,this._context.toObject());if(!Array.isArray(t))return t;let[n,...r]=t;return r.forEach(e=>e.then(e=>this.consume(e))),n}};function ve(e,t){return new ye(e,t)}var ye=class{constructor(e,t){this.client=e,this.observer=new ge(t)}start(e){return this.observer.observe(this.client,t=>{e(t.property,t.value)})}},be=`context:auth`,S=class e{static{this.TOKEN_KEY=`un-auth:token`}constructor(e){this.authenticated=!1,this.username=e||`anonymous`}static deauthenticate(t){return t.authenticated=!1,t.username=`anonymous`,localStorage.removeItem(e.TOKEN_KEY),t}},C=class e extends S{constructor(e){super();let t=o(e);console.log(`Token payload`,t),this.token=e,this.authenticated=!0,this.username=t.username}static authenticate(t){let n=new e(t);return localStorage.setItem(S.TOKEN_KEY,t),n}static authenticateFromLocalStorage(){let t=localStorage.getItem(S.TOKEN_KEY);return t?e.authenticate(t):new S}},w=class e extends _e{static{this.EVENT_TYPE=`auth:message`}constructor(t,n){super((e,t)=>this.update(e,t),t,e.EVENT_TYPE),this._redirectForLogin=n}update(e,t){switch(e[0]){case`auth/signin`:let{token:n,redirect:r}=e[1];return[D(n),T(r)];case`auth/signout`:return[O(t),T(this._redirectForLogin)];case`auth/redirect`:E(this._redirectForLogin,{next:window.location.href});break;default:let i=e[0];throw Error(`Unhandled Auth message "${i}"`)}return t}};c.dispatcher(w.EVENT_TYPE);function T(e,t={}){return new Promise(n=>{E(e,t),n(c.None)})}function E(e,t={}){if(e){let n=window.location.href,r=new URL(e,n);Object.entries(t).forEach(([e,t])=>r.searchParams.set(e,t)),console.log(`Redirecting to `,e),window.location.assign(r)}}function D(e){let{authenticated:t,username:n}=C.authenticate(e);return{authenticated:t,username:n,token:e}}function O(e){let{authenticated:t,username:n}=S.deauthenticate(new S(e.username));return{username:n,authenticated:t,token:void 0}}function k(e,t=be){return ve(e,t)}var A=Object.defineProperty,j=((e,t)=>{let n={};for(var r in e)A(n,r,{get:e[r],enumerable:!0});return t||A(n,Symbol.toStringTag,{value:`Module`}),n})({Dispatch:()=>N,None:()=>M,dispatch:()=>xe,dispatcher:()=>P}),M=[],N=class extends CustomEvent{constructor(e,t=`un:message`){super(t,{bubbles:!0,composed:!0,detail:e})}};function P(e=`un:message`){return(t,...n)=>t.dispatchEvent(new N(n,e))}var xe=P(),Se=class extends CustomEvent{constructor(e,t){super(e,{bubbles:!0,cancelable:!0,composed:!0,detail:t})}};function F(e,...t){let n={execute(){e(...t.map(e=>e instanceof L?e.open(n):e)),t.forEach(e=>e instanceof L&&e.close())}};n.execute()}var I=class e{constructor(){this.signals=new WeakMap,this.scheduled=new WeakSet}static{this.scheduler=new e}subscribe(e,t,n){let r=this.signals.get(e);r||(r=new Map,this.signals.set(e,r));let i=r.get(t);i||(i=new Set,r.set(t,i)),i.add(n)}scheduleEffects(e,t){let n=this.signals.get(e);if(!n)return;let r=n.get(t);if(r)for(let e of r)this.scheduled.has(e)||(this.scheduled.add(e),setTimeout(()=>{this.scheduled.delete(e),e.execute()}))}},Ce=class{constructor(){this.running=[],this.eventType=`un-effect:change`}isRunning(){return this.running.length>0}push(e){this.running.push(e)}pop(){this.running.pop()}current(){let e=this.running.length;return e?this.running[e-1]:void 0}subscribe(e,t){let n=this.current();n&&I.scheduler.subscribe(t,e,n)}runEffects(e,t){if(I.scheduler.scheduleEffects(t,e),this.host){let n=new Se(this.eventType,{property:e,value:t[e]});this.host.dispatchEvent(n)}}setHost(e,t){this.host=e,t&&(this.eventType=t)}},L=class{static{this.CHANGE_EVENT_TYPE=`un-context:change`}constructor(e,t){t?(this.manager=t.manager,this.object=t.object,this.proxy=t.proxy,this.update(e)):(this.manager=new Ce,this.object=e,this.proxy=we(this.object,this.manager))}get(e){return this.proxy[e]}set(e,t){this.proxy[e]=t}toObject(){return this.object}update(e){Object.assign(this.proxy,e)}apply(e){this.update(e(this.proxy))}createEffect(e){F(e,this)}setHost(e,t){this.manager.setHost(e,t)}open(e){return this.manager.push(e),this.proxy}close(){this.manager.pop()}};function we(e,t){return new Proxy(e,{get:(e,n,r)=>{let i=Reflect.get(e,n,r);return t.isRunning()&&R(i)&&t.subscribe(n,e),i},set:(e,n,r,i)=>{let a=Reflect.set(e,n,r,i);return a&&R(r)&&t.runEffects(n,e),a}})}function R(e){switch(typeof e){case`object`:case`number`:case`string`:case`symbol`:case`boolean`:case`undefined`:return!0;default:return!1}}var Te=class{constructor(e,...t){this.effectFn=()=>e(...t)}execute(){this.effectFn()}};function Ee(e,t){return Object.assign(e,{render:t}),e}function De(e,t,...n){let r=e.cloneNode(!0);return Array.from(t.entries()).forEach(([e,t])=>{let i=r.querySelector(`[data-${e}]`);i&&t.forEach(e=>e(i,r,...n))}),r}var Oe=class e{static{this.parser=new DOMParser}constructor(e){this.docType=`text/html`,this.plugins=[],e&&(this.docType=e)}use(e){this.plugins=this.plugins.concat(e)}parse(t,n){let r={},i=t.map((e,i)=>{if(i>=n.length)return[e];let a=n[i],o=this.classifyPlace(i,t),s=this.tryReplacements(o,a);if(s){let t=r[o.nodeLabel];switch(t?t.push(s):r[o.nodeLabel]=[s],o.kind){case`attr value`:return[e,`"" data-${o.nodeLabel}`];case`tag content`:return[e,`data-${o.nodeLabel}`];case`element content`:return[e,`<ins data-${o.nodeLabel}></ins>`]}}else throw console.error(`No match for template parameter`,o,a),`Failed to render template parameter ${i} around ${e}`;return[e]}).flat().join(``),a=e.parser.parseFromString(i,this.docType),o=a.head.childElementCount?a.head.children:a.body.children,s=new DocumentFragment;s.replaceChildren(...o);let c=new Map;for(let e in r){let t=s.querySelector(`[data-${e}]`);t&&r[e].forEach(n=>{let r=n.apply(t,s);if(r){let t=c.get(e);t?t.push(r):c.set(e,[r])}})}return Ee(s,(...e)=>De(s,c,...e))}static{this.OPEN_RE=/<([a-zA-z][$a-zA-Z0-9.-]*)\s+[^>]*$/}static{this.IN_TAG_RE=/^(\s+|[^<>]*|"[^"]*")*$/}static{this.ATTR_RE=/([$.]?[a-zA-Z][$a-zA-Z0-9.-]*)=\s*$/}static{this.CLOSE_RE=/[/]?>[^<]*$/}classifyPlace(t,n){let r=null;for(let i=t;i>=0&&!(n[i].match(e.CLOSE_RE)||(r=n[i].match(e.OPEN_RE),r)||!n[i].match(e.IN_TAG_RE));i--);if(r){let i=n[t].match(e.ATTR_RE);return i?{kind:`attr value`,nodeLabel:`node${t}`,tagName:r[1],attrName:i[1]}:{kind:`tag content`,nodeLabel:`node${t}`,tagName:r[1]}}return{kind:`element content`,nodeLabel:`node${t}`}}tryReplacements(e,t){let n=this.plugins;for(let r=0;r<n.length;r++){let i=n[r];if(e.kind===i.place&&ke(t,i))return i.mutator(e,t)}}};function ke(e,t){return typeof t.types==`function`?t.types(e,t):t.types.includes(typeof e)}var z=class{constructor(e){this.place=e}apply(e,t){throw`abstract method 'apply' called`}},B=class extends z{constructor(e,t){super(e),this.content=t}apply(e,t){(e.parentNode||t).replaceChild(this.content,e)}},Ae=class extends z{constructor(e,t){super(e),this.text=t,this.name=e.attrName}apply(e){e.setAttribute(this.name,this.text)}},je=class extends z{constructor(e,t){super(e),this.fn=t}apply(e,t){let n=this.place.nodeLabel;return(e,t,...r)=>{let i=new Comment(` <<< ${n} `),a=new Comment(` >>> ${n} `),o=new DocumentFragment;o.replaceChildren(i,a),(e.parentNode||t).replaceChild(o,e),F((...e)=>{Me(this.fn(...e),i,a)},...r)}}};function Me(e,t,n){let r=t.parentNode;if(!r)throw Error(`No parent for placeholder`);let i=e=>{if(Array.isArray(e)){let t=new DocumentFragment,n=e.map(i);return t.replaceChildren(...n),t}else if(e instanceof Node)return e;else return new Text(e?.toString()||``)},a=i(e);console.log(`📸 Rendered for view:`,e,a);let o=t.nextSibling;for(;o&&o!==n;){let e=o;o=o.nextSibling,r.removeChild(e)}a&&r.insertBefore(a,n)}var Ne=class extends z{constructor(e,t){super(e),this.fn=t,this.name=e.attrName}apply(e,t){return(e,t,...n)=>F((...t)=>{Pe(this.fn(...t),e,this.name)},...n)}};function Pe(e,t,n){let r=n.match(/^([.$])(.+)$/);if(r){let[n,i,a]=r;switch(i){case`.`:t[a]=e;break;case`$`:`viewModel`in t&&t.viewModel instanceof L&&t.viewModel.set(a,e);break}}else switch(typeof e){case`string`:t.setAttribute(n,e);break;case`undefined`:case`object`:case`boolean`:e?t.setAttribute(n,n):t.removeAttribute(n);break;default:t.setAttribute(n,e?.toString())}}var Fe=class extends z{constructor(e,t){super(e),this.fn=t}apply(e,t){return(e,t,...n)=>F((...t)=>{let n=this.fn(...t);typeof n==`function`&&n(e)},...n)}};new Oe().use([{place:`element content`,types:[`string`,`number`,`bigint`,`symbol`,`boolean`],mutator:(e,t)=>new B(e,new Text(t?.toString()||``))},{place:`attr value`,types:[`string`,`number`,`bigint`,`symbol`],mutator:(e,t)=>new Ae(e,t?.toString()||``)},{place:`element content`,types:e=>e instanceof Node,mutator:(e,t)=>new B(e,t)},{place:`element content`,types:[`function`],mutator:(e,t)=>new je(e,t)},{place:`attr value`,types:[`function`],mutator:(e,t)=>new Ne(e,t)},{place:`tag content`,types:[`function`],mutator:(e,t)=>new Fe(e,t)}]);var V=class e extends HTMLElement{static{this.DISCOVERY_EVENT=`un-provider:discover`}static{this.REGISTRY_EVENT=`un-provider:register`}static{this.CHANGE_EVENT=`un-provider:change`}static{document.addEventListener(e.DISCOVERY_EVENT,e=>{let[t,n]=e.detail,r=Re(t);r&&n(r)}),document.addEventListener(e.REGISTRY_EVENT,e=>{let[t,n]=e.detail;Le(t,n)})}constructor(t,n){super(),this.contextLabel=n,this.context=new L(t),this.context.setHost(this,e.CHANGE_EVENT),this.addEventListener(e.DISCOVERY_EVENT,e=>{let[t,n]=e.detail;t===this.contextLabel&&(e.stopPropagation(),n(this))});let r=new CustomEvent(e.REGISTRY_EVENT,{bubbles:!0,composed:!0,detail:[this.contextLabel,this]});this.dispatchEvent(r)}attach(t){return this.addEventListener(e.CHANGE_EVENT,t),this.context.toObject()}detach(t){this.removeEventListener(e.CHANGE_EVENT,t)}};function Ie(e,t){return new Promise((n,r)=>{let i=new CustomEvent(V.DISCOVERY_EVENT,{bubbles:!0,composed:!0,detail:[t,e=>e?n(e):r()]});e.isConnected?e.dispatchEvent(i):document.dispatchEvent(i)})}var H={};function Le(e,t){H[e]=t}function Re(e){return H[e]}var ze=class{constructor(e){this.contextLabel=e}observe(e,t){return new Promise((n,r)=>{this.provider?n(this.attachObserver(t)):Ie(e,this.contextLabel).then(e=>{this.provider=e,n(this.attachObserver(t))}).catch(e=>r(e))})}attachObserver(e){let t=this.provider.attach(t=>{let{property:n,value:r}=t.detail,i=new Te(e,{property:n,value:r});this.observed&&(this.observed[n]=r,i.execute())});return this.observed=t,t}},Be=class{constructor(e,t,n=`service:message`,r=!0){this._pending=[],this._context=t,this._update=e,this._eventType=n,this._running=r}attach(e){e.addEventListener(this._eventType,e=>{e.stopPropagation();let t=e.detail;this.consume(t)})}start(){this._running||(this._running=!0,this._pending.forEach(e=>this.process(e)))}consume(e){if(e.length===0){let t=e;this._running?this.process(t):this._pending.push(t)}}process(e){let t=this._update(e,this._context.toObject());if(!Array.isArray(t))return t;let[n,...r]=t;return r.forEach(e=>e.then(e=>this.consume(e))),n}},Ve=class{constructor(e,t){this.client=e,this.observer=new ze(t)}start(e){return this.observer.observe(this.client,t=>{e(t.property,t.value)})}},U=class{constructor(e,t){this.origin=e;let n=He(t).map(([e,t])=>[t,e]);this.inverse=Object.fromEntries(n)}mapObservation(e){let t=Object.entries(e);return Object.fromEntries(t.map(([e,t])=>[this.inverse[e],t]).filter(e=>e.length>0))}start(e){return this.origin.start((t,n)=>{let r=this.inverse[t];e(r,n)}).then(e=>this.mapObservation(e))}};function He(e){return Object.entries(e).map(([e,t])=>[e,t])}var Ue=class extends CustomEvent{constructor(e,t){super(e,{bubbles:!0,cancelable:!0,composed:!0,detail:t})}};function W(e,...t){let n={execute(){e(...t.map(e=>e instanceof K?e.open(n):e)),t.forEach(e=>e instanceof K&&e.close())}};n.execute()}var G=class e{constructor(){this.signals=new WeakMap,this.scheduled=new WeakSet}static{this.scheduler=new e}subscribe(e,t,n){let r=this.signals.get(e);r||(r=new Map,this.signals.set(e,r));let i=r.get(t);i||(i=new Set,r.set(t,i)),i.add(n)}scheduleEffects(e,t){let n=this.signals.get(e);if(!n)return;let r=n.get(t);if(r)for(let e of r)this.scheduled.has(e)||(this.scheduled.add(e),setTimeout(()=>{this.scheduled.delete(e),e.execute()}))}},We=class{constructor(){this.running=[],this.eventType=`un-effect:change`}isRunning(){return this.running.length>0}push(e){this.running.push(e)}pop(){this.running.pop()}current(){let e=this.running.length;return e?this.running[e-1]:void 0}subscribe(e,t){let n=this.current();n&&G.scheduler.subscribe(t,e,n)}runEffects(e,t){if(G.scheduler.scheduleEffects(t,e),this.host){let n=new Ue(this.eventType,{property:e,value:t[e]});this.host.dispatchEvent(n)}}setHost(e,t){this.host=e,t&&(this.eventType=t)}},K=class{static{this.CHANGE_EVENT_TYPE=`un-context:change`}constructor(e,t){t?(this.manager=t.manager,this.object=t.object,this.proxy=t.proxy,this.update(e)):(this.manager=new We,this.object=e,this.proxy=Ge(this.object,this.manager))}get(e){return this.proxy[e]}set(e,t){this.proxy[e]=t}toObject(){return this.object}update(e){Object.assign(this.proxy,e)}apply(e){this.update(e(this.proxy))}createEffect(e){W(e,this)}setHost(e,t){this.manager.setHost(e,t)}open(e){return this.manager.push(e),this.proxy}close(){this.manager.pop()}};function Ge(e,t){return new Proxy(e,{get:(e,n,r)=>{let i=Reflect.get(e,n,r);return t.isRunning()&&q(i)&&t.subscribe(n,e),i},set:(e,n,r,i)=>{let a=Reflect.set(e,n,r,i);return a&&q(r)&&t.runEffects(n,e),a}})}function q(e){switch(typeof e){case`object`:case`number`:case`string`:case`symbol`:case`boolean`:case`undefined`:return!0;default:return!1}}function Ke(e,t){return Object.assign(e,{render:t}),e}function qe(e,t,...n){let r=e.cloneNode(!0);return Array.from(t.entries()).forEach(([e,t])=>{let i=r.querySelector(`[data-${e}]`);i&&t.forEach(e=>e(i,r,...n))}),r}var Je=class e{static{this.parser=new DOMParser}constructor(e){this.docType=`text/html`,this.plugins=[],e&&(this.docType=e)}use(e){this.plugins=this.plugins.concat(e)}parse(t,n){let r={},i=t.map((e,i)=>{if(i>=n.length)return[e];let a=n[i],o=this.classifyPlace(i,t),s=this.tryReplacements(o,a);if(s){let t=r[o.nodeLabel];switch(t?t.push(s):r[o.nodeLabel]=[s],o.kind){case`attr value`:return[e,`"" data-${o.nodeLabel}`];case`tag content`:return[e,`data-${o.nodeLabel}`];case`element content`:return[e,`<ins data-${o.nodeLabel}></ins>`]}}else throw console.error(`No match for template parameter`,o,a),`Failed to render template parameter ${i} around ${e}`;return[e]}).flat().join(``),a=e.parser.parseFromString(i,this.docType),o=a.head.childElementCount?a.head.children:a.body.children,s=new DocumentFragment;s.replaceChildren(...o);let c=new Map;for(let e in r){let t=s.querySelector(`[data-${e}]`);t&&r[e].forEach(n=>{let r=n.apply(t,s);if(r){let t=c.get(e);t?t.push(r):c.set(e,[r])}})}return Ke(s,(...e)=>qe(s,c,...e))}static{this.OPEN_RE=/<([a-zA-z][$a-zA-Z0-9.-]*)\s+[^>]*$/}static{this.IN_TAG_RE=/^(\s+|[^<>]*|"[^"]*")*$/}static{this.ATTR_RE=/([$.]?[a-zA-Z][$a-zA-Z0-9.-]*)=\s*$/}static{this.CLOSE_RE=/[/]?>[^<]*$/}classifyPlace(t,n){let r=null;for(let i=t;i>=0&&!(n[i].match(e.CLOSE_RE)||(r=n[i].match(e.OPEN_RE),r)||!n[i].match(e.IN_TAG_RE));i--);if(r){let i=n[t].match(e.ATTR_RE);return i?{kind:`attr value`,nodeLabel:`node${t}`,tagName:r[1],attrName:i[1]}:{kind:`tag content`,nodeLabel:`node${t}`,tagName:r[1]}}return{kind:`element content`,nodeLabel:`node${t}`}}tryReplacements(e,t){let n=this.plugins;for(let r=0;r<n.length;r++){let i=n[r];if(e.kind===i.place&&Ye(t,i))return i.mutator(e,t)}}};function Ye(e,t){return typeof t.types==`function`?t.types(e,t):t.types.includes(typeof e)}var J=class{constructor(e){this.place=e}apply(e,t){throw`abstract method 'apply' called`}},Y=class extends J{constructor(e,t){super(e),this.content=t}apply(e,t){(e.parentNode||t).replaceChild(this.content,e)}},Xe=class extends J{constructor(e,t){super(e),this.text=t,this.name=e.attrName}apply(e){e.setAttribute(this.name,this.text)}},Ze=class extends J{constructor(e,t){super(e),this.fn=t}apply(e,t){let n=this.place.nodeLabel;return(e,t,...r)=>{let i=new Comment(` <<< ${n} `),a=new Comment(` >>> ${n} `),o=new DocumentFragment;o.replaceChildren(i,a),(e.parentNode||t).replaceChild(o,e),W((...e)=>{Qe(this.fn(...e),i,a)},...r)}}};function Qe(e,t,n){let r=t.parentNode;if(!r)throw Error(`No parent for placeholder`);let i=e=>{if(Array.isArray(e)){let t=new DocumentFragment,n=e.map(i);return t.replaceChildren(...n),t}else if(e instanceof Node)return e;else return new Text(e?.toString()||``)},a=i(e);console.log(`📸 Rendered for view:`,e,a);let o=t.nextSibling;for(;o&&o!==n;){let e=o;o=o.nextSibling,r.removeChild(e)}a&&r.insertBefore(a,n)}var $e=class extends J{constructor(e,t){super(e),this.fn=t,this.name=e.attrName}apply(e,t){return(e,t,...n)=>W((...t)=>{et(this.fn(...t),e,this.name)},...n)}};function et(e,t,n){let r=n.match(/^([.$])(.+)$/);if(r){let[n,i,a]=r;switch(i){case`.`:t[a]=e;break;case`$`:`viewModel`in t&&t.viewModel instanceof K&&t.viewModel.set(a,e);break}}else switch(typeof e){case`string`:t.setAttribute(n,e);break;case`undefined`:case`object`:case`boolean`:e?t.setAttribute(n,n):t.removeAttribute(n);break;default:t.setAttribute(n,e?.toString())}}var X=class extends J{constructor(e,t){super(e),this.fn=t}apply(e,t){return(e,t,...n)=>W((...t)=>{let n=this.fn(...t);typeof n==`function`&&n(e)},...n)}};new Je().use([{place:`element content`,types:[`string`,`number`,`bigint`,`symbol`,`boolean`],mutator:(e,t)=>new Y(e,new Text(t?.toString()||``))},{place:`attr value`,types:[`string`,`number`,`bigint`,`symbol`],mutator:(e,t)=>new Xe(e,t?.toString()||``)},{place:`element content`,types:e=>e instanceof Node,mutator:(e,t)=>new Y(e,t)},{place:`element content`,types:[`function`],mutator:(e,t)=>new Ze(e,t)},{place:`attr value`,types:[`function`],mutator:(e,t)=>new $e(e,t)},{place:`tag content`,types:[`function`],mutator:(e,t)=>new X(e,t)}]);var Z=class extends K{constructor(e,t){super(e,t)}get $(){return this.toObject()}with(e,...t){let n=Object.fromEntries(t.map(e=>[e,e]));return this.merge(new U(e,n))}withCalculated(e,t){return this.merge(new U(e,t))}withRenamed(e,t){return this.merge(new U(e,t))}merge(e){if(e){let t=e.start((e,n)=>{console.log(`🪄 Merging effect`,e,n,t),this.set(e,n)}).then(e=>{console.log(`👀 ViewModel source observed:`,e,t),Object.keys(e).forEach(t=>this.set(t,e[t]))})}return this}render(e){return e.render(this)}};function tt(e){return e===void 0?new Z({}):new Z(e)}var nt=n({CONTEXT_DEFAULT:()=>Q,Provider:()=>rt,Service:()=>$,dispatch:()=>it}),Q=`context:store`,$=class e extends Be{static{this.EVENT_TYPE=`store:message`}constructor(t,n){super((e,t)=>n(t,e),t,e.EVENT_TYPE)}},rt=class extends V{constructor(e,t){super(t,Q),this.viewModel=tt({authenticated:!1}).with(k(this),`authenticated`,`username`,`token`),this._updateFn=e}connectedCallback(){new $(this.context,(e,t)=>this._updateFn(e,t,this.viewModel.toObject())).attach(this)}};function it(e,t){console.log(`📨 Dispatching message:`,t,e),e.dispatchEvent(new j.Dispatch(t,$.EVENT_TYPE))}function at(e,t=Q){return new Ve(e,t)}Object.defineProperty(e,`Store`,{enumerable:!0,get:function(){return nt}}),e.fromStore=at});
package/package.json ADDED
@@ -0,0 +1,23 @@
1
+ {
2
+ "name": "@unbndl/store",
3
+ "version": "1.0.0",
4
+ "description": "Unbundled library for maintaining client-side state in a store, following the Elm architecture and MVU",
5
+ "main": "./dist/store.js",
6
+ "type": "module",
7
+ "scripts": {
8
+ "build": "npx vite build",
9
+ "test": "echo \"Error: no test specified\" && exit 1"
10
+ },
11
+ "keywords": [
12
+ "HTML",
13
+ "JavaScript",
14
+ "TypeScript",
15
+ "Unbundled",
16
+ "store",
17
+ "MVU",
18
+ "MV*",
19
+ "The Elm Architecture (TEA)"
20
+ ],
21
+ "author": "ken@mnmlst.me",
22
+ "license": "BSD-3-Clause"
23
+ }
@@ -0,0 +1,9 @@
1
+ import { FromService } from "@unbndl/service";
2
+ import * as Store from "./store.ts";
3
+
4
+ export function fromStore<M extends object>(
5
+ target: HTMLElement,
6
+ contextLabel: string = Store.CONTEXT_DEFAULT
7
+ ) {
8
+ return new FromService<M>(target, contextLabel);
9
+ }
package/src/index.ts ADDED
@@ -0,0 +1,2 @@
1
+ export * as Store from "./store";
2
+ export * from "./fromStore";
package/src/store.ts ADDED
@@ -0,0 +1,91 @@
1
+ import { Context } from "@unbndl/html";
2
+ import { Auth, fromAuth } from "@unbndl/auth";
3
+ import { Message, Provider, Service } from "@unbndl/service";
4
+ import { createViewModel } from "@unbndl/view";
5
+
6
+ const STORE_CONTEXT_DEFAULT = "context:store";
7
+
8
+ type UpdateFn<
9
+ M extends object,
10
+ Msg extends Message.Base,
11
+ Cmd extends Message.Base
12
+ > = (model: M, message: Msg | Cmd) => M | Message.Async<M, Cmd>;
13
+
14
+ type AuthorizedUpdateFn<
15
+ M extends object,
16
+ Msg extends Message.Base,
17
+ Cmd extends Message.Base
18
+ > = (
19
+ model: M,
20
+ message: Msg | Cmd,
21
+ auth: Auth.Model
22
+ ) => M | Message.Async<M, Cmd>;
23
+
24
+ class StoreService<
25
+ M extends object,
26
+ Msg extends Message.Base,
27
+ Cmd extends Message.Base
28
+ > extends Service<Msg | Cmd, M> {
29
+ static EVENT_TYPE = "store:message";
30
+
31
+ constructor(
32
+ context: Context<M>,
33
+ update: UpdateFn<M, Msg, Cmd>
34
+ ) {
35
+ super(
36
+ (message: Msg | Cmd, model: M) => update(model, message),
37
+ context,
38
+ StoreService.EVENT_TYPE
39
+ );
40
+ }
41
+ }
42
+
43
+ class StoreProvider<
44
+ M extends object,
45
+ Msg extends Message.Base,
46
+ Cmd extends Message.Base
47
+ > extends Provider<M> {
48
+ viewModel = createViewModel<Auth.Model>({
49
+ authenticated: false
50
+ }).with(fromAuth(this), "authenticated", "username", "token");
51
+
52
+ _updateFn: AuthorizedUpdateFn<M, Msg, Cmd>;
53
+
54
+ constructor(
55
+ updateFn: AuthorizedUpdateFn<M, Msg, Cmd>,
56
+ init: M
57
+ ) {
58
+ super(init, STORE_CONTEXT_DEFAULT);
59
+ this._updateFn = updateFn;
60
+ }
61
+
62
+ connectedCallback() {
63
+ const service = new StoreService<M, Msg, Cmd>(
64
+ this.context,
65
+ (model: M, message: Msg | Cmd) =>
66
+ this._updateFn(
67
+ model,
68
+ message,
69
+ this.viewModel.toObject()
70
+ )
71
+ );
72
+ service.attach(this);
73
+ }
74
+ }
75
+
76
+ function dispatch<Msg extends Message.Base>(
77
+ target: HTMLElement,
78
+ message: Msg
79
+ ) {
80
+ console.log("📨 Dispatching message:", message, target);
81
+ target.dispatchEvent(
82
+ new Message.Dispatch<Msg>(message, StoreService.EVENT_TYPE)
83
+ );
84
+ }
85
+
86
+ export {
87
+ STORE_CONTEXT_DEFAULT as CONTEXT_DEFAULT,
88
+ StoreProvider as Provider,
89
+ StoreService as Service,
90
+ dispatch
91
+ };
package/vite.config.js ADDED
@@ -0,0 +1,11 @@
1
+ import { defineConfig } from "vite";
2
+ import { resolve } from "path";
3
+
4
+ export default defineConfig({
5
+ build: {
6
+ lib: {
7
+ entry: resolve(__dirname, "src/index.ts"),
8
+ name: "store"
9
+ }
10
+ }
11
+ });