@storix-js/sync 0.2.1 → 0.3.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.
package/README.md CHANGED
@@ -19,4 +19,4 @@ const storix = createStorix({
19
19
  });
20
20
  ```
21
21
 
22
- The plugin uses `BroadcastChannel` when available and falls back to the `storage` event.
22
+ The plugin uses `BroadcastChannel` when available and the `storage` event only as a fallback, never as a duplicate second transport. Local changes are debounced/coalesced by scope and key, remote-origin changes are not echoed, and cross-namespace delivery requires explicit `namespaces` configuration.
package/dist/index.cjs CHANGED
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const H=require("@storix-js/core");function T(c={}){const g=c.channelName??"storix-sync",m=new Set(c.include??[]),h=new Set(c.exclude??[]),p=c.namespaces??[],I=p==="*"?null:new Set(p),y=c.debounce??16,S=crypto.randomUUID(),a=`__storix_sync__:${g}`,i=new Map,d=new Set,u=new Map,l=new Map;let r=null;const s=typeof window<"u"&&"BroadcastChannel"in window?new BroadcastChannel(g):null,f=n=>{const e=[n.$id,n.$scopeId];return!(e.some(t=>h.has(t))||m.size>0&&!e.some(t=>m.has(t)))},v=(n,e)=>e===n||I===null?!0:I.has(e),$=(n,e)=>{!e||e.originTabId===S||v(n.$namespace,e.namespace)&&e.storeId===n.$id&&f(n)&&n.$patch({[e.key]:e.newValue},"remote")},w=()=>{if(r=null,i.size===0)return;const n=Array.from(i.values());i.clear();for(const e of n){const t={...e,originTabId:S};if(s&&s.postMessage(t),typeof window<"u"&&"localStorage"in window)try{window.localStorage.setItem(a,JSON.stringify(t)),window.localStorage.removeItem(a)}catch{}}},M=n=>{if(i.set(`${n.scopeId}:${n.key}`,n),y<=0){w();return}r||(r=setTimeout(w,y))};return H.definePlugin({name:"sync",onInit(n){const e=n;if(f(e)){if(d.add(e.$scopeId),s){const t=o=>{$(e,o.data)};u.set(e.$scopeId,t),s.addEventListener("message",t)}if(typeof window<"u"){const t=o=>{if(!(o.key!==a||!o.newValue))try{const b=JSON.parse(o.newValue);$(e,b)}catch{}};l.set(e.$scopeId,t),window.addEventListener("storage",t)}}},onMutation(n,e){e.origin!=="remote"&&f(n)&&M(e)},onDispose(n){const e=n;d.delete(e.$scopeId);const t=u.get(e.$scopeId);s&&t&&(s.removeEventListener("message",t),u.delete(e.$scopeId));const o=l.get(e.$scopeId);typeof window<"u"&&o&&(window.removeEventListener("storage",o),l.delete(e.$scopeId)),r&&(clearTimeout(r),r=null),w(),d.size===0&&(s==null||s.close())}})}exports.syncPlugin=T;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require("@storix-js/core");function t(t={}){let n=t.channelName??`storix-sync`,r=new Set(t.include??[]),i=new Set(t.exclude??[]),a=t.namespaces??[],o=a===`*`?null:new Set(a),s=t.debounce??16,c=globalThis.crypto?.randomUUID?.()??`storix-${Date.now()}-${Math.random().toString(36).slice(2)}`,l=`__storix_sync__:${n}`,u=new Map,d=new Set,f=new Map,p=new Map,m=null,h=null,g=()=>(h||typeof window>`u`||typeof window.BroadcastChannel!=`function`||(h=new window.BroadcastChannel(n)),h),_=e=>{let t=[e.$id,e.$scopeId];return!(t.some(e=>i.has(e))||r.size>0&&!t.some(e=>r.has(e)))},v=(e,t)=>t===e||o===null||o.has(t),y=(e,t)=>{t&&t.originTabId!==c&&v(e.$namespace,t.namespace)&&t.storeId===e.$id&&_(e)&&e.$patch({[t.key]:t.newValue},`remote`)},b=()=>{if(m=null,u.size===0)return;let e=Array.from(u.values());u.clear();for(let t of e){let e={...t,originTabId:c},n=g();if(n&&n.postMessage(e),!n&&typeof window<`u`&&`localStorage`in window)try{window.localStorage.setItem(l,JSON.stringify(e)),window.localStorage.removeItem(l)}catch{}}},x=e=>{if(u.set(`${e.scopeId}:${e.key}`,e),s<=0){b();return}m||=setTimeout(b,s)};return(0,e.definePlugin)({name:`sync`,onInit(e){let t=e;if(!_(t))return;d.add(t.$scopeId);let n=g();if(n){let e=e=>{y(t,e.data)};f.set(t.$scopeId,e),n.addEventListener(`message`,e)}if(typeof window<`u`){let e=e=>{if(e.key===l&&e.newValue)try{let n=JSON.parse(e.newValue);y(t,n)}catch{}};p.set(t.$scopeId,e),window.addEventListener(`storage`,e)}},onMutation(e,t){t.origin!==`remote`&&_(e)&&x(t)},onDispose(e){let t=e;d.delete(t.$scopeId);let n=f.get(t.$scopeId);h&&n&&(h.removeEventListener(`message`,n),f.delete(t.$scopeId));let r=p.get(t.$scopeId);typeof window<`u`&&r&&(window.removeEventListener(`storage`,r),p.delete(t.$scopeId)),m&&=(clearTimeout(m),null),b(),d.size===0&&(h?.close(),h=null)}})}exports.syncPlugin=t;
package/dist/index.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { type MutationPayload } from '@storix-js/core';
1
2
  export interface SyncPluginOptions {
2
3
  channelName?: string;
3
4
  include?: string[];
@@ -5,5 +6,10 @@ export interface SyncPluginOptions {
5
6
  namespaces?: string[] | '*';
6
7
  debounce?: number;
7
8
  }
8
- export declare function syncPlugin(options?: SyncPluginOptions): import("@storix-js/core").StorePlugin;
9
+ export declare function syncPlugin(options?: SyncPluginOptions): {
10
+ name: string;
11
+ onInit(store: import("@storix-js/core").StoreInstance<{}, {}, {}, {}>): void;
12
+ onMutation(store: import("@storix-js/core").StoreInstance<{}, {}, {}, {}>, mutation: MutationPayload): void;
13
+ onDispose(store: import("@storix-js/core").StoreInstance<{}, {}, {}, {}>): void;
14
+ };
9
15
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,iBAAiB;IAChC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,EAAE,GAAG,GAAG,CAAC;IAC5B,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AASD,wBAAgB,UAAU,CAAC,OAAO,GAAE,iBAAsB,yCA8IzD"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,KAAK,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAErE,MAAM,WAAW,iBAAiB;IAChC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,EAAE,GAAG,GAAG,CAAC;IAC5B,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AASD,wBAAgB,UAAU,CAAC,OAAO,GAAE,iBAAsB;;;;;EAwJzD"}
package/dist/index.js CHANGED
@@ -1,71 +1,66 @@
1
- import { definePlugin as b } from "@storix-js/core";
2
- function E(c = {}) {
3
- const m = c.channelName ?? "storix-sync", g = new Set(c.include ?? []), h = new Set(c.exclude ?? []), p = c.namespaces ?? [], I = p === "*" ? null : new Set(p), $ = c.debounce ?? 16, S = crypto.randomUUID(), a = `__storix_sync__:${m}`, i = /* @__PURE__ */ new Map(), d = /* @__PURE__ */ new Set(), u = /* @__PURE__ */ new Map(), l = /* @__PURE__ */ new Map();
4
- let r = null;
5
- const t = typeof window < "u" && "BroadcastChannel" in window ? new BroadcastChannel(m) : null, f = (n) => {
6
- const e = [n.$id, n.$scopeId];
7
- return !(e.some((s) => h.has(s)) || g.size > 0 && !e.some((s) => g.has(s)));
8
- }, v = (n, e) => e === n || I === null ? !0 : I.has(e), y = (n, e) => {
9
- !e || e.originTabId === S || v(n.$namespace, e.namespace) && e.storeId === n.$id && f(n) && n.$patch({ [e.key]: e.newValue }, "remote");
10
- }, w = () => {
11
- if (r = null, i.size === 0) return;
12
- const n = Array.from(i.values());
13
- i.clear();
14
- for (const e of n) {
15
- const s = {
16
- ...e,
17
- originTabId: S
18
- };
19
- if (t && t.postMessage(s), typeof window < "u" && "localStorage" in window)
20
- try {
21
- window.localStorage.setItem(a, JSON.stringify(s)), window.localStorage.removeItem(a);
22
- } catch {
23
- }
24
- }
25
- }, M = (n) => {
26
- if (i.set(`${n.scopeId}:${n.key}`, n), $ <= 0) {
27
- w();
28
- return;
29
- }
30
- r || (r = setTimeout(w, $));
31
- };
32
- return b({
33
- name: "sync",
34
- onInit(n) {
35
- const e = n;
36
- if (f(e)) {
37
- if (d.add(e.$scopeId), t) {
38
- const s = (o) => {
39
- y(e, o.data);
40
- };
41
- u.set(e.$scopeId, s), t.addEventListener("message", s);
42
- }
43
- if (typeof window < "u") {
44
- const s = (o) => {
45
- if (!(o.key !== a || !o.newValue))
46
- try {
47
- const H = JSON.parse(o.newValue);
48
- y(e, H);
49
- } catch {
50
- }
51
- };
52
- l.set(e.$scopeId, s), window.addEventListener("storage", s);
53
- }
54
- }
55
- },
56
- onMutation(n, e) {
57
- e.origin !== "remote" && f(n) && M(e);
58
- },
59
- onDispose(n) {
60
- const e = n;
61
- d.delete(e.$scopeId);
62
- const s = u.get(e.$scopeId);
63
- t && s && (t.removeEventListener("message", s), u.delete(e.$scopeId));
64
- const o = l.get(e.$scopeId);
65
- typeof window < "u" && o && (window.removeEventListener("storage", o), l.delete(e.$scopeId)), r && (clearTimeout(r), r = null), w(), d.size === 0 && (t == null || t.close());
66
- }
67
- });
1
+ import { definePlugin as e } from "@storix-js/core";
2
+ //#region src/index.ts
3
+ function t(t = {}) {
4
+ let n = t.channelName ?? "storix-sync", r = new Set(t.include ?? []), i = new Set(t.exclude ?? []), a = t.namespaces ?? [], o = a === "*" ? null : new Set(a), s = t.debounce ?? 16, c = globalThis.crypto?.randomUUID?.() ?? `storix-${Date.now()}-${Math.random().toString(36).slice(2)}`, l = `__storix_sync__:${n}`, u = /* @__PURE__ */ new Map(), d = /* @__PURE__ */ new Set(), f = /* @__PURE__ */ new Map(), p = /* @__PURE__ */ new Map(), m = null, h = null, g = () => (h || typeof window > "u" || typeof window.BroadcastChannel != "function" || (h = new window.BroadcastChannel(n)), h), _ = (e) => {
5
+ let t = [e.$id, e.$scopeId];
6
+ return !(t.some((e) => i.has(e)) || r.size > 0 && !t.some((e) => r.has(e)));
7
+ }, v = (e, t) => t === e || o === null || o.has(t), y = (e, t) => {
8
+ t && t.originTabId !== c && v(e.$namespace, t.namespace) && t.storeId === e.$id && _(e) && e.$patch({ [t.key]: t.newValue }, "remote");
9
+ }, b = () => {
10
+ if (m = null, u.size === 0) return;
11
+ let e = Array.from(u.values());
12
+ u.clear();
13
+ for (let t of e) {
14
+ let e = {
15
+ ...t,
16
+ originTabId: c
17
+ }, n = g();
18
+ if (n && n.postMessage(e), !n && typeof window < "u" && "localStorage" in window) try {
19
+ window.localStorage.setItem(l, JSON.stringify(e)), window.localStorage.removeItem(l);
20
+ } catch {}
21
+ }
22
+ }, x = (e) => {
23
+ if (u.set(`${e.scopeId}:${e.key}`, e), s <= 0) {
24
+ b();
25
+ return;
26
+ }
27
+ m ||= setTimeout(b, s);
28
+ };
29
+ return e({
30
+ name: "sync",
31
+ onInit(e) {
32
+ let t = e;
33
+ if (!_(t)) return;
34
+ d.add(t.$scopeId);
35
+ let n = g();
36
+ if (n) {
37
+ let e = (e) => {
38
+ y(t, e.data);
39
+ };
40
+ f.set(t.$scopeId, e), n.addEventListener("message", e);
41
+ }
42
+ if (typeof window < "u") {
43
+ let e = (e) => {
44
+ if (e.key === l && e.newValue) try {
45
+ let n = JSON.parse(e.newValue);
46
+ y(t, n);
47
+ } catch {}
48
+ };
49
+ p.set(t.$scopeId, e), window.addEventListener("storage", e);
50
+ }
51
+ },
52
+ onMutation(e, t) {
53
+ t.origin !== "remote" && _(e) && x(t);
54
+ },
55
+ onDispose(e) {
56
+ let t = e;
57
+ d.delete(t.$scopeId);
58
+ let n = f.get(t.$scopeId);
59
+ h && n && (h.removeEventListener("message", n), f.delete(t.$scopeId));
60
+ let r = p.get(t.$scopeId);
61
+ typeof window < "u" && r && (window.removeEventListener("storage", r), p.delete(t.$scopeId)), m &&= (clearTimeout(m), null), b(), d.size === 0 && (h?.close(), h = null);
62
+ }
63
+ });
68
64
  }
69
- export {
70
- E as syncPlugin
71
- };
65
+ //#endregion
66
+ export { t as syncPlugin };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@storix-js/sync",
3
- "version": "0.2.1",
3
+ "version": "0.3.0",
4
4
  "type": "module",
5
5
  "main": "./dist/index.cjs",
6
6
  "module": "./dist/index.js",
@@ -19,13 +19,13 @@
19
19
  "require": "./dist/index.cjs"
20
20
  }
21
21
  },
22
+ "dependencies": {
23
+ "@storix-js/core": "0.3.0"
24
+ },
22
25
  "scripts": {
23
26
  "build": "vite build && tsc -p tsconfig.build.json --emitDeclarationOnly",
24
27
  "dev": "vite build --watch",
25
28
  "test": "vitest run --passWithNoTests",
26
29
  "typecheck": "tsc -p tsconfig.json --noEmit"
27
- },
28
- "dependencies": {
29
- "@storix-js/core": "workspace:*"
30
30
  }
31
- }
31
+ }