Comparing version 2.2.0 to 2.3.0
@@ -26,3 +26,3 @@ /* | ||
2 August 2022 | ||
4 August 2022 | ||
@@ -54,5 +54,2 @@ */ | ||
let logging = options.logging || false; | ||
let idb_name = options.idb_name; | ||
let storeName = options.storeName; | ||
let QOper8 = options.QOper8; | ||
@@ -70,13 +67,9 @@ if (index && !index.transforms && !index.props) index = false; | ||
if (!options.DPP) { | ||
let {DPP} = await import('https://robtweed.github.io/DPP/src/dpp.min.js'); | ||
options.DPP = DPP; | ||
} | ||
const obj = new KV(); | ||
let dpp = await options.DPP.create({ | ||
idb_name: idb_name, | ||
storeName: storeName, | ||
let dpp = new options.DPP({ | ||
idb_name: options.idb_name, | ||
storeName: options.storeName, | ||
logging: logging, | ||
QOper8: QOper8 | ||
QOper8: options.QOper8, | ||
qOptions: options.qOptions | ||
}); | ||
@@ -112,3 +105,3 @@ | ||
obj.storeName = storeName; | ||
obj.storeName = options.storeName; | ||
return obj; | ||
@@ -115,0 +108,0 @@ } |
@@ -1,1 +0,1 @@ | ||
let KV=class{constructor(){this.listeners=new Map,this.transforms={toLowerCase:function(e){return e.toLowerCase()},toString:function(e){return e.toString()},toInteger:function(e){return parseInt(e)},removePunctuation:function(e){return e.replace(/[^\w\s\']|_/g,"").replace(/\s+/g," ")}}}static async start(e){let t=e.index,s=e.logging||!1,i=e.idb_name,r=e.storeName,n=e.QOper8;if(!t||t.transforms||t.props||(t=!1),t&&(t.transforms&&(Array.isArray(t.transforms)||(t.transforms=[t.transforms])),t.props&&(Array.isArray(t.props)||(t.props=[t.props]))),!e.DPP){let{DPP:t}=await import("https://robtweed.github.io/DPP/src/dpp.min.js");e.DPP=t}const o=new KV;let d=await e.DPP.create({idb_name:i,storeName:r,logging:s,QOper8:n});if(o.DPP=d,o.store=await d.start(),o.store.data){(JSON.stringify(t)||"false")!==(JSON.stringify(o.store.indexing)||"false")&&(t?(o.store.indexing=t,t||delete o.store.indexing,o.reIndex()):(delete o.store.index,delete o.store.indexing))}else o.store.data={},t&&(o.store.indexing=t);return o.storeName=r,o}getIndexKey(e){if(this.store.indexing){if("object"==typeof e){if(this.store.indexing.props){let t=[];for(const s in e)if(this.store.indexing.props.includes(s)){let i=this.getIndexKey(e[s]);i&&t.push({prop:s,value:i})}return 0!==t.length&&t}return!1}if(this.store.indexing.transforms)for(const t of this.store.indexing.transforms)this.transforms[t]&&(e=this.transforms[t](e));return e}return!1}addIndex(e,t,s,i){if(this.store.index||(this.store.index={}),void 0===this.store.index[e]&&(this.store.index[e]={}),s){let i={};i[s]=!0,this.store.index[e][t]=i}else this.store.index[e][t]=!0}set(e,t,s){this.store.data[e]=t;let i=this.getIndexKey(t);if(i)if(Array.isArray(i))for(const t of i)this.addIndex(t.value,e,t.prop);else this.addIndex(i,e,null)}get(e){return this.store.data[e]}getByIndex(e,t){let s=[],i=this.getIndexKey(e);if(i)for(const e in this.store.index[i])if(t){let t={key:e,data:this.get(e)};s.push(t)}else s.push(e);return s}search(e,t){let s=[],i=this.getIndexKey(e);if(i)for(const e in this.store.index)if(e.includes(i)){let i=this.getByIndex(e,t);s=s.concat(i)}return s}has(e){return void 0!==this.store.data[e]}deleteIndex(e,t,s,i){s?(delete this.store.index[e][t][s],this.DPP.isEmpty(this.store.index[e][t])&&delete this.store.index[e][t]):delete this.store.index[e][t],this.DPP.isEmpty(this.store.index[e])&&delete this.store.index[e]}delete(e,t){if(this.has(e)){let t=this.getIndexKey(this.get(e));if(t)if(Array.isArray(t))for(const s of t)this.deleteIndex(s.value,e,s.prop);else this.deleteIndex(t,e,null);delete this.store.data[e]}}reIndex(){delete this.store.index;for(const e in this.store.data){let t=this.get(e);this.set(e,t)}}get hasKeys(){for(const e in this.store.data)return!0;return!1}get isEmpty(){return!this.hasKeys}clear(){for(const e in this.store.data)this.delete(e)}dump(){return JSON.stringify(this.store,null,2)}on(e,t){this.listeners.has(e)||this.listeners.set(e,t)}off(e){this.listeners.has(e)&&this.listeners.delete(e)}emit(e,t){if(this.listeners.has(e)){this.listeners.get(e).call(this,t)}}};export{KV}; | ||
let KV=class{constructor(){this.listeners=new Map,this.transforms={toLowerCase:function(e){return e.toLowerCase()},toString:function(e){return e.toString()},toInteger:function(e){return parseInt(e)},removePunctuation:function(e){return e.replace(/[^\w\s\']|_/g,"").replace(/\s+/g," ")}}}static async start(e){let t=e.index,s=e.logging||!1;!t||t.transforms||t.props||(t=!1),t&&(t.transforms&&(Array.isArray(t.transforms)||(t.transforms=[t.transforms])),t.props&&(Array.isArray(t.props)||(t.props=[t.props])));const r=new KV;let i=new e.DPP({idb_name:e.idb_name,storeName:e.storeName,logging:s,QOper8:e.QOper8,qOptions:e.qOptions});if(r.DPP=i,r.store=await i.start(),r.store.data){(JSON.stringify(t)||"false")!==(JSON.stringify(r.store.indexing)||"false")&&(t?(r.store.indexing=t,t||delete r.store.indexing,r.reIndex()):(delete r.store.index,delete r.store.indexing))}else r.store.data={},t&&(r.store.indexing=t);return r.storeName=e.storeName,r}getIndexKey(e){if(this.store.indexing){if("object"==typeof e){if(this.store.indexing.props){let t=[];for(const s in e)if(this.store.indexing.props.includes(s)){let r=this.getIndexKey(e[s]);r&&t.push({prop:s,value:r})}return 0!==t.length&&t}return!1}if(this.store.indexing.transforms)for(const t of this.store.indexing.transforms)this.transforms[t]&&(e=this.transforms[t](e));return e}return!1}addIndex(e,t,s,r){if(this.store.index||(this.store.index={}),void 0===this.store.index[e]&&(this.store.index[e]={}),s){let r={};r[s]=!0,this.store.index[e][t]=r}else this.store.index[e][t]=!0}set(e,t,s){this.store.data[e]=t;let r=this.getIndexKey(t);if(r)if(Array.isArray(r))for(const t of r)this.addIndex(t.value,e,t.prop);else this.addIndex(r,e,null)}get(e){return this.store.data[e]}getByIndex(e,t){let s=[],r=this.getIndexKey(e);if(r)for(const e in this.store.index[r])if(t){let t={key:e,data:this.get(e)};s.push(t)}else s.push(e);return s}search(e,t){let s=[],r=this.getIndexKey(e);if(r)for(const e in this.store.index)if(e.includes(r)){let r=this.getByIndex(e,t);s=s.concat(r)}return s}has(e){return void 0!==this.store.data[e]}deleteIndex(e,t,s,r){s?(delete this.store.index[e][t][s],this.DPP.isEmpty(this.store.index[e][t])&&delete this.store.index[e][t]):delete this.store.index[e][t],this.DPP.isEmpty(this.store.index[e])&&delete this.store.index[e]}delete(e,t){if(this.has(e)){let t=this.getIndexKey(this.get(e));if(t)if(Array.isArray(t))for(const s of t)this.deleteIndex(s.value,e,s.prop);else this.deleteIndex(t,e,null);delete this.store.data[e]}}reIndex(){delete this.store.index;for(const e in this.store.data){let t=this.get(e);this.set(e,t)}}get hasKeys(){for(const e in this.store.data)return!0;return!1}get isEmpty(){return!this.hasKeys}clear(){for(const e in this.store.data)this.delete(e)}dump(){return JSON.stringify(this.store,null,2)}on(e,t){this.listeners.has(e)||this.listeners.set(e,t)}off(e){this.listeners.has(e)&&this.listeners.delete(e)}emit(e,t){if(this.listeners.has(e)){this.listeners.get(e).call(this,t)}}};export{KV}; |
@@ -9,6 +9,7 @@ (async () => { | ||
//const {KV} = await import('./dpp-kv.js'); | ||
//const {createKV} = await import('./dpp-kv_browser.js'); | ||
const {KV} = await import('https://robtweed.github.io/DPP/db/key-value-store/dpp-kv.min.js'); | ||
const {createKV} = await import('https://robtweed.github.io/DPP/db/key-value-store/dpp-kv_browser.js'); | ||
let tel = await KV.start({ | ||
let tel = await createKV({ | ||
storeName: 'telephone', | ||
@@ -23,4 +24,2 @@ index: { | ||
//qOptions: { | ||
// handlerPath: '/dpp/js/idb_handlers', | ||
// workerLoaderPath: '/dpp/js/' | ||
// logging: true | ||
@@ -27,0 +26,0 @@ //}, |
@@ -26,3 +26,3 @@ /* | ||
2 August 2022 | ||
4 August 2022 | ||
@@ -38,17 +38,10 @@ */ | ||
let logging = options.logging || false; | ||
let idb_name = options.idb_name; | ||
let storeName = options.storeName; | ||
let QOper8 = options.QOper8; | ||
if (!options.DPP) { | ||
let {DPP} = await import('https://robtweed.github.io/DPP/src/dpp.min.js'); | ||
options.DPP = DPP; | ||
} | ||
const obj = new LIST(); | ||
let dpp = await options.DPP.create({ | ||
idb_name: idb_name, | ||
storeName: storeName, | ||
let dpp = new options.DPP({ | ||
idb_name: options.idb_name, | ||
storeName: options.storeName, | ||
logging: logging, | ||
QOper8: QOper8 | ||
QOper8: options.QOper8, | ||
qOptions: options.qOptions | ||
}); | ||
@@ -67,3 +60,3 @@ | ||
obj.storeName = storeName; | ||
obj.storeName = options.storeName; | ||
return obj; | ||
@@ -70,0 +63,0 @@ } |
@@ -1,1 +0,1 @@ | ||
let LIST=class{constructor(){this.listeners=new Map}static async start(e){let t=e.logging||!1,o=e.idb_name,n=e.storeName,r=e.QOper8;if(!e.DPP){let{DPP:t}=await import("https://robtweed.github.io/DPP/src/dpp.min.js");e.DPP=t}const s=new LIST;let d=await e.DPP.create({idb_name:o,storeName:n,logging:t,QOper8:r});return s.DPP=d,s.store=await d.start(),d.isEmpty(s.store)&&(s.store.nextNodeNo=0,s.store.count=0,s.store.node={}),s.storeName=n,s}rpush(e){if(!e)return!1;let t=this.store,o=0===t.count,n=t.nextNodeNo+1;if(t.nextNodeNo=n,t.count++,t.node||(t.node={}),t.node[n]={},t.node[n].content=e,o)t.firstNode=n,t.lastNode=n;else{let e=t.lastNode;t.lastNode=n,t.node[n].previousNode=e,t.node[e].nextNode=n}return n}lpush(e){if(!e)return!1;let t=this.store,o=0===t.count,n=t.nextNodeNo+1;if(t.nextNodeNo=n,t.count++,t.node||(this.store.node={}),t.node[n]={},t.node[n].content=e,o)t.firstNode=n,t.lastNode=n;else{let e=t.firstNode;t.firstNode=n,t.node[n].nextNode=e,t.node[e].previousNode=n}return n}get rpop(){let e=this.store;if(this.DPP.isEmpty(e))return{};if(0===e.count)return{};let t=e.lastNode;if(!e.node[t])return{};let o=e.node[t].content,n=e.count;if(1===n)e.count=0,e.nextNodeNo=0,delete e.node,delete e.firstNode,delete e.lastNode;else{let o=e.node[t].previousNode;e.lastNode=o,delete e.node[o].nextNode,delete e.node[t],e.count=n-1}return o}get lpop(){let e=this.store;if(this.DPP.isEmpty(e))return{};if(0===e.count)return{};let t=e.firstNode;if(!e.node[t])return{};let o=e.node[t].content,n=e.count;if(1===n)e.count=0,e.nextNodeNo=0,delete e.node,delete e.firstNode,delete e.lastNode;else{let o=e.node[t].nextNode;e.firstNode=o,delete e.node[o].previousNode,delete e.node[t],e.count=n-1}return o}lrange(e,t){let o=this.store,n=[];if(this.DPP.isEmpty(o))return n;if(0===o.count)return n;void 0!==e&&void 0===t&&(t=e),void 0===e&&(e=0),void 0===t&&(t=-1);let r=-1;function s(s){return++r>=e&&n.push(o.node[s].content),t!==r&&s!==o.lastNode&&o.node[s].nextNode}let d=o.firstNode;for(;d;)d=s(d);return n}ltrim(e,t){let o=this.store;if(this.DPP.isEmpty(o))return!1;if(0===o.count)return!1;void 0!==e&&void 0===t&&(t=e),void 0===e&&(e=0),void 0===t&&(t=-1);let n=-1;function r(e){let t=o.node[e].previousNode,n=o.node[e].nextNode;return delete o.node[e],o.count=o.count-1,t&&n?(o.node[t].nextNode=n,void(o.node[n].previousNode=t)):t||n?t?(o.lastNode=t,void delete o.node[t].nextNode):(o.firstNode=n,void delete o.node[n].previousNode):(delete o.firstNode,void delete o.lastNode)}function s(s){n++;let d=o.node[s].nextNode;return n<e?(r(s),0!==o.count&&d):-1!==t&&n>t?(r(s),0!==o.count&&d):s!==o.lastNode&&d}let d=o.firstNode;for(;d;)d=s(d);return!0}count(){return this.store.count}get length(){return this.store.count}get isEmpty(){return 0===this.length}insertBefore(e,t){if(!e)return!1;if(!t)return this.lpush(e);let o=this.store;if(this.DPP.isEmpty(o))return this.rpush(e);let n=this.getMemberId(t);if(!n)return this.rpush(e);let r=o.nextNodeNo+1;o.nextNodeNo=r,o.count=o.count+1,o.node||(this.store.node={}),o.node[r]={},o.node[r].content=e,o.node[r].nextNode=n;let s=o.node[n].previousNode;return s?(o.node[n].previousNode=r,o.node[r].previousNode=s,o.node[s].nextNode=r):o.firstNode=r,r}getMemberId(e){let t=this.store;if(this.DPP.isEmpty(t))return!1;if(0===t.count)return!1;if(t.count<e)return!1;let o=-1,n=!1;function r(r){return e===++o?(n=r,""):r===t.lastNode?"":t.node[r].nextNode}let s=t.firstNode;for(;""!==s;)s=r(s);return n}clear(){let e=this.length+1;this.ltrim(e,-1),this.store.nextNodeNo=0}dump(){return JSON.stringify(this.store,null,2)}on(e,t){this.listeners.has(e)||this.listeners.set(e,t)}off(e){this.listeners.has(e)&&this.listeners.delete(e)}emit(e,t){if(this.listeners.has(e)){this.listeners.get(e).call(this,t)}}};export{LIST}; | ||
let LIST=class{constructor(){this.listeners=new Map}static async start(e){let t=e.logging||!1;const o=new LIST;let n=new e.DPP({idb_name:e.idb_name,storeName:e.storeName,logging:t,QOper8:e.QOper8,qOptions:e.qOptions});return o.DPP=n,o.store=await n.start(),n.isEmpty(o.store)&&(o.store.nextNodeNo=0,o.store.count=0,o.store.node={}),o.storeName=e.storeName,o}rpush(e){if(!e)return!1;let t=this.store,o=0===t.count,n=t.nextNodeNo+1;if(t.nextNodeNo=n,t.count++,t.node||(t.node={}),t.node[n]={},t.node[n].content=e,o)t.firstNode=n,t.lastNode=n;else{let e=t.lastNode;t.lastNode=n,t.node[n].previousNode=e,t.node[e].nextNode=n}return n}lpush(e){if(!e)return!1;let t=this.store,o=0===t.count,n=t.nextNodeNo+1;if(t.nextNodeNo=n,t.count++,t.node||(this.store.node={}),t.node[n]={},t.node[n].content=e,o)t.firstNode=n,t.lastNode=n;else{let e=t.firstNode;t.firstNode=n,t.node[n].nextNode=e,t.node[e].previousNode=n}return n}get rpop(){let e=this.store;if(this.DPP.isEmpty(e))return{};if(0===e.count)return{};let t=e.lastNode;if(!e.node[t])return{};let o=e.node[t].content,n=e.count;if(1===n)e.count=0,e.nextNodeNo=0,delete e.node,delete e.firstNode,delete e.lastNode;else{let o=e.node[t].previousNode;e.lastNode=o,delete e.node[o].nextNode,delete e.node[t],e.count=n-1}return o}get lpop(){let e=this.store;if(this.DPP.isEmpty(e))return{};if(0===e.count)return{};let t=e.firstNode;if(!e.node[t])return{};let o=e.node[t].content,n=e.count;if(1===n)e.count=0,e.nextNodeNo=0,delete e.node,delete e.firstNode,delete e.lastNode;else{let o=e.node[t].nextNode;e.firstNode=o,delete e.node[o].previousNode,delete e.node[t],e.count=n-1}return o}lrange(e,t){let o=this.store,n=[];if(this.DPP.isEmpty(o))return n;if(0===o.count)return n;void 0!==e&&void 0===t&&(t=e),void 0===e&&(e=0),void 0===t&&(t=-1);let r=-1;function s(s){return++r>=e&&n.push(o.node[s].content),t!==r&&s!==o.lastNode&&o.node[s].nextNode}let d=o.firstNode;for(;d;)d=s(d);return n}ltrim(e,t){let o=this.store;if(this.DPP.isEmpty(o))return!1;if(0===o.count)return!1;void 0!==e&&void 0===t&&(t=e),void 0===e&&(e=0),void 0===t&&(t=-1);let n=-1;function r(e){let t=o.node[e].previousNode,n=o.node[e].nextNode;return delete o.node[e],o.count=o.count-1,t&&n?(o.node[t].nextNode=n,void(o.node[n].previousNode=t)):t||n?t?(o.lastNode=t,void delete o.node[t].nextNode):(o.firstNode=n,void delete o.node[n].previousNode):(delete o.firstNode,void delete o.lastNode)}function s(s){n++;let d=o.node[s].nextNode;return n<e?(r(s),0!==o.count&&d):-1!==t&&n>t?(r(s),0!==o.count&&d):s!==o.lastNode&&d}let d=o.firstNode;for(;d;)d=s(d);return!0}count(){return this.store.count}get length(){return this.store.count}get isEmpty(){return 0===this.length}insertBefore(e,t){if(!e)return!1;if(!t)return this.lpush(e);let o=this.store;if(this.DPP.isEmpty(o))return this.rpush(e);let n=this.getMemberId(t);if(!n)return this.rpush(e);let r=o.nextNodeNo+1;o.nextNodeNo=r,o.count=o.count+1,o.node||(this.store.node={}),o.node[r]={},o.node[r].content=e,o.node[r].nextNode=n;let s=o.node[n].previousNode;return s?(o.node[n].previousNode=r,o.node[r].previousNode=s,o.node[s].nextNode=r):o.firstNode=r,r}getMemberId(e){let t=this.store;if(this.DPP.isEmpty(t))return!1;if(0===t.count)return!1;if(t.count<e)return!1;let o=-1,n=!1;function r(r){return e===++o?(n=r,""):r===t.lastNode?"":t.node[r].nextNode}let s=t.firstNode;for(;""!==s;)s=r(s);return n}clear(){let e=this.length+1;this.ltrim(e,-1),this.store.nextNodeNo=0}dump(){return JSON.stringify(this.store,null,2)}on(e,t){this.listeners.has(e)||this.listeners.set(e,t)}off(e){this.listeners.has(e)&&this.listeners.delete(e)}emit(e,t){if(this.listeners.has(e)){this.listeners.get(e).call(this,t)}}};export{LIST}; |
@@ -5,5 +5,5 @@ (async () => { | ||
const {LIST} = await import('https://robtweed.github.io/DPP/db/key-value-store/dpp-list.min.js'); | ||
const {createLIST} = await import('https://robtweed.github.io/DPP/db/list-store/dpp-list_browser.js'); | ||
let myList = await LIST.start({ | ||
let myList = await createLIST({ | ||
storeName: 'demo-list' | ||
@@ -10,0 +10,0 @@ }); |
(async () => { | ||
const {DPP} = await import('../src/dpp.js'); | ||
const {createDPP} = await import('../src/dpp_browser.js'); | ||
let dpp = await DPP.create({ | ||
let dpp = await createDPP({ | ||
storeName: 'po_a', | ||
@@ -12,2 +12,3 @@ logging: true, | ||
}); | ||
let a = await dpp.start(); | ||
@@ -14,0 +15,0 @@ |
65
KV.md
@@ -29,3 +29,3 @@ # A Key/Value Store Implemented Using DPP | ||
Next, we'll create the *kv.js* module that the page above will load. For simplicity we'll load the DPP Key/Value Store module directly from its Github repository, but you can modify the code below to load your own local copy: | ||
Next, we'll create the *kv.js* module that the page above will load. For simplicity we'll load the DPP Key/Value Store creation module directly from its Github repository, but you can modify the code below to load your own local copy: | ||
@@ -37,5 +37,5 @@ | ||
const {KV} = await import('https://robtweed.github.io/DPP/db/key-value-store/dpp-kv.min.js'); | ||
const {createKV} = await import('https://robtweed.github.io/DPP/db/key-value-store/dpp-kv_browser.js'); | ||
let tel = await KV.start({ | ||
let tel = await createKV({ | ||
storeName: 'telephone' | ||
@@ -59,4 +59,4 @@ }); | ||
console.log('Key/Value Store Using DPP'); | ||
const {KV} = await import('https://robtweed.github.io/DPP/db/key-value-store/dpp-kv.min.js'); | ||
let tel = await KV.start({ | ||
const {createKV} = await import('https://robtweed.github.io/DPP/db/key-value-store/dpp-kv_browser.js'); | ||
let tel = await createKV({ | ||
storeName: 'telephone' | ||
@@ -96,4 +96,4 @@ }); | ||
console.log('Key/Value Store Using DPP'); | ||
const {KV} = await import('https://robtweed.github.io/DPP/db/key-value-store/dpp-kv.min.js'); | ||
let tel = await KV.start({ | ||
const {createKV} = await import('https://robtweed.github.io/DPP/db/key-value-store/dpp-kv_browser.js'); | ||
let tel = await createKV({ | ||
storeName: 'telephone' | ||
@@ -136,4 +136,4 @@ }); | ||
console.log('Key/Value Store Using DPP'); | ||
const {KV} = await import('https://robtweed.github.io/DPP/db/key-value-store/dpp-kv.min.js'); | ||
let tel = await KV.start({ | ||
const {createKV} = await import('https://robtweed.github.io/DPP/db/key-value-store/dpp-kv_browser.js'); | ||
let tel = await createKV({ | ||
storeName: 'telephone' | ||
@@ -175,3 +175,3 @@ }); | ||
let tel = await KV.start({ | ||
let tel = await createKV({ | ||
storeName: 'telephone', | ||
@@ -220,3 +220,3 @@ index: true | ||
let tel = await KV.start({ | ||
let tel = await createKV({ | ||
storeName: 'telephone', | ||
@@ -230,3 +230,3 @@ index: { | ||
let tel = await KV.start({ | ||
let tel = await createKV({ | ||
storeName: 'telephone', | ||
@@ -247,3 +247,3 @@ index: { | ||
let tel = await KV.start({ | ||
let tel = await createKV({ | ||
storeName: 'telephone', | ||
@@ -257,3 +257,3 @@ index: { | ||
let tel = await KV.start({ | ||
let tel = await createKV({ | ||
storeName: 'telephone', | ||
@@ -303,13 +303,15 @@ index: { | ||
The example shown above used a copy of the DPP Key/Value Store module from this Github repository. It will have also used copies from Github for *QOper8* and *DPP*. | ||
The example shown above used a copy of the DPP Key/Value Store creation module from this Github repository. Behind the scenes, it will have also used copies from Github for the actual *KV* class module, as well as *QOper8* and *DPP*. | ||
The example also used the default *indexedDB* database store name of "DPP". | ||
If you want to use local copies for the Key/Value store, QOper8 and DPP Modules, use the same options as documented for instantiating DPP itself, eg: | ||
## Using Local Copies of the Resources Used by the Key/Value Store | ||
If you want to use local copies for the Key/Value store, QOper8 and DPP Modules, use the same options as documented for instantiating DPP itself, and then use the *KV* module's *start* method: | ||
const {KV} = await import('./dpp/dpp-kv.js'); | ||
const {DPP} = await import('./dpp/dpp.js'); | ||
const {QOper8} = await import('./qoper8/qoper8.js'); | ||
const {KV} = await import('/path/to/dpp-kv.js'); | ||
const {DPP} = await import('/path/to/dpp.js'); | ||
const {QOper8} = await import('/path/to/qoper8.js'); | ||
let tel = await KV.start({ | ||
@@ -339,1 +341,26 @@ storeName: 'telephone', | ||
## Using the Key/Value Store with Node.js and NPM | ||
If you're building your front-end application using Node.js and WebPack (or equivalent), you need to use a slightly different approach. | ||
First, make sure that you've installed DPP: | ||
npm install dpp-db | ||
Then use the following: | ||
import {createKV} from 'dbb-db/createKV'; | ||
let tel = await createKV({ | ||
storeName: 'telephone', | ||
index: { | ||
transforms: ['toLowerCase', 'removePunctuation'] | ||
} | ||
}); | ||
...etc | ||
Behind the scenes, the *createKV* module will import the *KV*, *DPP* and *QOper8* modules from your *node_modules* folder. | ||
57
LIST.md
@@ -35,6 +35,6 @@ # A Redis-like List Store Implemented Using DPP | ||
console.log('Redis-like List Store Using DPP'); | ||
const {createLIST} = await import('https://robtweed.github.io/DPP/db/list-store/dpp-list_browser.js'); | ||
const {LIST} = await import('https://robtweed.github.io/DPP/db/key-value-store/dpp-list.min.js'); | ||
let myList = await LIST.start({ | ||
let myList = await createLIST({ | ||
storeName: 'demo-list' | ||
@@ -125,5 +125,5 @@ }); | ||
const {LIST} = await import('https://robtweed.github.io/DPP/db/key-value-store/dpp-list.min.js'); | ||
const {createLIST} = await import('https://robtweed.github.io/DPP/db/list-store/dpp-list_browser.js'); | ||
let myList = await LIST.start({ | ||
let myList = await createLIST({ | ||
storeName: 'demo-list' | ||
@@ -202,16 +202,17 @@ }); | ||
The example shown above used a copy of the DPP List Store module from this Github repository. It will have also used copies from Github for *QOper8* and *DPP*. | ||
The example shown above used a copy of the DPP LIST Store creation module from this Github repository. Behind the scenes, it will have also used copies from Github for the actual *LIST* class module, as well as *QOper8* and *DPP*. | ||
The example also used the default *indexedDB* database store name of "DPP". | ||
If you want to use local copies for the List store, QOper8 and DPP Modules, use the same options as documented for instantiating DPP itself, eg: | ||
## Using Local Copies of the Resources Used by the List Store | ||
If you want to use local copies for the List store, QOper8 and DPP Modules, use the same options as documented for instantiating DPP itself, but use the *LIST* module's *start* method: | ||
const {LIST} = await import('./dpp/dpp-list.js'); | ||
const {DPP} = await import('./dpp/dpp.js'); | ||
const {QOper8} = await import('./qoper8/qoper8.js'); | ||
const {LIST} = await import('/path/to/dpp-kv.js'); | ||
const {DPP} = await import('/path/to/dpp.js'); | ||
const {QOper8} = await import('/path/to/qoper8.js'); | ||
let myList = await LIST.start({ | ||
storeName: 'list-demo', | ||
storeName: 'demo-list', | ||
DPP: DPP, | ||
@@ -225,3 +226,3 @@ QOper8: QOper8 | ||
let myList = await LIST.start({ | ||
storeName: 'list-demo', | ||
storeName: 'demo-list', | ||
@@ -232,2 +233,32 @@ idb_name: 'myIDBStore' | ||
or, if using the *createLIST* module: | ||
let myList = await createLIST({ | ||
storeName: 'demo-list', | ||
idb_name: 'myIDBStore' | ||
}); | ||
## Using the List Store with Node.js and NPM | ||
If you're building your front-end application using Node.js and WebPack (or equivalent), you need to use a slightly different approach. | ||
First, make sure that you've installed DPP: | ||
npm install dpp-db | ||
Then use the following: | ||
import {createLIST} from 'dbb-db/createLIST'; | ||
let myList = await createLIST({ | ||
storeName: 'demo-list', | ||
idb_name: 'myIDBStore' | ||
}); | ||
...etc | ||
Behind the scenes, the *createLIST* module will import the *LIST*, *DPP* and *QOper8* modules from your *node_modules* folder. | ||
{ | ||
"name": "dpp-db", | ||
"version": "2.2.0", | ||
"version": "2.3.0", | ||
"description": "Deep Persistent Proxy: Persistent Objects in your Browser", | ||
@@ -9,3 +9,8 @@ "type": "module", | ||
"exports": { | ||
".": "./src/dpp.js" | ||
".": "./src/dpp.js", | ||
"./node": "./src/dpp_node.js", | ||
"./createKV": "./db/key-value-store/dpp-kv_node.js", | ||
"./KV": "./db/key-value-store/dpp-kv.js", | ||
"./createLIST": "./db/list-store/dpp-list_node.js", | ||
"./LIST": "./db/list-store/dpp-list.js" | ||
}, | ||
@@ -12,0 +17,0 @@ "scripts": { |
203
README.md
@@ -84,7 +84,9 @@ # DPP: Deep Persistent Proxy Objects for JavaScript | ||
DPP is designed so that it can be used whether you build your front-end code manually, or build it using Node.js and WebPack. The way you install and use DPP varies depending on which approach you use. | ||
### Using a CDN Copy | ||
You can use DPP directly from the Github CDN linked to this repository. In your main module, load it using: | ||
You can use DPP directly from the Github CDN linked to this repository. In your main browser application module, load it using: | ||
const {DPP} = await import('https://cdn.jsdelivr.net/gh/robtweed/DPP/src/dpp.min.js'); | ||
const {createDPP} = await import('https://cdn.jsdelivr.net/gh/robtweed/DPP/src/dpp_browser.min.js'); | ||
@@ -99,2 +101,5 @@ ### Using a Local Copy | ||
- dpp.min.js | ||
- dpp_browser.js | ||
- dpp_browser.min.js | ||
- dpp_node.js | ||
- idb_handlers | ||
@@ -109,5 +114,10 @@ - delete.js | ||
const {createDPP} = await import('/dpp/dpp_browser.min.js'); | ||
Note that if you're going to use local copies of both DPP and its dependent QOper8 modules, you can bypass this step and just use the DPP class modules itself: | ||
const {DPP} = await import('/dpp/dpp.min.js'); | ||
See below on how to use this latter approach. | ||
### From NPM | ||
@@ -119,3 +129,7 @@ | ||
You can now load DPP using: | ||
import {createDPP} from "dpp-db/node"; | ||
## Starting DPP | ||
@@ -133,7 +147,7 @@ | ||
Now instantiate an instance of DPP for your object: | ||
Now create an instance of DPP using these as inputs: | ||
const {DPP} = await import('/dpp/dpp.min.js'); | ||
const {createDPP} = await import('https://cdn.jsdelivr.net/gh/robtweed/DPP/src/dpp_browser.min.js'); | ||
let dpp = await DPP.create({ | ||
let dpp = await createDPP({ | ||
storeName: storeName, | ||
@@ -143,7 +157,4 @@ idb_name: idb_name | ||
As noted above, if you didn't provide an *idb_name* property, DPP would use an *indexedDB* database name of *DPP*. | ||
You can now start DPP and attach your local object to its *indexedDB* copy: | ||
Then start your DPP instance, which will also attach your local object to its corresponding copy in *indexedDB*: | ||
let myObj = await dpp.start(); | ||
@@ -155,27 +166,63 @@ | ||
### Using a Local Copy of DPP | ||
By default, DPP will use a copy of *QOper8* from its Github repository. That's what happens behind the scenes if you use this method of instantiation (and it's why you must await its completion): | ||
let dpp = await DPP.create({ | ||
storeName: storeName | ||
### Using a Local Copy of DPP, but a CDN Copy of QOper8 | ||
You can use DPP with your own local copy of DPP, but allow it to use a CDN copy of QOper8 behind the scenes. | ||
Installing a local copy of *DPP* is described earlier above. | ||
You need to decide on a store name: this is the name of the store that will be used by indexedDB to maintain your object. The name is entirely for you to decide, eg: | ||
let storeName = 'myObjCopy'; | ||
Optionally you can specify an *indexedDB* database name. By default, DPP will apply a database name of "DPP". Otherwise we can do the following: | ||
let idb_name = 'MY-DB'; | ||
Now create an instance of DPP using these as inputs: | ||
const {createDPP} = await import('/dpp/dpp_browser.min.js'); | ||
const {DPP} = await import('/dpp/dpp.min.js'); | ||
let dpp = await createDPP({ | ||
storeName: storeName, | ||
idb_name: idb_name, | ||
DPP: DPP | ||
}); | ||
You can, however, use your own local copy of *QOper8* if you've copied it from the Github repository to your own web server. For example, let's say you installed it in the folder */var/www/qoper8* on your Web Server. | ||
You can now start DPP and attach your local object to its *indexedDB* copy: | ||
You can instantiate DPP as follows: | ||
let myObj = await dpp.start(); | ||
You're ready to start using your object! | ||
### Using a Local Copies of DPP and QOper8 | ||
if you're using a local copy of DPP, it's probably most sensible to also use a local copy of QOper8. | ||
Installing a local copy of *DPP* is described earlier above. | ||
Installing a local copy of *Qoper8* is very similar: copy/clone it from its Github repository to your own web server. For example, let's say you installed it in the folder */var/www/qoper8* on your Web Server. | ||
You need to decide on a store name: this is the name of the store that will be used by indexedDB to maintain your object. The name is entirely for you to decide, eg: | ||
let storeName = 'myObjCopy'; | ||
Optionally you can specify an *indexedDB* database name. By default, DPP will apply a database name of "DPP". Otherwise we can do the following: | ||
let idb_name = 'MY-DB'; | ||
You can now just use the DPP module itself and create an instance of DPP using its constructor directly: | ||
const {DPP} = await import('/dpp/dpp.min.js'); | ||
const {QOper8} = await import('/qoper8/QOper8.min.js'); | ||
let storeName = 'myObjCopy'; | ||
let idb_name = 'MY-DB'; // optional | ||
let dpp = new DPP({ | ||
storeName: storeName, | ||
idb_name: idb_name, // optional, 'DPP' is the default | ||
idb_name: idb_name, | ||
QOper8: QOper8 | ||
}); | ||
You can now start DPP and attach your local object to its *indexedDB* copy: | ||
@@ -188,2 +235,31 @@ | ||
### Using DPP Installed Using NPM | ||
If you're using a bundler such as WebPack to create your front-end code, you'll need to use the NPM/Node.js-based approach described below. | ||
If you installed DPP using NPM (see above), you use it as follows: | ||
You need to decide on a store name: this is the name of the store that will be used by indexedDB to maintain your object. The name is entirely for you to decide, eg: | ||
let storeName = 'myObjCopy'; | ||
Optionally you can specify an *indexedDB* database name. By default, DPP will apply a database name of "DPP". Otherwise we can do the following: | ||
let idb_name = 'MY-DB'; | ||
Now import the *createDPP* function and use it to create an instance of DPP. Then link the local object of your choice (eg *myObj*) to its corresponding copy in *indexedDB*: | ||
import {createDPP} from "dpp-db/node"; | ||
let dpp = createDPP({ | ||
storeName: storeName, | ||
idb_name: idb_name | ||
}); | ||
let myObj = await dpp.start(); | ||
You're ready to start using your object! | ||
---- | ||
## Using Your Object | ||
@@ -208,11 +284,4 @@ | ||
const {DPP} = await import('https://cdn.jsdelivr.net/gh/robtweed/DPP/src/dpp.min.js'); | ||
// We'll use an indexedDB storename named "po_a" | ||
// and create an instance of the DPP class | ||
let dpp = await DPP.create({storeName: 'po_a'}); | ||
// start the indexedDB database and attach a local object to the indexDB store: | ||
const {createDPP} = await import('https://cdn.jsdelivr.net/gh/robtweed/DPP/src/dpp_browser.min.js'); | ||
let dpp = await createDPP({storeName: 'po_a'}); | ||
let a = await dpp.start(); | ||
@@ -263,4 +332,4 @@ | ||
(async () => { | ||
const {DPP} = await import('https://cdn.jsdelivr.net/gh/robtweed/DPP/src/dpp.min.js'); | ||
let dpp = await DPP.create({storeName: 'po_a'}); | ||
const {createDPP} = await import('https://cdn.jsdelivr.net/gh/robtweed/DPP/src/dpp_browser.min.js'); | ||
let dpp = await createDPP({storeName: 'po_a'}); | ||
let a = await dpp.start(); | ||
@@ -279,5 +348,7 @@ console.log('a: ' + JSON.stringify(a, null, 2)); | ||
(async () => { | ||
const {DPP} = await import('https://cdn.jsdelivr.net/gh/robtweed/DPP/src/dpp.min.js'); | ||
let dpp = await DPP.create({storeName: 'po_a'}); | ||
let a = await dpp.start('new'); // <== add the 'new' argument | ||
const {createDPP} = await import('https://cdn.jsdelivr.net/gh/robtweed/DPP/src/dpp_browser.min.js'); | ||
let dpp = await createDPP({storeName: 'po_a'}); | ||
let a = await dpp.start('new'); // <== add the 'new' argument | ||
console.log('a: ' + JSON.stringify(a, null, 2)); | ||
@@ -291,36 +362,62 @@ })(); | ||
- Loading the DPP Module into your browser: | ||
- Loading the DPP Creation Module into your browser: | ||
const {DPP} = await import(/path/to/dpp.js) | ||
const {createDPP} = await import(/path/to/dpp_browser.js); | ||
- Creating an instance of the DPP Class | ||
or, if building using local copies of DPP and QOper8, load the DPP module itself: | ||
- Using QOper8 from CDN | ||
const {DPP} = await import(/path/to/dpp.min.js); | ||
let dpp = await DPP.create({ | ||
or, if building using Node.js/NPM | ||
import {createDPP} from 'dpp-db/node'; | ||
- Starting DPP: | ||
- Using DPP and QOper8 from CDN | ||
let dpp = await createDPP({ | ||
storeName: storeName, | ||
idb_name: idbName // optional, 'DPP' used if omitted | ||
idb_name: idbName, // optional, 'DPP' used if omitted | ||
}); | ||
- Using a local copy of QOper8: | ||
const {QOper8} = await import('/qoper8/QOper8.min.js'); | ||
- Using a local copy of DPP (but CDN copy of QOper8): | ||
const {DPP} = await import('/path/to/dpp.min.js'); | ||
let dpp = await createDPP({ | ||
storeName: storeName, | ||
idb_name: idbName, | ||
DPP: DPP | ||
}); | ||
- Using local copies of both DPP and QOper8: | ||
const {DPP} = await import('/path/to/dpp.min.js'); | ||
const {QOper8} = await import('path/to/qoper8.min.js'); | ||
let dpp = new DPP({ | ||
storeName: storeName, | ||
idb_name: idb_name, | ||
idb_name: idbName, | ||
DPP: DPP, | ||
QOper8: QOper8 | ||
}); | ||
- Open/Start DPP and connect a local object to the *indexedDB* Database store | ||
let local_object = await dpp.start(mode) | ||
- creating a local object and attaching it to its DPP-managed copy in *indexedDB*: | ||
- If *mode* is not specified, the Proxy Object specified by *obj_name* will be restored with any existing data from | ||
let local_object = await dpp.start(mode); | ||
- If *mode* is not specified, the Proxy Object specified by *local_object* will be restored with any existing data from | ||
the specified *indexedDB* ObjectStore | ||
- If you specify a value of *new* for *mode*, then the specified *indexedDB* ObjectStore is cleared down and | ||
the Proxy Object will be empty. | ||
the Proxy Object will be empty. For example: | ||
let local_object = await dpp.start('new'); | ||
## Limitations to DPP | ||
@@ -330,4 +427,2 @@ | ||
- If you assign them to another variable, changes made to that variable will not be persisted in the *indexedDB* copy. | ||
- A DPP Proxy Object can be as deeply-nested as you want, and can contain any mixture of: | ||
@@ -346,8 +441,12 @@ | ||
- Note that the base Proxy Object variable cannot be used as a simple variable, ie the following will not be | ||
persisted: | ||
persisted, because you'll overwrite the Proxy Object: | ||
let a = await dpp.start('new'); | ||
a = 'hello world'; | ||
let a = await createDPP({ | ||
storeName: 'a-copy', | ||
mode: 'new' | ||
}); | ||
a = 'hello world'; | ||
Instead, you must define at least one property of the Proxy Object. ie the following **will** be persisted: | ||
@@ -354,0 +453,0 @@ |
@@ -26,3 +26,3 @@ /* | ||
2 August 2022 | ||
3 August 2022 | ||
@@ -38,3 +38,3 @@ */ | ||
['restore', ` | ||
self.handler=async function(e,t){let a={},r=this;if(r.idb&&r.idb.db){let i=e.storeName;r.idb.storeName=e.storeName,await r.idb.stores[i].iterate(function(e,t){var r=a;let i;e.forEach(function(a,s){let o=!1;if(Array.isArray(a)&&(o=!0,a=+a[0]),0===s&&(i=a),s===e.length-1)r[a]=t;else{let t=e[s+1];Array.isArray(t)?void 0===r[a]&&(r[a]=[]):void 0===r[a]&&(r[a]={}),r=r[a]}})}),t({obj:a})}else t({error:"Database not instantiated"})}; | ||
self.handler=async function(e,t){let a={},i=this;if(i.idb&&i.idb.db){let r=e.storeName;i.idb.storeName=e.storeName,e.clear?await i.idb.stores[r].iterate(async function(e,t){console.log("deleting "+e),await i.idb.stores[r].clearByKey(e)}):await i.idb.stores[r].iterate(function(e,t){var i=a;let r;e.forEach(function(a,s){let o=!1;if(Array.isArray(a)&&(o=!0,a=+a[0]),0===s&&(r=a),s===e.length-1)i[a]=t;else{let t=e[s+1];Array.isArray(t)?void 0===i[a]&&(i[a]=[]):void 0===i[a]&&(i[a]={}),i=i[a]}})}),t({obj:a})}else t({error:"Database not instantiated"})}; | ||
`], | ||
@@ -59,4 +59,4 @@ ['put', ` | ||
this.name = 'DPP-Q'; | ||
this.build = '2.2'; | ||
this.buildDate = '2 August 2022'; | ||
this.build = '2.3'; | ||
this.buildDate = '3 August 2022'; | ||
this.listeners = new Map(); | ||
@@ -252,3 +252,8 @@ this.logging = logging || false; | ||
async clear() { | ||
await this.store.clear(); | ||
let msg = { | ||
type: 'restore', | ||
storeName: this.storeName, | ||
clear: true | ||
}; | ||
dpp.QOper8.message(msg); | ||
} | ||
@@ -284,2 +289,7 @@ | ||
async start(mode) { | ||
if (typeof mode === 'object') { | ||
if (mode.storeName) this.storeName = mode.storeName; | ||
if (mode.idb_name) this.idb_name = mode.idb_name; | ||
mode = mode.mode; | ||
} | ||
let msg = { | ||
@@ -286,0 +296,0 @@ type: 'instantiate', |
@@ -1,1 +0,1 @@ | ||
let handlerCode=new Map([["instantiate",'\nself.handler=async function(e,t){let r=this;const o=class{constructor(e){this.name=e}getObjectStore(e){return r.idb.db.transaction(this.name,e).objectStore(this.name)}iterate_db(e,t,r){let o;t||"function"!=typeof e||(t=e,e=null);let n="";e&&(o=IDBKeyRange.lowerBound(e),n=e.toString()+","),this.getObjectStore().openCursor(o).onsuccess=function(o){let i=o.target.result;if(i){let o=i.value;if(e){let e=o.id.toString()+",";""!==n&&e.startsWith(n)?(t&&t(o.id,o.value),i.continue()):r&&"function"==typeof r&&r()}else t&&t(o.id,o.value),i.continue()}else r&&"function"==typeof r&&r()}}iterate(e,t){t||"function"!=typeof e||(t=e,e=null);let r=this;return new Promise(o=>{r.iterate_db(e,t,function(){o()})})}async clearByKey(e){let t=this;await this.iterate(e,async function(e){await t.delete(e)})}clear_db(e){if(!_worker.idb.db)return e({error:"clear() Error: Database has not been opened"});let t=this.getObjectStore("readwrite").clear();t.onsuccess=function(){e({ok:!0})},t.onerror=function(){e({error:t.error})}}clear(){let e=this;return new Promise(t=>{e.clear_db(function(e){t(e)})})}put_item(e,t,o){if(!r.idb.db)return o({error:"addItem Error: Database has not been opened"});o||(o=t,t=e,e=null);let n=this.getObjectStore("readwrite").put(t);n.onsuccess=function(){r.emit("putCommitted",t),o({key:n.result})},n.onerror=function(){o({error:n.error})}}put(e,t){t||(t=e,e=null);let r=this;return new Promise(o=>{r.put_item(e,t,function(e){o(e)})})}delete_item(e,t){if(!r.idb.db)return t({error:"delete_item Error: Database has not been opened"});let o=this.getObjectStore("readwrite").delete(e);o.onsuccess=function(){r.emit("deleteCommitted",e),t({ok:!0})},o.onerror=function(){t({error:o.error})}}delete(e){let t=this;return new Promise(r=>{t.delete_item(e,function(e){r(e)})})}};function n(e,t){let o={};t?o.keyPath=t:o.autoIncrement=!0,r.idb.objectStores.set(e,o)}function i(e,t){if(!r.idb.store)return t({error:"Open Database Error: Store Name not defined"});t||(t=e,e=null);let n=indexedDB.open(r.idb.store,e);n.onsuccess=function(e){r.idb.db=e.target.result,r.emit("databaseOpen",r.idb.db),t({db:r.idb.db})},n.onerror=function(e){t({error:e.target.errorCode})},n.onupgradeneeded=function(e){r.idb.db=e.target.result,function(){if(r.idb)for(const[e,t]of r.idb.objectStores.entries())r.idb.db.objectStoreNames.contains(e)||(r.idb.db.createObjectStore(e,t),r.idb.stores[e]||(r.idb.stores[e]=new o(e)))}()}}async function s(e){return new Promise(t=>{i(e,function(e){t(e)})})}r.idb||(this.idb={objectStores:new Map,stores:{},store:e.idb_name});let d=e.objectStores||[];for(const e of d)n(e,"id");await s();let a=!1;for(const e of r.idb.objectStores.keys())r.idb.db.objectStoreNames.contains(e)||(a=!0),r.idb.stores[e]=new o(e);if(a){let e=r.idb.db.version+1;r.idb.db.close(),await s(e),r.emit("databaseReady"),t({db_ready:!0})}else this.emit("databaseReady"),t({db_ready:!0})};\n '],["restore",'\nself.handler=async function(e,t){let a={},r=this;if(r.idb&&r.idb.db){let i=e.storeName;r.idb.storeName=e.storeName,await r.idb.stores[i].iterate(function(e,t){var r=a;let i;e.forEach(function(a,s){let o=!1;if(Array.isArray(a)&&(o=!0,a=+a[0]),0===s&&(i=a),s===e.length-1)r[a]=t;else{let t=e[s+1];Array.isArray(t)?void 0===r[a]&&(r[a]=[]):void 0===r[a]&&(r[a]={}),r=r[a]}})}),t({obj:a})}else t({error:"Database not instantiated"})};\n '],["put",'\nself.handler=async function(e,a){let t=this;if(t.idb&&t.idb.db){let i=e.key,l=e.value,s=t.idb.stores[t.idb.storeName];await s.clearByKey(i);let d={id:i,value:l};await s.put(d),a({ok:!0})}else a({error:"Database not instantiated"})};\n '],["delete",'\nself.handler=async function(e,t){let a=this;if(a.idb&&a.idb.db){let i=e.key,s=a.idb.stores[a.idb.storeName];await s.clearByKey(i),t({ok:!0})}else t({error:"Database not instantiated"})};\n ']]),DPP=class{constructor(e){let t=e.logging||!1,r=e.QOper8,i=e.qOptions||{},s=e.idb_name||"DPP",o=e.storeName||"DPP_Store";this.name="DPP-Q",this.build="2.2",this.buildDate="2 August 2022",this.listeners=new Map,this.logging=t||!1,this.storeName=o,this.idb_name=s,this.QOper8=new r({poolSize:1,logging:i.logging,workerInactivityCheckInterval:i.workerInactivityCheckInterval||60,workerInactivityLimit:i.workerInactivityLimit||60});let n=new Map;for(const[e,t]of handlerCode)n.set(e,this.QOper8.createUrl(t));this.QOper8.handlersByMessageType=n;let a=this;this.deepProxy=class{constructor(e,t){return this._preproxy=new WeakMap,this._handler=t,this.proxify(e,[])}makeHandler(e){let t=this;return{set:(r,i,s,o)=>("object"==typeof s&&(s=t.proxify(s,[...e,i])),r[i]=s,t._handler.set&&t._handler.set(r,[...e,i],s,o),!0),deleteProperty(r,i){if(Reflect.has(r,i)){t.unproxy(r,i);let s=Reflect.deleteProperty(r,i);return s&&t._handler.deleteProperty&&t._handler.deleteProperty(r,[...e,i]),s}return!0}}}unproxy(e,t){this._preproxy.has(e[t])&&(e[t]=this._preproxy.get(e[t]),this._preproxy.delete(e[t]));for(let r of Object.keys(e[t]))"object"==typeof e[t][r]&&this.unproxy(e[t],r)}proxify(e,t){for(let r of Object.keys(e))"object"==typeof e[r]&&(e[r]=this.proxify(e[r],[...t,r]));let r=new Proxy(e,this.makeHandler(t));return this._preproxy.set(r,e),r}},this.persistAs=class{constructor(){this.storeName=a.storeName,this.persist=!0}async proxy(e){let t=this,r=(this.storeName,new a.deepProxy({},{async set(e,r,i,s){if(!t.persist)return;a.logMessage("proxy set called with prop = "+JSON.stringify(r));let o=t.receiver,n=!1;function l(t,i){1===t.length&&(e[r]=i),a.emit("save",i);let s={type:"put",key:t,value:i};a.QOper8.message(s)}return r.forEach(function(e,t){o=o[e],n&&(r[t]=[e]),n=Array.isArray(o)}),"object"==typeof i&&async function e(t,r){a.logMessage("getProps called for "+JSON.stringify(t)),a.logMessage("obj="+JSON.stringify(r));let i={type:"delete",key:t};a.QOper8.message(i);let s=Array.isArray(r);for(let[i,o]of Object.entries(r)){s&&(i=[i]);let r=t.slice();r.push(i),"object"!=typeof o?l(r,o):e(r,o)}}(r,i),["string","number","boolean","symbol","bigint"].includes(typeof i)&&l(r,i),a.emit("proxy_set_completed",r),!0},deleteProperty(e,r){let i=t.receiver,s=!1;r.forEach(function(e,t){i=i[e],s&&(r[t]=[e]),s=Array.isArray(i)}),a.emit("delete",r);let o={type:"delete",key:r};a.QOper8.message(o)}}));return this.receiver=r,"new"!==e?await this.restore():await this.clear(),r}async clear(){await this.store.clear()}async restore(){let e={type:"restore",storeName:this.storeName},t=await a.QOper8.send(e);this.persist=!1;for(let e in t.obj)this.receiver[e]=t.obj[e];this.persist=!0}}}static async create(e){if(!e.QOper8){let{QOper8:t}=await import("https://robtweed.github.io/QOper8/src/QOper8.min.js");e.QOper8=t}return new DPP(e)}async start(e){let t={type:"instantiate",idb_name:this.idb_name,objectStores:[this.storeName]};return this.QOper8.message(t),await(new this.persistAs).proxy(e)}isEmpty(e){for(const t in e)return!1;return!0}on(e,t){this.listeners.has(e)||this.listeners.set(e,t)}off(e){this.listeners.has(e)&&this.listeners.delete(e)}emit(e,t){if(this.listeners.has(e)){this.listeners.get(e).call(this,t)}}logMessage(e){this.logging&&console.log(Date.now()+": "+e)}};export{DPP}; | ||
let handlerCode=new Map([["instantiate",'\nself.handler=async function(e,t){let r=this;const o=class{constructor(e){this.name=e}getObjectStore(e){return r.idb.db.transaction(this.name,e).objectStore(this.name)}iterate_db(e,t,r){let o;t||"function"!=typeof e||(t=e,e=null);let n="";e&&(o=IDBKeyRange.lowerBound(e),n=e.toString()+","),this.getObjectStore().openCursor(o).onsuccess=function(o){let i=o.target.result;if(i){let o=i.value;if(e){let e=o.id.toString()+",";""!==n&&e.startsWith(n)?(t&&t(o.id,o.value),i.continue()):r&&"function"==typeof r&&r()}else t&&t(o.id,o.value),i.continue()}else r&&"function"==typeof r&&r()}}iterate(e,t){t||"function"!=typeof e||(t=e,e=null);let r=this;return new Promise(o=>{r.iterate_db(e,t,function(){o()})})}async clearByKey(e){let t=this;await this.iterate(e,async function(e){await t.delete(e)})}clear_db(e){if(!_worker.idb.db)return e({error:"clear() Error: Database has not been opened"});let t=this.getObjectStore("readwrite").clear();t.onsuccess=function(){e({ok:!0})},t.onerror=function(){e({error:t.error})}}clear(){let e=this;return new Promise(t=>{e.clear_db(function(e){t(e)})})}put_item(e,t,o){if(!r.idb.db)return o({error:"addItem Error: Database has not been opened"});o||(o=t,t=e,e=null);let n=this.getObjectStore("readwrite").put(t);n.onsuccess=function(){r.emit("putCommitted",t),o({key:n.result})},n.onerror=function(){o({error:n.error})}}put(e,t){t||(t=e,e=null);let r=this;return new Promise(o=>{r.put_item(e,t,function(e){o(e)})})}delete_item(e,t){if(!r.idb.db)return t({error:"delete_item Error: Database has not been opened"});let o=this.getObjectStore("readwrite").delete(e);o.onsuccess=function(){r.emit("deleteCommitted",e),t({ok:!0})},o.onerror=function(){t({error:o.error})}}delete(e){let t=this;return new Promise(r=>{t.delete_item(e,function(e){r(e)})})}};function n(e,t){let o={};t?o.keyPath=t:o.autoIncrement=!0,r.idb.objectStores.set(e,o)}function i(e,t){if(!r.idb.store)return t({error:"Open Database Error: Store Name not defined"});t||(t=e,e=null);let n=indexedDB.open(r.idb.store,e);n.onsuccess=function(e){r.idb.db=e.target.result,r.emit("databaseOpen",r.idb.db),t({db:r.idb.db})},n.onerror=function(e){t({error:e.target.errorCode})},n.onupgradeneeded=function(e){r.idb.db=e.target.result,function(){if(r.idb)for(const[e,t]of r.idb.objectStores.entries())r.idb.db.objectStoreNames.contains(e)||(r.idb.db.createObjectStore(e,t),r.idb.stores[e]||(r.idb.stores[e]=new o(e)))}()}}async function s(e){return new Promise(t=>{i(e,function(e){t(e)})})}r.idb||(this.idb={objectStores:new Map,stores:{},store:e.idb_name});let d=e.objectStores||[];for(const e of d)n(e,"id");await s();let a=!1;for(const e of r.idb.objectStores.keys())r.idb.db.objectStoreNames.contains(e)||(a=!0),r.idb.stores[e]=new o(e);if(a){let e=r.idb.db.version+1;r.idb.db.close(),await s(e),r.emit("databaseReady"),t({db_ready:!0})}else this.emit("databaseReady"),t({db_ready:!0})};\n '],["restore",'\nself.handler=async function(e,t){let a={},i=this;if(i.idb&&i.idb.db){let r=e.storeName;i.idb.storeName=e.storeName,e.clear?await i.idb.stores[r].iterate(async function(e,t){console.log("deleting "+e),await i.idb.stores[r].clearByKey(e)}):await i.idb.stores[r].iterate(function(e,t){var i=a;let r;e.forEach(function(a,s){let o=!1;if(Array.isArray(a)&&(o=!0,a=+a[0]),0===s&&(r=a),s===e.length-1)i[a]=t;else{let t=e[s+1];Array.isArray(t)?void 0===i[a]&&(i[a]=[]):void 0===i[a]&&(i[a]={}),i=i[a]}})}),t({obj:a})}else t({error:"Database not instantiated"})};\n '],["put",'\nself.handler=async function(e,a){let t=this;if(t.idb&&t.idb.db){let i=e.key,l=e.value,s=t.idb.stores[t.idb.storeName];await s.clearByKey(i);let d={id:i,value:l};await s.put(d),a({ok:!0})}else a({error:"Database not instantiated"})};\n '],["delete",'\nself.handler=async function(e,t){let a=this;if(a.idb&&a.idb.db){let i=e.key,s=a.idb.stores[a.idb.storeName];await s.clearByKey(i),t({ok:!0})}else t({error:"Database not instantiated"})};\n ']]),DPP=class{constructor(e){let t=e.logging||!1,r=e.QOper8,i=e.qOptions||{},s=e.idb_name||"DPP",o=e.storeName||"DPP_Store";this.name="DPP-Q",this.build="2.3",this.buildDate="3 August 2022",this.listeners=new Map,this.logging=t||!1,this.storeName=o,this.idb_name=s,this.QOper8=new r({poolSize:1,logging:i.logging,workerInactivityCheckInterval:i.workerInactivityCheckInterval||60,workerInactivityLimit:i.workerInactivityLimit||60});let n=new Map;for(const[e,t]of handlerCode)n.set(e,this.QOper8.createUrl(t));this.QOper8.handlersByMessageType=n;let a=this;this.deepProxy=class{constructor(e,t){return this._preproxy=new WeakMap,this._handler=t,this.proxify(e,[])}makeHandler(e){let t=this;return{set:(r,i,s,o)=>("object"==typeof s&&(s=t.proxify(s,[...e,i])),r[i]=s,t._handler.set&&t._handler.set(r,[...e,i],s,o),!0),deleteProperty(r,i){if(Reflect.has(r,i)){t.unproxy(r,i);let s=Reflect.deleteProperty(r,i);return s&&t._handler.deleteProperty&&t._handler.deleteProperty(r,[...e,i]),s}return!0}}}unproxy(e,t){this._preproxy.has(e[t])&&(e[t]=this._preproxy.get(e[t]),this._preproxy.delete(e[t]));for(let r of Object.keys(e[t]))"object"==typeof e[t][r]&&this.unproxy(e[t],r)}proxify(e,t){for(let r of Object.keys(e))"object"==typeof e[r]&&(e[r]=this.proxify(e[r],[...t,r]));let r=new Proxy(e,this.makeHandler(t));return this._preproxy.set(r,e),r}},this.persistAs=class{constructor(){this.storeName=a.storeName,this.persist=!0}async proxy(e){let t=this,r=(this.storeName,new a.deepProxy({},{async set(e,r,i,s){if(!t.persist)return;a.logMessage("proxy set called with prop = "+JSON.stringify(r));let o=t.receiver,n=!1;function l(t,i){1===t.length&&(e[r]=i),a.emit("save",i);let s={type:"put",key:t,value:i};a.QOper8.message(s)}return r.forEach(function(e,t){o=o[e],n&&(r[t]=[e]),n=Array.isArray(o)}),"object"==typeof i&&async function e(t,r){a.logMessage("getProps called for "+JSON.stringify(t)),a.logMessage("obj="+JSON.stringify(r));let i={type:"delete",key:t};a.QOper8.message(i);let s=Array.isArray(r);for(let[i,o]of Object.entries(r)){s&&(i=[i]);let r=t.slice();r.push(i),"object"!=typeof o?l(r,o):e(r,o)}}(r,i),["string","number","boolean","symbol","bigint"].includes(typeof i)&&l(r,i),a.emit("proxy_set_completed",r),!0},deleteProperty(e,r){let i=t.receiver,s=!1;r.forEach(function(e,t){i=i[e],s&&(r[t]=[e]),s=Array.isArray(i)}),a.emit("delete",r);let o={type:"delete",key:r};a.QOper8.message(o)}}));return this.receiver=r,"new"!==e?await this.restore():await this.clear(),r}async clear(){let e={type:"restore",storeName:this.storeName,clear:!0};a.QOper8.message(e)}async restore(){let e={type:"restore",storeName:this.storeName},t=await a.QOper8.send(e);this.persist=!1;for(let e in t.obj)this.receiver[e]=t.obj[e];this.persist=!0}}}static async create(e){if(!e.QOper8){let{QOper8:t}=await import("https://robtweed.github.io/QOper8/src/QOper8.min.js");e.QOper8=t}return new DPP(e)}async start(e){"object"==typeof e&&(e.storeName&&(this.storeName=e.storeName),e.idb_name&&(this.idb_name=e.idb_name),e=e.mode);let t={type:"instantiate",idb_name:this.idb_name,objectStores:[this.storeName]};return this.QOper8.message(t),await(new this.persistAs).proxy(e)}isEmpty(e){for(const t in e)return!1;return!0}on(e,t){this.listeners.has(e)||this.listeners.set(e,t)}off(e){this.listeners.has(e)&&this.listeners.delete(e)}emit(e,t){if(this.listeners.has(e)){this.listeners.get(e).call(this,t)}}logMessage(e){this.logging&&console.log(Date.now()+": "+e)}};export{DPP}; |
@@ -0,1 +1,3 @@ | ||
/* | ||
@@ -25,7 +27,4 @@ ---------------------------------------------------------------------------- | ||
---------------------------------------------------------------------------- | ||
QOper8 WebWorker for DPP: Delete the object record from IndexDB Database | ||
31 July 2022 | ||
*/ | ||
@@ -32,0 +31,0 @@ |
@@ -28,7 +28,7 @@ /* | ||
31 July 2022 | ||
3 August 2022 | ||
*/ | ||
export async function handler(obj, finished) { | ||
self.handler = async function (obj, finished) { | ||
@@ -42,30 +42,37 @@ let ref = {}; | ||
worker.idb.storeName = obj.storeName; | ||
await worker.idb.stores[storeName].iterate(function(key, value) { | ||
var o = ref; | ||
let key1; | ||
key.forEach(function(prop, index) { | ||
let isArr = false; | ||
if (Array.isArray(prop)) { | ||
isArr = true; | ||
prop = +prop[0]; | ||
} | ||
if (index === 0) { | ||
key1 = prop; | ||
} | ||
if (index === (key.length - 1)) { | ||
o[prop] = value; | ||
} | ||
else { | ||
let nextKey = key[index + 1]; | ||
if (Array.isArray(nextKey)) { | ||
if (typeof o[prop] === 'undefined') o[prop] = []; | ||
if (obj.clear) { | ||
await worker.idb.stores[storeName].iterate(async function(key, value) { | ||
await worker.idb.stores[storeName].clearByKey(key); | ||
}); | ||
} | ||
else { | ||
await worker.idb.stores[storeName].iterate(function(key, value) { | ||
var o = ref; | ||
let key1; | ||
key.forEach(function(prop, index) { | ||
let isArr = false; | ||
if (Array.isArray(prop)) { | ||
isArr = true; | ||
prop = +prop[0]; | ||
} | ||
if (index === 0) { | ||
key1 = prop; | ||
} | ||
if (index === (key.length - 1)) { | ||
o[prop] = value; | ||
} | ||
else { | ||
if (typeof o[prop] === 'undefined') o[prop] = {}; | ||
let nextKey = key[index + 1]; | ||
if (Array.isArray(nextKey)) { | ||
if (typeof o[prop] === 'undefined') o[prop] = []; | ||
} | ||
else { | ||
if (typeof o[prop] === 'undefined') o[prop] = {}; | ||
} | ||
o = o[prop]; | ||
} | ||
o = o[prop]; | ||
} | ||
}); | ||
}); | ||
}); | ||
} | ||
finished({ | ||
@@ -72,0 +79,0 @@ obj: ref |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
125101
29
1673
489