@signaldb/sync
Advanced tools
Comparing version 1.0.1 to 1.1.0
@@ -1,5 +0,5 @@ | ||
(function(f,d){typeof exports=="object"&&typeof module<"u"?d(exports,require("@signaldb/core")):typeof define=="function"&&define.amd?define(["exports","@signaldb/core"],d):(f=typeof globalThis<"u"?globalThis:f||self,d(f.SignalDB={},f.core))})(this,function(f,d){"use strict";var S=Object.defineProperty;var I=(f,d,g)=>d in f?S(f,d,{enumerable:!0,configurable:!0,writable:!0,value:g}):f[d]=g;var p=(f,d,g)=>I(f,typeof d!="symbol"?d+"":d,g);function g(u,e,t={}){let a,s;const{leading:n=!1,trailing:i=!0}=t;function o(...l){const c=n&&!a,r=i&&!a;return a&&clearTimeout(a),a=setTimeout(()=>{a=null,i&&!c&&(s=u.apply(this,l))},e),c?s=u.apply(this,l):r||(s=null),s}return o}class v{constructor(){p(this,"queue",[]);p(this,"pendingPromise",!1)}add(e){return new Promise((t,a)=>{this.queue.push(()=>e().then(t).catch(s=>{throw a(s),s})),this.dequeue()})}hasPendingPromise(){return this.pendingPromise}dequeue(){if(this.pendingPromise||this.queue.length===0)return;const e=this.queue.shift();e&&(this.pendingPromise=!0,e().then(()=>{this.pendingPromise=!1,this.dequeue()}).catch(()=>{this.pendingPromise=!1,this.dequeue()}))}}function w(u,e){const t=[],a=[],s=[],n=new Map(u.map(o=>[o.id,o])),i=new Map(e.map(o=>[o.id,o]));for(const[o,l]of n){const c=i.get(o);c?d.isEqual(c,l)||a.push(c):s.push(l)}for(const[o,l]of i)n.has(o)||t.push(l);return{added:t,modified:a,removed:s}}function O(u,e){if(e.items!=null)return e.items;const t=u||[];return e.changes.added.forEach(a=>{const s=t.findIndex(n=>n.id===a.id);s===-1?t.push(a):t[s]=a}),e.changes.modified.forEach(a=>{const s=t.findIndex(n=>n.id===a.id);s===-1?t.push(a):t[s]=a}),e.changes.removed.forEach(a=>{const s=t.findIndex(n=>n.id===a.id);s!==-1&&t.splice(s,1)}),t}async function $(u,e){const t=new d.Collection;t.batch(()=>{u.forEach(s=>t.insert(s)),e.forEach(s=>{if(s.type==="remove"){t.removeOne({id:s.data});return}const n={id:s.data.id},i=t.findOne(n);if(s.type==="insert"){i?t.updateOne(n,{$set:s.data}):t.insert(s.data);return}i?t.updateOne(n,s.data.modifier):t.insert(d.modify(n,s.data.modifier))})});const a=t.find().fetch();return await t.dispose(),a}function N(u){return u.added.length>0||u.modified.length>0||u.removed.length>0}function D(u,e){return N(w(u,e))}async function P({changes:u,lastSnapshot:e,data:t,pull:a,push:s,insert:n,update:i,remove:o,batch:l}){let c=t,r=e||[],m=O(e,c);if(u.length>0){const h=await $(r,u);if(D(r,h)){const C=await $(m,u),E=w(m,C);N(E)&&(await s(E),c=await a(),m=O(m,c)),r=h}}const y=c.changes==null?w(r,c.items):c.changes;return l(()=>{y.added.forEach(h=>n(h)),y.modified.forEach(h=>i(h.id,{$set:h})),y.removed.forEach(h=>o(h.id))}),m}class M{constructor(e){p(this,"options");p(this,"collections",new Map);p(this,"changes");p(this,"snapshots");p(this,"syncOperations");p(this,"remoteChanges",[]);p(this,"syncQueues",new Map);p(this,"persistenceReady");p(this,"isDisposed",!1);p(this,"instanceId",d.randomId());p(this,"id");p(this,"deboucedPush",g(e=>{this.pushChanges(e).catch(()=>{})},100));this.options=e,this.id=this.options.id||"default-sync-manager";const{reactivity:t}=this.options,a=this.createPersistenceAdapter("changes"),s=this.createPersistenceAdapter("snapshots"),n=this.createPersistenceAdapter("sync-operations");this.changes=new d.Collection({name:`${this.options.id}-changes`,persistence:a==null?void 0:a.adapter,reactivity:t}),this.snapshots=new d.Collection({name:`${this.options.id}-snapshots`,persistence:s==null?void 0:s.adapter,reactivity:t}),this.syncOperations=new d.Collection({name:`${this.options.id}-sync-operations`,persistence:n==null?void 0:n.adapter,reactivity:t}),this.changes.on("persistence.error",i=>a==null?void 0:a.handler(i)),this.snapshots.on("persistence.error",i=>s==null?void 0:s.handler(i)),this.syncOperations.on("persistence.error",i=>n==null?void 0:n.handler(i)),this.persistenceReady=Promise.all([new Promise((i,o)=>{if(!a){i();return}this.syncOperations.once("persistence.error",o),this.syncOperations.once("persistence.init",i)}),new Promise((i,o)=>{if(!s){i();return}this.changes.once("persistence.error",o),this.changes.once("persistence.init",i)}),new Promise((i,o)=>{if(!n){i();return}this.snapshots.once("persistence.error",o),this.snapshots.once("persistence.init",i)})]).then(()=>{}),this.changes.setMaxListeners(1e3),this.snapshots.setMaxListeners(1e3),this.syncOperations.setMaxListeners(1e3)}createPersistenceAdapter(e){if(this.options.persistenceAdapter==null)return;let t=()=>{};return{adapter:this.options.persistenceAdapter(`${this.id}-${e}`,s=>{t=s}),handler:s=>t(s)}}getSyncQueue(e){return this.syncQueues.get(e)==null&&this.syncQueues.set(e,new v),this.syncQueues.get(e)}async dispose(){this.collections.clear(),this.syncQueues.clear(),this.remoteChanges.splice(0,this.remoteChanges.length),await Promise.all([this.changes.dispose(),this.snapshots.dispose(),this.syncOperations.dispose()]),this.isDisposed=!0}getCollection(e){const t=this.collections.get(e);if(t==null)throw new Error(`Collection with id '${e}' not found`);return t}addCollection(e,t){if(this.isDisposed)throw new Error("SyncManager is disposed");this.options.registerRemoteChange&&this.options.registerRemoteChange(t,async n=>{if(n==null)await this.sync(t.name);else{const i=Date.now(),o=this.syncOperations.insert({start:i,collectionName:t.name,instanceId:this.instanceId,status:"active"});await this.syncWithData(t.name,n).then(()=>{this.syncOperations.removeMany({id:{$ne:o},collectionName:t.name,$or:[{end:{$lte:i}},{status:"active"}]}),this.syncOperations.updateOne({id:o},{$set:{status:"done",end:Date.now()}})}).catch(l=>{throw this.options.onError&&this.options.onError(t,l),this.syncOperations.updateOne({id:o},{$set:{status:"error",end:Date.now(),error:l.stack||l.message}}),l})}}),this.collections.set(t.name,[e,t]);const a=n=>{for(const i of this.remoteChanges)if(d.isEqual(i,n))return!0;return!1},s=n=>{for(let i=0;i<this.remoteChanges.length;i+=1)if(d.isEqual(this.remoteChanges[i],n)){this.remoteChanges.splice(i,1);return}};e.on("added",n=>{if(a({collectionName:t.name,type:"insert",data:n})){s({collectionName:t.name,type:"insert",data:n});return}this.changes.insert({collectionName:t.name,time:Date.now(),type:"insert",data:n}),this.schedulePush(t.name)}),e.on("changed",({id:n},i)=>{const o={id:n,modifier:i};if(a({collectionName:t.name,type:"update",data:o})){s({collectionName:t.name,type:"update",data:o});return}this.changes.insert({collectionName:t.name,time:Date.now(),type:"update",data:o}),this.schedulePush(t.name)}),e.on("removed",({id:n})=>{if(a({collectionName:t.name,type:"remove",data:n})){s({collectionName:t.name,type:"remove",data:n});return}this.changes.insert({collectionName:t.name,time:Date.now(),type:"remove",data:n}),this.schedulePush(t.name)})}schedulePush(e){this.deboucedPush(e)}async syncAll(){if(this.isDisposed)throw new Error("SyncManager is disposed");const e=[];if(await Promise.all([...this.collections.keys()].map(t=>this.sync(t).catch(a=>{e.push({id:t,error:a})}))),e.length>0)throw new Error(`Error while syncing collections: | ||
(function(p,r){typeof exports=="object"&&typeof module<"u"?r(exports,require("@signaldb/core")):typeof define=="function"&&define.amd?define(["exports","@signaldb/core"],r):(p=typeof globalThis<"u"?globalThis:p||self,r(p.SignalDB={},p.core))})(this,function(p,r){"use strict";var M=Object.defineProperty;var I=(p,r,g)=>r in p?M(p,r,{enumerable:!0,configurable:!0,writable:!0,value:g}):p[r]=g;var u=(p,r,g)=>I(p,typeof r!="symbol"?r+"":r,g);function g(d,e,t={}){let s,n;const{leading:o=!1,trailing:a=!0}=t;function c(...l){const i=o&&!s,f=a&&!s;return s&&clearTimeout(s),s=setTimeout(()=>{s=null,a&&!i&&(n=d.apply(this,l))},e),i?n=d.apply(this,l):f||(n=null),n}return c}class N{constructor(){u(this,"queue",[]);u(this,"pendingPromise",!1)}add(e){return new Promise((t,s)=>{this.queue.push(()=>e().then(t).catch(n=>{throw s(n),n})),this.dequeue()})}hasPendingPromise(){return this.pendingPromise}dequeue(){if(this.pendingPromise||this.queue.length===0)return;const e=this.queue.shift();e&&(this.pendingPromise=!0,e().then(()=>{this.pendingPromise=!1,this.dequeue()}).catch(()=>{this.pendingPromise=!1,this.dequeue()}))}}function w(d,e){const t=[],s=[],n=[],o=new Map(d.map(c=>[c.id,c])),a=new Map(e.map(c=>[c.id,c]));for(const[c,l]of o){const i=a.get(c);i?r.isEqual(i,l)||s.push(i):n.push(l)}for(const[c,l]of a)o.has(c)||t.push(l);return{added:t,modified:s,removed:n}}function C(d,e){if(e.items!=null)return e.items;const t=d||[];return e.changes.added.forEach(s=>{const n=t.findIndex(o=>o.id===s.id);n===-1?t.push(s):t[n]=s}),e.changes.modified.forEach(s=>{const n=t.findIndex(o=>o.id===s.id);n===-1?t.push(s):t[n]=s}),e.changes.removed.forEach(s=>{const n=t.findIndex(o=>o.id===s.id);n!==-1&&t.splice(n,1)}),t}async function P(d,e){const t=new r.Collection;t.batch(()=>{d.forEach(n=>t.insert(n)),e.forEach(n=>{if(n.type==="remove"){t.removeOne({id:n.data});return}const o={id:n.data.id},a=t.findOne(o);if(n.type==="insert"){a?t.updateOne(o,{$set:n.data}):t.insert(n.data);return}a?t.updateOne(o,n.data.modifier):t.insert(r.modify(o,n.data.modifier))})});const s=t.find().fetch();return await t.dispose(),s}function O(d){return d.added.length>0||d.modified.length>0||d.removed.length>0}function E(d,e){return O(w(d,e))}async function v({changes:d,lastSnapshot:e,data:t,pull:s,push:n,insert:o,update:a,remove:c,batch:l}){let i=t,f=e||[],y=C(e,i);if(d.length>0){const m=await P(f,d);if(E(f,m)){const D=await P(y,d),$=w(y,D);O($)&&(await n($),i=await s(),y=C(y,i)),f=m}}const h=i.changes==null?w(f,i.items):i.changes;return l(()=>{h.added.forEach(m=>o(m)),h.modified.forEach(m=>a(m.id,{$set:m})),h.removed.forEach(m=>c(m.id))}),y}class S{constructor(e){u(this,"options");u(this,"collections",new Map);u(this,"changes");u(this,"snapshots");u(this,"syncOperations");u(this,"remoteChanges",[]);u(this,"syncQueues",new Map);u(this,"persistenceReady");u(this,"isDisposed",!1);u(this,"instanceId",r.randomId());u(this,"id");u(this,"deboucedPush",g(e=>{this.pushChanges(e).catch(()=>{})},100));this.options={autostart:!0,...e},this.id=this.options.id||"default-sync-manager";const{reactivity:t}=this.options,s=this.createPersistenceAdapter("changes"),n=this.createPersistenceAdapter("snapshots"),o=this.createPersistenceAdapter("sync-operations");this.changes=new r.Collection({name:`${this.options.id}-changes`,persistence:s==null?void 0:s.adapter,reactivity:t}),this.snapshots=new r.Collection({name:`${this.options.id}-snapshots`,persistence:n==null?void 0:n.adapter,reactivity:t}),this.syncOperations=new r.Collection({name:`${this.options.id}-sync-operations`,persistence:o==null?void 0:o.adapter,reactivity:t}),this.changes.on("persistence.error",a=>s==null?void 0:s.handler(a)),this.snapshots.on("persistence.error",a=>n==null?void 0:n.handler(a)),this.syncOperations.on("persistence.error",a=>o==null?void 0:o.handler(a)),this.persistenceReady=Promise.all([this.syncOperations.isReady(),this.changes.isReady(),this.snapshots.isReady()]).then(()=>{}),this.changes.setMaxListeners(1e3),this.snapshots.setMaxListeners(1e3),this.syncOperations.setMaxListeners(1e3)}createPersistenceAdapter(e){if(this.options.persistenceAdapter==null)return;let t=()=>{};return{adapter:this.options.persistenceAdapter(`${this.id}-${e}`,n=>{t=n}),handler:n=>t(n)}}getSyncQueue(e){return this.syncQueues.get(e)==null&&this.syncQueues.set(e,new N),this.syncQueues.get(e)}async dispose(){this.collections.clear(),this.syncQueues.clear(),this.remoteChanges.splice(0,this.remoteChanges.length),await Promise.all([this.changes.dispose(),this.snapshots.dispose(),this.syncOperations.dispose()]),this.isDisposed=!0}getCollection(e){const{collection:t,options:s}=this.getCollectionProperties(e);return[t,s]}getCollectionProperties(e){const t=this.collections.get(e);if(t==null)throw new Error(`Collection with id '${e}' not found`);return t}addCollection(e,t){if(this.isDisposed)throw new Error("SyncManager is disposed");this.collections.set(t.name,{collection:e,options:t,readyPromise:e.isReady(),syncPaused:!0});const s=o=>{for(const a of this.remoteChanges)if(r.isEqual(a,o))return!0;return!1},n=o=>{for(let a=0;a<this.remoteChanges.length;a+=1)if(r.isEqual(this.remoteChanges[a],o)){this.remoteChanges.splice(a,1);return}};e.on("added",o=>{if(s({collectionName:t.name,type:"insert",data:o})){n({collectionName:t.name,type:"insert",data:o});return}this.changes.insert({collectionName:t.name,time:Date.now(),type:"insert",data:o}),!this.getCollectionProperties(t.name).syncPaused&&this.schedulePush(t.name)}),e.on("changed",({id:o},a)=>{const c={id:o,modifier:a};if(s({collectionName:t.name,type:"update",data:c})){n({collectionName:t.name,type:"update",data:c});return}this.changes.insert({collectionName:t.name,time:Date.now(),type:"update",data:c}),!this.getCollectionProperties(t.name).syncPaused&&this.schedulePush(t.name)}),e.on("removed",({id:o})=>{if(s({collectionName:t.name,type:"remove",data:o})){n({collectionName:t.name,type:"remove",data:o});return}this.changes.insert({collectionName:t.name,time:Date.now(),type:"remove",data:o}),!this.getCollectionProperties(t.name).syncPaused&&this.schedulePush(t.name)}),this.options.autostart&&this.startSync(t.name).catch(o=>{this.options.onError&&this.options.onError(this.getCollectionProperties(t.name).options,o)})}schedulePush(e){this.deboucedPush(e)}async startAll(){await Promise.all([...this.collections.keys()].map(e=>this.startSync(e)))}async startSync(e){const t=this.getCollectionProperties(e);if(!t.syncPaused)return;this.schedulePush(e);const s=this.options.registerRemoteChange?await this.options.registerRemoteChange(t.options,async n=>{if(n==null)await this.sync(e);else{const o=Date.now(),a=this.syncOperations.insert({start:o,collectionName:e,instanceId:this.instanceId,status:"active"});await this.syncWithData(e,n).then(()=>{this.syncOperations.removeMany({id:{$ne:a},collectionName:e,$or:[{end:{$lte:o}},{status:"active"}]}),this.syncOperations.updateOne({id:a},{$set:{status:"done",end:Date.now()}})}).catch(c=>{throw this.options.onError&&this.options.onError(this.getCollectionProperties(e).options,c),this.syncOperations.updateOne({id:a},{$set:{status:"error",end:Date.now(),error:c.stack||c.message}}),c})}}):void 0;this.collections.set(e,{...t,syncPaused:!1,cleanupFunction:s})}async pauseAll(){await Promise.all([...this.collections.keys()].map(e=>this.pauseSync(e)))}async pauseSync(e){const t=this.getCollectionProperties(e);t.syncPaused||(t.cleanupFunction&&await t.cleanupFunction(),this.collections.set(e,{...t,cleanupFunction:void 0,syncPaused:!0}))}async syncAll(){if(this.isDisposed)throw new Error("SyncManager is disposed");const e=[];if(await Promise.all([...this.collections.keys()].map(t=>this.sync(t).catch(s=>{e.push({id:t,error:s})}))),e.length>0)throw new Error(`Error while syncing collections: | ||
${e.map(t=>`${t.id}: ${t.error.message}`).join(` | ||
`)}`)}isSyncing(e){return this.syncOperations.findOne({...e?{collectionName:e}:{},status:"active"},{fields:{status:1}})!=null}async isReady(){await this.persistenceReady}async sync(e,t={}){if(this.isDisposed)throw new Error("SyncManager is disposed");await this.isReady();const s=this.getCollection(e)[1],n=this.syncOperations.find({collectionName:e,instanceId:this.instanceId,status:"active"}).count()>0,i=Date.now();let o=null;await new Promise(c=>{setTimeout(c,0)});const l=async()=>{const c=this.syncOperations.findOne({collectionName:e,status:"done"},{sort:{end:-1}});if(t!=null&&t.onlyWithChanges&&this.changes.find({collectionName:e,$and:[{time:{$lte:i}}]},{sort:{time:1}}).count()===0)return;n||(o=this.syncOperations.insert({start:i,collectionName:e,instanceId:this.instanceId,status:"active"}));const r=await this.options.pull(s,{lastFinishedSyncStart:c==null?void 0:c.start,lastFinishedSyncEnd:c==null?void 0:c.end});await this.syncWithData(e,r)};await(t!=null&&t.force?l():this.getSyncQueue(e).add(l)).catch(c=>{throw o!=null&&(this.options.onError&&this.options.onError(s,c),this.syncOperations.updateOne({id:o},{$set:{status:"error",end:Date.now(),error:c.stack||c.message}})),c}),o!=null&&(this.syncOperations.removeMany({id:{$ne:o},collectionName:e,$or:[{end:{$lte:i}},{status:"active"}]}),this.syncOperations.updateOne({id:o},{$set:{status:"done",end:Date.now()}}))}async pushChanges(e){await this.sync(e,{onlyWithChanges:!0})}async syncWithData(e,t){const a=this.getCollection(e),[s,n]=a,i=Date.now(),o=this.syncOperations.findOne({collectionName:e,status:"done"},{sort:{end:-1}}),l=this.snapshots.findOne({collectionName:e},{sort:{time:-1}}),c=this.changes.find({collectionName:e,$and:[{time:{$lte:i}}]},{sort:{time:1}}).fetch();await P({changes:c,lastSnapshot:l==null?void 0:l.items,data:t,pull:()=>this.options.pull(n,{lastFinishedSyncStart:o==null?void 0:o.start,lastFinishedSyncEnd:o==null?void 0:o.end}),push:r=>this.options.push(n,{changes:r}),insert:r=>{if(r.id&&s.findOne({id:r.id})){this.remoteChanges.push({collectionName:e,type:"update",data:{id:r.id,modifier:{$set:r}}}),s.updateOne({id:r.id},{$set:r});return}this.remoteChanges.push({collectionName:e,type:"insert",data:r}),s.insert(r)},update:(r,m)=>{if(r&&!s.findOne({id:r})){const y={...m.$set,id:r};this.remoteChanges.push({collectionName:e,type:"insert",data:y}),s.insert(y);return}this.remoteChanges.push({collectionName:e,type:"update",data:{id:r,modifier:m}}),s.updateOne({id:r},m)},remove:r=>{s.findOne({id:r})&&(this.remoteChanges.push({collectionName:e,type:"remove",data:r}),s.removeOne({id:r}))},batch:r=>{s.batch(()=>{r()})}}).then(async r=>{if(this.snapshots.removeMany({collectionName:e,time:{$lte:i}}),this.changes.removeMany({collectionName:e,id:{$in:c.map(h=>h.id)}}),this.snapshots.insert({time:i,collectionName:e,items:r}),await new Promise(h=>{setTimeout(h,0)}),this.changes.find({collectionName:e}).count()>0){await this.sync(e,{force:!0,onlyWithChanges:!0});return}const y=s.find({id:{$nin:r.map(h=>h.id)}}).map(h=>h.id);s.batch(()=>{r.forEach(h=>{const C=!!s.findOne({id:h.id});/* istanbul ignore else -- @preserve */C?(this.remoteChanges.push({collectionName:e,type:"update",data:{id:h.id,modifier:{$set:h}}}),s.updateOne({id:h.id},{$set:h})):(this.remoteChanges.push({collectionName:e,type:"insert",data:h}),s.insert(h))}),y.forEach(h=>{s.removeOne({id:h})})})})}}f.SyncManager=M,Object.defineProperty(f,Symbol.toStringTag,{value:"Module"})}); | ||
`)}`)}isSyncing(e){return this.syncOperations.findOne({...e?{collectionName:e}:{},status:"active"},{fields:{status:1}})!=null}async isReady(){await this.persistenceReady}async sync(e,t={}){if(this.isDisposed)throw new Error("SyncManager is disposed");await this.isReady();const{options:s,readyPromise:n}=this.getCollectionProperties(e);await n;const o=this.syncOperations.find({collectionName:e,instanceId:this.instanceId,status:"active"}).count()>0,a=Date.now();let c=null;await new Promise(i=>{setTimeout(i,0)});const l=async()=>{const i=this.syncOperations.findOne({collectionName:e,status:"done"},{sort:{end:-1}});if(t!=null&&t.onlyWithChanges&&this.changes.find({collectionName:e,$and:[{time:{$lte:a}}]},{sort:{time:1}}).count()===0)return;o||(c=this.syncOperations.insert({start:a,collectionName:e,instanceId:this.instanceId,status:"active"}));const f=await this.options.pull(s,{lastFinishedSyncStart:i==null?void 0:i.start,lastFinishedSyncEnd:i==null?void 0:i.end});await this.syncWithData(e,f)};await(t!=null&&t.force?l():this.getSyncQueue(e).add(l)).catch(i=>{throw c!=null&&(this.options.onError&&this.options.onError(s,i),this.syncOperations.updateOne({id:c},{$set:{status:"error",end:Date.now(),error:i.stack||i.message}})),i}),c!=null&&(this.syncOperations.removeMany({id:{$ne:c},collectionName:e,$or:[{end:{$lte:a}},{status:"active"}]}),this.syncOperations.updateOne({id:c},{$set:{status:"done",end:Date.now()}}))}async pushChanges(e){await this.sync(e,{onlyWithChanges:!0})}async syncWithData(e,t){const{collection:s,options:n}=this.getCollectionProperties(e),o=Date.now(),a=this.syncOperations.findOne({collectionName:e,status:"done"},{sort:{end:-1}}),c=this.snapshots.findOne({collectionName:e},{sort:{time:-1}}),l=this.changes.find({collectionName:e,$and:[{time:{$lte:o}}]},{sort:{time:1}}).fetch();await v({changes:l,lastSnapshot:c==null?void 0:c.items,data:t,pull:()=>this.options.pull(n,{lastFinishedSyncStart:a==null?void 0:a.start,lastFinishedSyncEnd:a==null?void 0:a.end}),push:i=>this.options.push(n,{changes:i}),insert:i=>{if(i.id&&s.findOne({id:i.id})){this.remoteChanges.push({collectionName:e,type:"update",data:{id:i.id,modifier:{$set:i}}}),s.updateOne({id:i.id},{$set:i});return}this.remoteChanges.push({collectionName:e,type:"insert",data:i}),s.insert(i)},update:(i,f)=>{if(i&&!s.findOne({id:i})){const y={...f.$set,id:i};this.remoteChanges.push({collectionName:e,type:"insert",data:y}),s.insert(y);return}this.remoteChanges.push({collectionName:e,type:"update",data:{id:i,modifier:f}}),s.updateOne({id:i},f)},remove:i=>{s.findOne({id:i})&&(this.remoteChanges.push({collectionName:e,type:"remove",data:i}),s.removeOne({id:i}))},batch:i=>{s.batch(()=>{i()})}}).then(async i=>{if(this.snapshots.removeMany({collectionName:e,time:{$lte:o}}),this.changes.removeMany({collectionName:e,id:{$in:l.map(h=>h.id)}}),this.snapshots.insert({time:o,collectionName:e,items:i}),await new Promise(h=>{setTimeout(h,0)}),this.changes.find({collectionName:e}).count()>0){await this.sync(e,{force:!0,onlyWithChanges:!0});return}const y=s.find({id:{$nin:i.map(h=>h.id)}}).map(h=>h.id);s.batch(()=>{i.forEach(h=>{const m=!!s.findOne({id:h.id});/* istanbul ignore else -- @preserve */m?(this.remoteChanges.push({collectionName:e,type:"update",data:{id:h.id,modifier:{$set:h}}}),s.updateOne({id:h.id},{$set:h})):(this.remoteChanges.push({collectionName:e,type:"insert",data:h}),s.insert(h))}),y.forEach(h=>{s.removeOne({id:h})})})})}}p.SyncManager=S,Object.defineProperty(p,Symbol.toStringTag,{value:"Module"})}); | ||
//# sourceMappingURL=index.umd.js.map |
@@ -8,2 +8,3 @@ import type { BaseItem, PersistenceAdapter, ReactivityAdapter, Changeset, LoadResponse } from '@signaldb/core'; | ||
} & T; | ||
type CleanupFunction = (() => void | Promise<void>) | void; | ||
interface Options<CollectionOptions extends Record<string, any>, ItemType extends BaseItem<IdType> = BaseItem, IdType = any> { | ||
@@ -17,3 +18,3 @@ pull: (collectionOptions: SyncOptions<CollectionOptions>, pullParameters: { | ||
}) => Promise<void>; | ||
registerRemoteChange?: (collectionOptions: SyncOptions<CollectionOptions>, onChange: (data?: LoadResponse<ItemType>) => Promise<void>) => void; | ||
registerRemoteChange?: (collectionOptions: SyncOptions<CollectionOptions>, onChange: (data?: LoadResponse<ItemType>) => Promise<void>) => CleanupFunction | Promise<CleanupFunction>; | ||
id?: string; | ||
@@ -23,2 +24,3 @@ persistenceAdapter?: (id: string, registerErrorHandler: (handler: (error: Error) => void) => void) => PersistenceAdapter<any, any>; | ||
onError?: (collectionOptions: SyncOptions<CollectionOptions>, error: Error) => void; | ||
autostart?: boolean; | ||
} | ||
@@ -53,6 +55,9 @@ /** | ||
protected options: Options<CollectionOptions, ItemType, IdType>; | ||
protected collections: Map<string, [ | ||
Collection<ItemType, IdType, any>, | ||
SyncOptions<CollectionOptions> | ||
]>; | ||
protected collections: Map<string, { | ||
collection: Collection<ItemType, IdType, any>; | ||
options: SyncOptions<CollectionOptions>; | ||
readyPromise: Promise<void>; | ||
syncPaused: boolean; | ||
cleanupFunction?: CleanupFunction; | ||
}>; | ||
protected changes: Collection<Change<ItemType>, string>; | ||
@@ -89,2 +94,3 @@ protected snapshots: Collection<Snapshot<ItemType>, string>; | ||
* Gets a collection with it's options by name | ||
* @deprecated Use getCollectionProperties instead. | ||
* @param name Name of the collection | ||
@@ -94,4 +100,17 @@ * @throws Will throw an error if the name wasn't found | ||
*/ | ||
getCollection(name: string): [Collection<ItemType, IdType, any>, SyncOptions<CollectionOptions>]; | ||
getCollection(name: string): (Collection<ItemType, IdType, any> | SyncOptions<CollectionOptions>)[]; | ||
/** | ||
* Gets collection options by name | ||
* @param name Name of the collection | ||
* @throws Will throw an error if the name wasn't found | ||
* @returns An object of all properties of the collection | ||
*/ | ||
getCollectionProperties(name: string): { | ||
collection: Collection<ItemType, IdType, any>; | ||
options: SyncOptions<CollectionOptions>; | ||
readyPromise: Promise<void>; | ||
syncPaused: boolean; | ||
cleanupFunction?: CleanupFunction | undefined; | ||
}; | ||
/** | ||
* Adds a collection to the sync manager. | ||
@@ -106,2 +125,26 @@ * @param collection Collection to add | ||
/** | ||
* Setup all collections to be synced with remote changes | ||
* and enable automatic pushing changes to the remote source. | ||
*/ | ||
startAll(): Promise<void>; | ||
/** | ||
* Setup a collection to be synced with remote changes | ||
* and enable automatic pushing changes to the remote source. | ||
* @param name Name of the collection | ||
*/ | ||
startSync(name: string): Promise<void>; | ||
/** | ||
* Pauses the sync process for all collections. | ||
* This means that the collections will not be synced with remote changes | ||
* and changes will not automatically be pushed to the remote source. | ||
*/ | ||
pauseAll(): Promise<void>; | ||
/** | ||
* Pauses the sync process for a collection. | ||
* This means that the collection will not be synced with remote changes | ||
* and changes will not automatically be pushed to the remote source. | ||
* @param name Name of the collection | ||
*/ | ||
pauseSync(name: string): Promise<void>; | ||
/** | ||
* Starts the sync process for all collections | ||
@@ -108,0 +151,0 @@ */ |
{ | ||
"name": "@signaldb/sync", | ||
"version": "1.0.1", | ||
"version": "1.1.0", | ||
"description": "", | ||
@@ -55,4 +55,4 @@ "scripts": { | ||
"peerDependencies": { | ||
"@signaldb/core": "1.x" | ||
"@signaldb/core": "^1.2.0" | ||
} | ||
} |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
146568
938