sqlite-worker
Advanced tools
Comparing version 0.3.0 to 0.3.1
@@ -22,3 +22,4 @@ 'use strict'; | ||
options.worker || | ||
(library.slice(0, library.lastIndexOf('/')) + '/worker.js') | ||
(library.slice(0, library.lastIndexOf('/')) + '/worker.js'), | ||
{type: 'module'} | ||
), { | ||
@@ -25,0 +26,0 @@ onmessage({data: {id, result, error}}) { |
@@ -20,2 +20,3 @@ 'use strict'; | ||
case 'init': | ||
console.log(options.library); | ||
if (!db) | ||
@@ -22,0 +23,0 @@ db = import(options.library).then(({init}) => init(options)); |
@@ -1,1 +0,1 @@ | ||
const e=new WeakMap,t=(t,...n)=>{const{t:s,v:o}=((e,t)=>{const n=[e[0]],s=[];for(let o=0,l=0,a=0,{length:c}=t;l<c;l++)t[l]instanceof r?n[o]+=t[l].v+e[l+1]:(s[a++]=l,n[++o]=e[l+1]);return{t:n,v:s}})(t,n),l=e.get(t)||e.set(t,{}).get(t);return(l[s]||(l[s]=[s])).concat(o.map((e=>n[e])))};function r(e){this.v=e}const n=(e,r)=>(n,...o)=>new Promise(((a,c)=>{n.some(l)&&c(s(new Error("SQLITE_ERROR: SQL injection hazard")));const[i,...u]=t(n,...o);e[r](i.join("?"),u,((e,t)=>{e?c(e):a(t)}))})),s=e=>(e.code="SQLITE_ERROR",e),o=(e,...t)=>new r(function(e){for(var t=e[0],r=1,n=arguments.length;r<n;r++)t+=arguments[r]+e[r];return t}(e,...t)),l=e=>e.includes("?");function a(e){return{all:n(e,"all"),get:n(e,"get"),query:n(e,"run"),raw:o}}const{assign:c}=Object,i=(e,t=1)=>new Promise(((r,n)=>{c(indexedDB.open(e,t),{onupgradeneeded({target:{result:e,transaction:t}}){e.objectStoreNames.contains("sqlite")||e.createObjectStore("sqlite").createIndex("buffer","buffer",{unique:!0}),c(t,{oncomplete(){r(e)}})},onsuccess({target:{result:e}}){r(e)},onerror:n})})),u=(e={})=>new Promise(((t,r)=>{const{url:n}=import.meta,s=e.dir||n.slice(0,n.lastIndexOf("/"))+"/../dist";self.exports={},self.module={exports:exports},import(s+"/sql-wasm.js").then((()=>{const n=self.module.exports;delete self.exports,Promise.all([i(e.name||"sqlite-worker"),n({locateFile:e=>s+"/"+e})]).then((([n,{Database:s}])=>{const o=e=>n.transaction(["sqlite"],e).objectStore("sqlite");c(o("readonly").get("buffer"),{onsuccess(){let r=Promise.resolve();const{result:n}=this,l=new s(n||e.database||new Uint8Array(0)),i=()=>{r=r.then((()=>new Promise(((t,r)=>{const n=l.export();c(o("readwrite").put(n,"buffer"),{onsuccess(){t(),e.update&&e.update(n)},onerror:r})}))))};n||i();const{all:u,get:m,query:d,raw:p}=a({all(e,t,r){try{const n=l.exec(e,t),s=[];n.forEach(f,s),r(null,s)}catch(e){r(e)}},get(e,t,r){try{const n=l.exec(e+" LIMIT 1",t),s=[];n.forEach(f,s),r(null,s.shift()||null)}catch(e){r(e)}},run(e,t,r){try{r(null,l.run(e,t))}catch(e){r(e)}}});let g=0;t({all:u,get:m,raw:p,query(t){return/\b(?:INSERT|DELETE|UPDATE)\b/i.test(t[0])&&(clearTimeout(g),g=setTimeout(i,e.timeout||250)),d.apply(this,arguments)}})},onerror:r})}),r)}))}));function f({columns:e,values:t}){for(let{length:r}=t,n=0;n<r;n++){const r=t[n],s={};for(let{length:t}=e,n=0;n<t;n++)s[e[n]]=r[n];this.push(s)}}const{assign:m}=Object,d=new Map;let p=0;function g(e){const t=import.meta.url,r=e=>(t,...r)=>n(e,{template:t,values:r}),n=(e,t)=>new Promise(((r,n)=>{const o=p++;d.set(o,{resolve:r,reject:n}),s.postMessage({id:o,action:e,options:t})})),s=m(new Worker(e.worker||t.slice(0,t.lastIndexOf("/"))+"/worker.js"),{onmessage({data:{id:e,result:t,error:r}}){const{resolve:n,reject:s}=d.get(e);d.delete(e),r?s(r):n(t)}});return n("init",m({library:t},e)).then((()=>({all:r("all"),get:r("get"),query:r("query")})))}export{g as SQLiteWorker,u as init}; | ||
const e=new WeakMap,t=(t,...n)=>{const{t:o,v:s}=((e,t)=>{const n=[e[0]],o=[];for(let s=0,l=0,a=0,{length:c}=t;l<c;l++)t[l]instanceof r?n[s]+=t[l].v+e[l+1]:(o[a++]=l,n[++s]=e[l+1]);return{t:n,v:o}})(t,n),l=e.get(t)||e.set(t,{}).get(t);return(l[o]||(l[o]=[o])).concat(s.map((e=>n[e])))};function r(e){this.v=e}const n=(e,r)=>(n,...s)=>new Promise(((a,c)=>{n.some(l)&&c(o(new Error("SQLITE_ERROR: SQL injection hazard")));const[i,...u]=t(n,...s);e[r](i.join("?"),u,((e,t)=>{e?c(e):a(t)}))})),o=e=>(e.code="SQLITE_ERROR",e),s=(e,...t)=>new r(function(e){for(var t=e[0],r=1,n=arguments.length;r<n;r++)t+=arguments[r]+e[r];return t}(e,...t)),l=e=>e.includes("?");function a(e){return{all:n(e,"all"),get:n(e,"get"),query:n(e,"run"),raw:s}}const{assign:c}=Object,i=(e,t=1)=>new Promise(((r,n)=>{c(indexedDB.open(e,t),{onupgradeneeded({target:{result:e,transaction:t}}){e.objectStoreNames.contains("sqlite")||e.createObjectStore("sqlite").createIndex("buffer","buffer",{unique:!0}),c(t,{oncomplete(){r(e)}})},onsuccess({target:{result:e}}){r(e)},onerror:n})})),u=(e={})=>new Promise(((t,r)=>{const{url:n}=import.meta,o=e.dir||n.slice(0,n.lastIndexOf("/"))+"/../dist";self.exports={},self.module={exports:exports},import(o+"/sql-wasm.js").then((()=>{const n=self.module.exports;delete self.exports,Promise.all([i(e.name||"sqlite-worker"),n({locateFile:e=>o+"/"+e})]).then((([n,{Database:o}])=>{const s=e=>n.transaction(["sqlite"],e).objectStore("sqlite");c(s("readonly").get("buffer"),{onsuccess(){let r=Promise.resolve();const{result:n}=this,l=new o(n||e.database||new Uint8Array(0)),i=()=>{r=r.then((()=>new Promise(((t,r)=>{const n=l.export();c(s("readwrite").put(n,"buffer"),{onsuccess(){t(),e.update&&e.update(n)},onerror:r})}))))};n||i();const{all:u,get:m,query:d,raw:p}=a({all(e,t,r){try{const n=l.exec(e,t),o=[];n.forEach(f,o),r(null,o)}catch(e){r(e)}},get(e,t,r){try{const n=l.exec(e+" LIMIT 1",t),o=[];n.forEach(f,o),r(null,o.shift()||null)}catch(e){r(e)}},run(e,t,r){try{r(null,l.run(e,t))}catch(e){r(e)}}});let g=0;t({all:u,get:m,raw:p,query(t){return/\b(?:INSERT|DELETE|UPDATE)\b/i.test(t[0])&&(clearTimeout(g),g=setTimeout(i,e.timeout||250)),d.apply(this,arguments)}})},onerror:r})}),r)}))}));function f({columns:e,values:t}){for(let{length:r}=t,n=0;n<r;n++){const r=t[n],o={};for(let{length:t}=e,n=0;n<t;n++)o[e[n]]=r[n];this.push(o)}}const{assign:m}=Object,d=new Map;let p=0;function g(e){const t=import.meta.url,r=e=>(t,...r)=>n(e,{template:t,values:r}),n=(e,t)=>new Promise(((r,n)=>{const s=p++;d.set(s,{resolve:r,reject:n}),o.postMessage({id:s,action:e,options:t})})),o=m(new Worker(e.worker||t.slice(0,t.lastIndexOf("/"))+"/worker.js",{type:"module"}),{onmessage({data:{id:e,result:t,error:r}}){const{resolve:n,reject:o}=d.get(e);d.delete(e),r?o(r):n(t)}});return n("init",m({library:t},e)).then((()=>({all:r("all"),get:r("get"),query:r("query")})))}export{g as SQLiteWorker,u as init}; |
@@ -1,1 +0,1 @@ | ||
let e=null;const t=(e,t,s,{template:a,values:r})=>{e.then((e=>{e[t].apply(null,[a].concat(r)).then((e=>{postMessage({id:s,result:e})}),(({message:e})=>{postMessage({id:s,error:e})}))}))};addEventListener("message",(({data:{id:s,action:a,options:r}})=>{switch(a){case"init":return e||(e=import(r.library).then((({init:e})=>e(r)))),e.then((()=>postMessage({id:s,result:"OK"})),(({message:e})=>postMessage({id:s,error:e})));case"all":return t(e,"all",s,r);case"get":return t(e,"get",s,r);case"query":return t(e,"query",s,r)}})); | ||
let e=null;const s=(e,s,t,{template:r,values:a})=>{e.then((e=>{e[s].apply(null,[r].concat(a)).then((e=>{postMessage({id:t,result:e})}),(({message:e})=>{postMessage({id:t,error:e})}))}))};addEventListener("message",(({data:{id:t,action:r,options:a}})=>{switch(r){case"init":return console.log(a.library),e||(e=import(a.library).then((({init:e})=>e(a)))),e.then((()=>postMessage({id:t,result:"OK"})),(({message:e})=>postMessage({id:t,error:e})));case"all":return s(e,"all",t,a);case"get":return s(e,"get",t,a);case"query":return s(e,"query",t,a)}})); |
@@ -19,3 +19,4 @@ const {assign} = Object; | ||
options.worker || | ||
(library.slice(0, library.lastIndexOf('/')) + '/worker.js') | ||
(library.slice(0, library.lastIndexOf('/')) + '/worker.js'), | ||
{type: 'module'} | ||
), { | ||
@@ -22,0 +23,0 @@ onmessage({data: {id, result, error}}) { |
@@ -19,2 +19,3 @@ let db = null; | ||
case 'init': | ||
console.log(options.library); | ||
if (!db) | ||
@@ -21,0 +22,0 @@ db = import(options.library).then(({init}) => init(options)); |
{ | ||
"name": "sqlite-worker", | ||
"version": "0.3.0", | ||
"version": "0.3.1", | ||
"description": "A simple, and persistent, SQLite database for Web and Workers", | ||
@@ -5,0 +5,0 @@ "main": "./cjs/index.js", |
@@ -9,2 +9,16 @@ # sqlite-worker | ||
### ⚠ Warning about Workers | ||
Obviously I was too naive to believe I could `import(...)` modules in 2021 inside workers too, but [the reality is different](https://stackoverflow.com/a/45578811/2800218): | ||
* **Chrome** works without any issue whatsoever as *Worker* from the main thread, but *Service Worker* apparently cannot `import(...)` anything | ||
* **Firefox** never had a dynamic `import`, or even static, I believe, so *Worker* here won't work | ||
* **WebKit** has issues since 2016 too | ||
This means that while this module recommendation is to use its *SQLiteWorker* export, or to use the directly its *init* export via *Service Worker*, none of these recommendation actually work as expected, so that for a cross browser experience, using the *init* export from the main thread is the only option. | ||
Please note the *WASM* module *should* also offload from the main thread, but the thing is that I'd love for browsers to fix their inconsistencies regarding ES Modules and remove this whole warning session once they do. | ||
## How to import this module | ||
@@ -21,3 +35,3 @@ | ||
// either direct init([options]) | ||
// or use SQLiteWorker with defaults | ||
// or use SQLiteWorker with defaults (Chrome only) | ||
SQLiteWorker({name: 'my-db'}).then(() => { | ||
@@ -45,3 +59,3 @@ console.log('ready'); | ||
These options work only with direct initialization, so either in the main thread or via *Service Worker* after importing its `init` export. | ||
These options work only with direct initialization, so either in the main thread or via *Service Worker* (once fixed in Chrome) after importing its `init` export. | ||
@@ -84,4 +98,29 @@ * **update**: a *function* that receives latest version of the database, as `Uint8Array`, whenever some query executed an `INSERT`, a `DELETE`, or an `UPDATE`. | ||
### Worker usage | ||
### Direct usage | ||
This is currently the cross browser way to use this module, and it won't work within a *Service Worker* until Chrome fixes its bug. | ||
```js | ||
import {init} from 'sqlite-worker'; | ||
// init([options]) | ||
init({name: 'my-db'}).then(async ({all, get, query}) => { | ||
await query`CREATE TABLE IF NOT EXISTS todos (id INTEGER PRIMARY KEY, value TEXT)`; | ||
const {total} = await get`SELECT COUNT(id) as total FROM todos`; | ||
if (total < 1) { | ||
console.log('Inserting some value'); | ||
await query`INSERT INTO todos (value) VALUES (${'a'})`; | ||
await query`INSERT INTO todos (value) VALUES (${'b'})`; | ||
await query`INSERT INTO todos (value) VALUES (${'c'})`; | ||
} | ||
console.log(await all`SELECT * FROM todos`); | ||
}); | ||
``` | ||
### Worker usage (Chrome only) | ||
This module can also be used as *Worker*, which is a recommendation where the browser is compatible. | ||
If specified, you can pass your own worker via the `worker` option, but by default, this module can be initialized as such: | ||
@@ -109,23 +148,2 @@ | ||
### Direct usage | ||
This module can also be used in the main thread, or be imported within a *Service Worker*, as opposite of creating a new worker from the main page. | ||
```js | ||
import {init} from 'sqlite-worker'; | ||
// init([options]) | ||
init({name: 'my-db'}).then(async ({all, get, query}) => { | ||
await query`CREATE TABLE IF NOT EXISTS todos (id INTEGER PRIMARY KEY, value TEXT)`; | ||
const {total} = await get`SELECT COUNT(id) as total FROM todos`; | ||
if (total < 1) { | ||
console.log('Inserting some value'); | ||
await query`INSERT INTO todos (value) VALUES (${'a'})`; | ||
await query`INSERT INTO todos (value) VALUES (${'b'})`; | ||
await query`INSERT INTO todos (value) VALUES (${'c'})`; | ||
} | ||
console.log(await all`SELECT * FROM todos`); | ||
}); | ||
``` | ||
## Compatibility | ||
@@ -132,0 +150,0 @@ |
1215784
677
149