ueberdb2 4.1.22 → 4.1.25

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/dist/cassandra_db.d.ts +1 -0
  2. package/dist/couch_db.d.ts +1 -0
  3. package/dist/databases/cassandra_db.cjs +1 -0
  4. package/dist/databases/couch_db.cjs +1 -0
  5. package/dist/databases/dirty_db.cjs +1 -0
  6. package/dist/databases/dirty_git_db.cjs +1 -0
  7. package/dist/databases/elasticsearch_db.cjs +1 -0
  8. package/dist/databases/memory_db.cjs +1 -0
  9. package/dist/databases/mock_db.cjs +1 -0
  10. package/dist/databases/mongodb_db.cjs +1 -0
  11. package/dist/databases/mssql_db.cjs +5 -0
  12. package/dist/databases/mysql_db.cjs +1 -0
  13. package/dist/databases/postgres_db.cjs +1 -0
  14. package/dist/databases/postgrespool_db.cjs +1 -0
  15. package/dist/databases/redis_db.cjs +1 -0
  16. package/dist/databases/rethink_db.cjs +1 -0
  17. package/dist/databases/sqlite_db.cjs +4 -0
  18. package/dist/dirty_db.d.ts +1 -0
  19. package/dist/dirty_git_db.d.ts +1 -0
  20. package/dist/elasticsearch_db.d.ts +1 -0
  21. package/dist/index.d.ts +85 -0
  22. package/dist/lib/AbstractDatabase.cjs +1 -0
  23. package/dist/lib/CacheAndBufferLayer.cjs +1 -0
  24. package/dist/lib/logging.cjs +1 -0
  25. package/dist/memory_db.d.ts +1 -0
  26. package/dist/mock_db.d.ts +1 -0
  27. package/dist/mongodb_db.d.ts +1 -0
  28. package/dist/mssql_db.d.ts +1 -0
  29. package/dist/mysql_db.d.ts +1 -0
  30. package/dist/postgres_db.d.ts +1 -0
  31. package/dist/postgrespool_db.d.ts +1 -0
  32. package/dist/redis_db.d.ts +1 -0
  33. package/dist/rethink_db.d.ts +1 -0
  34. package/dist/sqlite_db.d.ts +1 -0
  35. package/package.json +10 -12
  36. package/dist/databases/cassandra_db.js +0 -235
  37. package/dist/databases/couch_db.js +0 -173
  38. package/dist/databases/dirty_db.js +0 -75
  39. package/dist/databases/dirty_git_db.js +0 -59
  40. package/dist/databases/elasticsearch_db.js +0 -243
  41. package/dist/databases/memory_db.js +0 -37
  42. package/dist/databases/mock_db.js +0 -38
  43. package/dist/databases/mongodb_db.js +0 -134
  44. package/dist/databases/mssql_db.js +0 -185
  45. package/dist/databases/mysql_db.js +0 -168
  46. package/dist/databases/postgres_db.js +0 -190
  47. package/dist/databases/postgrespool_db.js +0 -12
  48. package/dist/databases/redis_db.js +0 -120
  49. package/dist/databases/rethink_db.js +0 -121
  50. package/dist/databases/sqlite_db.js +0 -138
  51. package/dist/index.js +0 -197
  52. package/dist/lib/AbstractDatabase.js +0 -40
  53. package/dist/lib/CacheAndBufferLayer.js +0 -662
  54. package/dist/lib/logging.js +0 -35
@@ -0,0 +1 @@
1
+ export * from './databases/cassandra_db'
@@ -0,0 +1 @@
1
+ export * from './databases/couch_db'
@@ -0,0 +1 @@
1
+ "use strict";var y=Object.defineProperty;var m=(o,r,e)=>r in o?y(o,r,{enumerable:!0,configurable:!0,writable:!0,value:e}):o[r]=e;var h=(o,r,e)=>(m(o,typeof r!="symbol"?r+"":r,e),e);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const E=require("../lib/AbstractDatabase.cjs"),d=require("../node_modules/cassandra-driver/index.cjs"),f=class extends E{constructor(e){super();h(this,"client");h(this,"pool");if(!e.clientOptions)throw new Error("The Cassandra client options should be defined");if(!e.columnFamily)throw new Error("The Cassandra column family should be defined");this.settings={database:e.database},this.settings.clientOptions=e.clientOptions,this.settings.columnFamily=e.columnFamily,this.settings.logger=e.logger}init(e){this.client=new d.Client(this.settings.clientOptions),this.settings.logger&&this.client.on("log",this.settings.logger),this.client.execute("SELECT columnfamily_name FROM system.schema_columnfamilies WHERE keyspace_name = ?",[this.settings.clientOptions.keyspace],(i,t)=>{if(i)return e(i);let s=!1;const n=t.rows.length;for(let l=0;l<n;l++)if(t.rows[l].columnfamily_name===this.settings.columnFamily){s=!0;break}if(s)return e(null);{const l=`CREATE COLUMNFAMILY "${this.settings.columnFamily}" (key text PRIMARY KEY, data text)`;this.client&&this.client.execute(l,e)}})}get(e,i){const t=`SELECT data FROM "${this.settings.columnFamily}" WHERE key = ?`;this.client&&this.client.execute(t,[e],(s,n)=>s?i(s):!n.rows||n.rows.length===0?i(null,null):i(null,n.rows[0].data))}findKeys(e,i,t){let s=null;if(!i)s=`SELECT key FROM "${this.settings.columnFamily}"`,this.client&&this.client.execute(s,(n,l)=>{if(n)return t(n);const u=new RegExp(`^${e.replace(/\*/g,".*")}$`),a=[];return l.rows.forEach(c=>{u.test(c.key)&&a.push(c.key)}),t(null,a)});else if(i==="*:*:*"){const n=/^([^:]+):\*$/.exec(e);if(n)s=`SELECT * from "${this.settings.columnFamily}" WHERE key = ?`,this.client&&this.client.execute(s,[`ueberdb:keys:${n[1]}`],(l,u)=>{if(l)return t(l);if(!u.rows||u.rows.length===0)return t(null,[]);const a=u.rows.map(c=>c.data);return t(null,a)});else{const l="Cassandra db only supports key patterns like pad:* when notKey is set to *:*:*";return t(new Error(l),null)}}else return t(new Error("Cassandra db currently only supports *:*:* as notKey"),null)}set(e,i,t){this.doBulk([{type:"set",key:e,value:i}],t)}remove(e,i){this.doBulk([{type:"remove",key:e}],i)}doBulk(e,i){const t=[];e.forEach(s=>{const n=/^([^:]+):([^:]+)$/.exec(s.key);s.type==="set"?(t.push({query:`UPDATE "${this.settings.columnFamily}" SET data = ? WHERE key = ?`,params:[s.value,s.key]}),n&&t.push({query:`UPDATE "${this.settings.columnFamily}" SET data = ? WHERE key = ?`,params:["1",`ueberdb:keys:${n[1]}`]})):s.type==="remove"&&(t.push({query:`DELETE FROM "${this.settings.columnFamily}" WHERE key=?`,params:[s.key]}),n&&t.push({query:`DELETE FROM "${this.settings.columnFamily}" WHERE key = ?`,params:[`ueberdb:keys:${n[1]}`]}))}),this.client&&this.client.batch(t,{prepare:!0},i)}close(e){this.pool.shutdown(e)}};exports.Database=f;
@@ -0,0 +1 @@
1
+ "use strict";var u=Object.defineProperty;var c=(o,n,t)=>n in o?u(o,n,{enumerable:!0,configurable:!0,writable:!0,value:t}):o[n]=t;var d=(o,n,t)=>(c(o,typeof n!="symbol"?n+"":n,t),t);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const h=require("../lib/AbstractDatabase.cjs"),l=require("../_virtual/__vite-browser-external.cjs"),g=require("../node_modules/nano/lib/nano.cjs"),f=class extends h{constructor(t){super();d(this,"agent");d(this,"db");this.agent=null,this.db=null,this.settings=t,this.settings.cache=1e3,this.settings.writeInterval=100,this.settings.json=!1}get isAsync(){return!0}async init(){this.agent=new l.Agent({keepAlive:!0,maxSockets:this.settings.maxListeners||1});const t={url:`http://${this.settings.host}:${this.settings.port}`,requestDefaults:{agent:this.agent}};this.settings.user&&this.settings.password&&(t.requestDefaults.auth={username:this.settings.user,password:this.settings.password});const s=g(t);try{await s.db.get(this.settings.database)}catch(e){if(e.statusCode!==404)throw e;await s.db.create(this.settings.database)}this.db=s.use(this.settings.database)}async get(t){let s;try{this.db&&(s=await this.db.get(t))}catch(e){if(e.statusCode===404)return null;throw e}return s&&"value"in s?s.value:""}async findKeys(t,s){const e=t.indexOf("*");if(!this.db)return;const i=e<0?t:t.slice(0,e);return(await this.db.find({selector:{_id:e<0?i:{$gte:i,$lte:`${i}￰`,$regex:this.createFindRegex(t,s).source}},fields:["_id"]})).docs.map(r=>r._id)}async set(t,s){let e;if(this.db){try{e=await this.db.get(t)}catch(i){if(i.statusCode!==404)throw i}await this.db.insert({_id:t,value:s,...e==null?{}:{_rev:e._rev}})}}async remove(t){let s;if(!this.db)return;try{s=await this.db.head(t)}catch(i){if(i.statusCode===404)return;throw i}const e=JSON.parse(s.etag);await this.db.destroy(t,e)}async doBulk(t){if(!this.db)return;const s=t.map(a=>a.key),e={};for(const{key:a,value:r}of(await this.db.fetchRevs({keys:s})).rows)r!=null&&(e[a]=r.rev);const i=[];for(const a of t){const r={_id:a.key,_rev:void 0,_deleted:!1,value:""};e[a.key]!=null&&(r._rev=e[a.key]),a.type==="set"&&(r.value=a.value),a.type==="remove"&&(r._deleted=!0),i.push(r)}await this.db.bulk({docs:i})}async close(){this.db=null,this.agent&&this.agent.destroy(),this.agent=null}};exports.Database=f;
@@ -0,0 +1 @@
1
+ "use strict";var h=Object.defineProperty;var d=(s,e,t)=>e in s?h(s,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):s[e]=t;var l=(s,e,t)=>(d(s,typeof e!="symbol"?e+"":e,t),t);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const o=require("../lib/AbstractDatabase.cjs"),c=require("../node_modules/dirty/lib/dirty/index.cjs"),b=class extends o{constructor(e){super();l(this,"db");this.db=null,(!e||!e.filename)&&(e={filename:null}),this.settings=e,this.settings.cache=0,this.settings.writeInterval=0,this.settings.json=!1}init(e){this.db=new c.default(this.settings.filename),this.db.on("load",t=>{e()})}get(e,t){t(null,this.db.get(e))}findKeys(e,t,i){const n=[],r=this.createFindRegex(e,t);this.db.forEach((a,u)=>{a.search(r)!==-1&&n.push(a)}),i(null,n)}set(e,t,i){this.db.set(e,t,i)}remove(e,t){this.db.rm(e,t)}close(e){this.db.close(),this.db=null,e&&e()}};exports.Database=b;
@@ -0,0 +1 @@
1
+ "use strict";var d=Object.defineProperty;var c=(s,t,e)=>t in s?d(s,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):s[t]=e;var a=(s,t,e)=>(c(s,typeof t!="symbol"?t+"":t,e),e);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const h=require("../lib/AbstractDatabase.cjs"),l=require("../node_modules/dirty/lib/dirty/index.cjs"),u=class extends h{constructor(t){super();a(this,"db");this.db=null,(!t||!t.filename)&&(t={}),this.settings=t,this.settings.cache=0,this.settings.writeInterval=0,this.settings.json=!1}init(t){this.db=new l.dirty.Dirty(this.settings.filename),this.db.on("load",e=>{t()})}get(t,e){e(null,this.db.get(t))}findKeys(t,e,r){const i=[],o=this.createFindRegex(t,e);this.db.forEach((n,b)=>{n.search(o)!==-1&&i.push(n)}),r(null,i)}set(t,e,r){this.db.set(t,e,r);const i=require("path").dirname(this.settings.filename);require("simple-git")(i).silent(!0).add("./*.db").commit("Automated commit...").push(["-u","origin","master"],()=>console.debug("Stored git commit"))}remove(t,e){this.db.rm(t,e)}close(t){this.db.close(),t&&t()}};exports.Database=u;
@@ -0,0 +1 @@
1
+ "use strict";var q=Object.defineProperty;var k=(i,e,t)=>e in i?q(i,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):i[e]=t;var l=(i,e,t)=>(k(i,typeof e!="symbol"?e+"":e,t),t);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const v=require("../lib/AbstractDatabase.cjs"),w=require("assert");require("../node_modules/buffer/index.cjs");const C=require("crypto"),M=require("../node_modules/elasticsearch8/index.cjs"),S=require("../_virtual/index3.cjs"),j="2",c=i=>{const e=S.__exports.Buffer.from(i);return e.length>512?C.createHash("sha512").update(e).digest("hex"):i},y={properties:{key:{type:"wildcard"},value:{type:"object",enabled:!1}}},D=async(i,e,t,s)=>{let n=0,r=0;const f=new Map;s.info(`Attempting elasticsearch record migration from schema v1 at base index ${e} to schema v2 at index ${t}...`);const $=await i.indices.get({index:[e,`${e}-*-*`]}),u=new Map,d=[];try{for(const a of Object.keys($)){const o=await i.search({index:a,scroll:"10m"});u.set(a,o._scroll_id),d.push({index:a,res:o})}for(;d.length;){const{index:a,res:{hits:{hits:o,total:{value:b}}}}=d.shift();if(o.length===0)continue;f.set(a,b);const m=[];for(const{_id:h,_type:_,_source:{val:x}}of o){let g=`${_}:${h}`;if(e&&a!==e){const p=a.slice(e.length+1).split("-");if(p.length!==2)throw new Error(`unable to migrate records from index ${a} due to data ambiguity`);g=`${p[0]}:${decodeURIComponent(_)}:${p[1]}:${h}`}m.push({index:{_id:c(g)}},{key:g,value:JSON.parse(x)})}if(await i.bulk({index:t,body:m}),r+=o.length,Math.floor(r/100)>Math.floor(n/100)){const h=[...f.values()].reduce((_,x)=>_+x,0);s.info(`Migrated ${r} records out of ${h}`),n=r}d.push({index:a,res:await i.scroll({scroll:"5m",scroll_id:u.get(a)})})}s.info(`Finished migrating ${r} records`)}finally{await Promise.all([...u.values()].map(a=>i.clearScroll({scroll_id:a})))}},A=class extends v{constructor(e){super();l(this,"_client");l(this,"_index");l(this,"_indexClean");l(this,"_q");this._client=null,this.settings={host:"127.0.0.1",port:"9200",base_index:"ueberes",migrate_to_newer_schema:!1,api:"7.6",...e||{},json:!1},this._index=`${this.settings.base_index}_s${j}`,this._q={index:this._index},this._indexClean=!0}get isAsync(){return!0}async _refreshIndex(){this._indexClean||(this._indexClean=!0,await this._client.indices.refresh(this._q))}async init(){const e=new M.elasticsearch8.Client({node:`http://${this.settings.host}:${this.settings.port}`});if(await e.ping(),!await e.indices.exists({index:this._index})){let s;const n=await e.indices.exists({index:this.settings.base_index});if(n&&!this.settings.migrate_to_newer_schema)throw new Error(`Data exists under the legacy index (schema) named ${this.settings.base_index}. Set migrate_to_newer_schema to true to copy the existing data to a new index named ${this._index}.`);let r=0;for(;s=`${this._index}_${n?"migrate_attempt_":"i"}${r++}`,!!await e.indices.exists({index:s}););await e.indices.create({index:s,mappings:y}),n&&await D(e,this.settings.base_index,s,this.logger),await e.indices.putAlias({index:s,name:this._index})}const t=Object.values(await e.indices.get({index:this._index}));w.equal(t.length,1);try{w.deepEqual(t[0].mappings,y)}catch(s){this.logger.warn(`Index ${this._index} mappings does not match expected; attempting to use index anyway. Details: ${s}`)}this._client=e}async get(e){const t=await this._client.get({...this._q,id:c(e)},{ignore:[404]});return t.found?t._source.value:null}async findKeys(e,t){await this._refreshIndex();const s={...this._q,body:{query:{bool:{filter:{wildcard:{key:{value:e}}},...t==null?{}:{must_not:{wildcard:{key:{value:t}}}}}}}},{hits:n}=await this._client.search(s);return n.hits.map(r=>r._source.key)}async set(e,t){this._indexClean=!1,await this._client.index({...this._q,id:c(e),body:{key:e,value:t}})}async remove(e){this._indexClean=!1,await this._client.delete({...this._q,id:c(e)},{ignore:[404]})}async doBulk(e){const t=[];for(const{type:s,key:n,value:r}of e)switch(this._indexClean=!1,s){case"set":t.push({index:{_id:c(n)}}),t.push({key:n,value:r});break;case"remove":t.push({delete:{_id:c(n)}});break}await this._client.bulk({...this._q,body:t})}async close(){this._client!=null&&this._client.close(),this._client=null}};exports.Database=A;
@@ -0,0 +1 @@
1
+ "use strict";var d=Object.defineProperty;var c=(a,e,t)=>e in a?d(a,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):a[e]=t;var r=(a,e,t)=>(c(a,typeof e!="symbol"?e+"":e,t),t);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const l=require("../lib/AbstractDatabase.cjs"),o=class extends l{constructor(t){super();r(this,"_data");this.settings=t,t.json=!1,t.cache=0,t.writeInterval=0,this._data=null}get isAsync(){return!0}close(){this._data=null}findKeys(t,s){const i=this.createFindRegex(t,s);return[...this._data.keys()].filter(n=>i.test(n))}get(t){return this._data.get(t)}init(){this._data=this.settings.data||new Map}remove(t){this._data.delete(t)}set(t,s){this._data.set(t,s)}};exports.Database=o;
@@ -0,0 +1 @@
1
+ "use strict";var n=Object.defineProperty;var r=(i,t,e)=>t in i?n(i,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):i[t]=e;var o=(i,t,e)=>(r(i,typeof t!="symbol"?t+"":t,e),e);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const a=require("../node_modules/events/events.cjs"),c=class extends a.default.EventEmitter{constructor(t){super();o(this,"settings");o(this,"mock");this.settings={writeInterval:1,...t},t.mock=this,this.settings=t,console.log("Initialized")}close(t){this.emit("close",t)}doBulk(t,e){this.emit("doBulk",t,e)}findKeys(t,e,s){this.emit("findKeys",t,e,s)}get(t,e){this.emit("get",t,e)}async init(t){this.emit("init",t())}remove(t,e){this.emit("remove",t,e)}set(t,e,s){this.emit("set",t,e,s)}};exports.Database=c;
@@ -0,0 +1 @@
1
+ "use strict";var c=Object.defineProperty;var h=(n,e,t)=>e in n?c(n,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):n[e]=t;var o=(n,e,t)=>(h(n,typeof e!="symbol"?e+"":e,t),t);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const a=require("../lib/AbstractDatabase.cjs");require("../node_modules/mongodb/lib/index.cjs");const r=require("../_virtual/index2.cjs"),d=class extends a{constructor(e){super();o(this,"interval");o(this,"database");o(this,"client");o(this,"collection");if(this.settings=e,!this.settings.url)throw new Error("You must specify a mongodb url");this.settings.database==null&&(this.settings.database=this.settings.dbName),this.settings.collection||(this.settings.collection="ueberdb")}clearPing(){this.interval&&clearInterval(this.interval[Symbol.toPrimitive]())}schedulePing(){this.clearPing(),this.interval=setInterval(()=>{this.database.command({ping:1})},1e4)}init(e){r.__exports.MongoClient.connect(this.settings.url).then(t=>{this.client=t,this.database=t.db(this.settings.database),this.collection=this.database.collection(this.settings.collection),e(null)}).catch(t=>{e(t)}),this.schedulePing()}get(e,t){this.collection.findOne({_id:e}).then(i=>{t(null,i&&i.value)}).catch(i=>{console.log(i),t(i)}),this.schedulePing()}findKeys(e,t,i){const s={$and:[{_id:{$regex:`${e.replace(/\*/g,"")}`}}]};t&&s.$and.push({_id:{$not:{$regex:`${t.replace(/\*/g,"")}`}}}),this.collection.find(s).map(l=>l._id).toArray().then(l=>{i(null,l)}).catch(l=>i(l)),this.schedulePing()}set(e,t,i){e.length>100?i("Your Key can only be 100 chars"):this.collection.updateMany({_id:e},{$set:{value:t}},{upsert:!0}).then(()=>i(null)).catch(s=>i(s)),this.schedulePing()}remove(e,t){this.collection.deleteOne({_id:e}).then(i=>t(null,i)).catch(i=>t(i)),this.schedulePing()}doBulk(e,t){const i=this.collection.initializeOrderedBulkOp();for(const s in e)e[s].type==="set"?i.find({_id:e[s].key}).upsert().updateOne({$set:{value:e[s].value}}):e[s].type==="remove"&&i.find({_id:e[s].key}).deleteOne();i.execute().then(s=>{t(null,s)}).catch(s=>{t(s)}),this.schedulePing()}close(e){this.clearPing(),this.client.close().then(t=>e(t))}};exports.Database=d;
@@ -0,0 +1,5 @@
1
+ "use strict";var h=Object.defineProperty;var R=(T,N,e)=>N in T?h(T,N,{enumerable:!0,configurable:!0,writable:!0,value:e}):T[N]=e;var y=(T,N,e)=>(R(T,typeof N!="symbol"?N+"":N,e),e);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const f=require("../lib/AbstractDatabase.cjs"),v=require("../node_modules/async/dist/async.cjs"),u=require("../node_modules/mssql/index.cjs"),A=class extends f{constructor(e){super();y(this,"db");e=e||{},e.json!=null&&(e.parseJSON=e.json),e.requestTimeout=3e5,e.server=e.host,this.settings=e,this.settings.cache=0,this.settings.writeInterval=0}init(e){const r="IF OBJECT_ID(N'dbo.store', N'U') IS NULL BEGIN CREATE TABLE [store] ( [key] NVARCHAR(100) PRIMARY KEY, [value] NTEXT NOT NULL ); END";new u.ConnectionPool(this.settings).connect().then(n=>{this.db=n,new u.Request(this.db).query(r,s=>{e(s)}),this.db.on("error",s=>{console.log(s)})})}get(e,r){const n=new u.Request(this.db);n.input("key",u.NVarChar(100),e),n.query("SELECT [value] FROM [store] WHERE [key] = @key",(o,s)=>{let E=null;!o&&s&&s.rowsAffected[0]===1&&(E=s.recordset[0].value),r(o,E)})}findKeys(e,r,n){const o=new u.Request(this.db);let s="SELECT [key] FROM [store] WHERE [key] LIKE @key";e=e.replace(/\*/g,"%"),o.input("key",u.NVarChar(100),e),r!=null&&(r=r.replace(/\*/g,"%"),o.input("notkey",u.NVarChar(100),r),s+=" AND [key] NOT LIKE @notkey"),o.query(s,(E,a)=>{const i=[];if(!E&&a&&a.rowsAffected[0]>0)for(let t=0;t<a.recordset.length;t++)i.push(a.recordset[t].key);n(E,i)})}set(e,r,n){const o=new u.Request(this.db);if(e.length>100)n("Your Key can only be 100 chars");else{const s="MERGE [store] t USING (SELECT @key [key], @value [value]) s ON t.[key] = s.[key] WHEN MATCHED AND s.[value] IS NOT NULL THEN UPDATE SET t.[value] = s.[value] WHEN NOT MATCHED THEN INSERT ([key], [value]) VALUES (s.[key], s.[value]);";o.input("key",u.NVarChar(100),e),o.input("value",u.NText,r),o.query(s,(E,a)=>{n(E?E.toString():"")})}}remove(e,r){const n=new u.Request(this.db);n.input("key",u.NVarChar(100),e),n.query("DELETE FROM [store] WHERE [key] = @key",r)}doBulk(e,r){const o=new u.Request(this.db);let s=!0,E=!0;const a=[];let i="DELETE FROM [store] WHERE [key] IN (";for(const t in e)e[t].type==="set"?(s?(a.push("BEGIN TRANSACTION;"),s=!1):Number(t)%100===0&&a.push(`
2
+ COMMIT TRANSACTION;
3
+ BEGIN TRANSACTION;
4
+ `),a.push(`MERGE [store] t USING (SELECT '${e[t].key}' [key], '${e[t].value}' [value]) s`,"ON t.[key] = s.[key]","WHEN MATCHED AND s.[value] IS NOT NULL THEN UPDATE SET t.[value] = s.[value]","WHEN NOT MATCHED THEN INSERT ([key], [value]) VALUES (s.[key], s.[value]);")):e[t].type==="remove"&&(E||(i+=","),E=!1,i+=`'${e[t].key}'`);i+=");",a.push("COMMIT TRANSACTION;"),v.default.parallel([t=>{s?t():o.batch(a.join(`
5
+ `),(l,c)=>{l&&t(l),t(l,c)})},t=>{E?t():o.query(i,t)}],(t,l)=>{t&&r(t),r(t,l)})}close(e){this.db&&this.db.close(e)}};exports.Database=A;
@@ -0,0 +1 @@
1
+ "use strict";var c=Object.defineProperty;var h=(i,t,e)=>t in i?c(i,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):i[t]=e;var l=(i,t,e)=>(h(i,typeof t!="symbol"?t+"":t,e),e);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const u=require("../lib/AbstractDatabase.cjs");require("crypto");require("../node_modules/events/events.cjs");require("../node_modules/buffer/index.cjs");const E=require("util");require("../node_modules/string_decoder/lib/string_decoder.cjs");const A=class extends u{constructor(t){super();l(this,"_mysqlSettings");l(this,"_pool");this.logger=console,this._mysqlSettings={charset:"utf8mb4",...t},this.settings={engine:"InnoDB",bulkLimit:100,json:!0,queryTimeout:6e4},this._pool=null}get isAsync(){return!0}async _query(t){try{return await new Promise((e,r)=>{t={timeout:this.settings.queryTimeout,...t},this._pool&&this._pool.query(t,(s,...n)=>s!=null?r(s):e(n))})}catch(e){throw this.logger.error(`${e.fatal?"Fatal ":""}MySQL error: ${e.stack||e}`),e}}async init(){this._pool=(void 0)(this._mysqlSettings);const{database:t,charset:e}=this._mysqlSettings,r=`CREATE TABLE IF NOT EXISTS \`store\` ( \`key\` VARCHAR( 100 ) NOT NULL COLLATE utf8mb4_bin, \`value\` LONGTEXT COLLATE utf8mb4_bin NOT NULL , PRIMARY KEY ( \`key\` ) ) ENGINE=${this.settings.engine} CHARSET=utf8mb4 COLLATE=utf8mb4_bin;`,s="ALTER TABLE store MODIFY `key` VARCHAR(100) COLLATE utf8mb4_bin;";await this._query({sql:r});const n=`SELECT DEFAULT_CHARACTER_SET_NAME, DEFAULT_COLLATION_NAME FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME = '${t}'`;let[a]=await this._query({sql:n});a=JSON.parse(JSON.stringify(a)),a[0].DEFAULT_CHARACTER_SET_NAME!==e&&(this.logger.error(`Database is not configured with charset ${e} -- This may lead to crashes when certain characters are pasted in pads`),this.logger.log(a[0],e)),a[0].DEFAULT_COLLATION_NAME.indexOf(e)===-1&&(this.logger.error(`Database is not configured with collation name that includes ${e} -- This may lead to crashes when certain characters are pasted in pads`),this.logger.log(a[0],e,a[0].DEFAULT_COLLATION_NAME));const o=`SELECT CCSA.character_set_name AS character_set_name FROM information_schema.\`TABLES\` T,information_schema.\`COLLATION_CHARACTER_SET_APPLICABILITY\` CCSA WHERE CCSA.collation_name = T.table_collation AND T.table_schema = '${t}' AND T.table_name = 'store'`;[a]=await this._query({sql:o}),a[0]||this.logger.warn("Data has no character_set_name value -- This may lead to crashes when certain characters are pasted in pads"),a[0]&&a[0].character_set_name!==e&&(this.logger.error(`table is not configured with charset ${e} -- This may lead to crashes when certain characters are pasted in pads`),this.logger.log(a[0],e)),await this.get("MYSQL_MIGRATION_LEVEL")!=="1"&&(await this._query({sql:s}),await this.set("MYSQL_MIGRATION_LEVEL","1"))}async get(t){const[e]=await this._query({sql:"SELECT `value` FROM `store` WHERE `key` = ? AND BINARY `key` = ?",values:[t,t]});return e.length===1?e[0].value:null}async findKeys(t,e){let r="SELECT `key` FROM `store` WHERE `key` LIKE ?";const s=[];t=t.replace(/\*/g,"%"),s.push(t),e!=null&&(e=e.replace(/\*/g,"%"),r+=" AND `key` NOT LIKE ?",s.push(e));const[n]=await this._query({sql:r,values:s});return n.map(a=>a.key)}async set(t,e){if(t.length>100)throw new Error("Your Key can only be 100 chars");await this._query({sql:"REPLACE INTO `store` VALUES (?,?)",values:[t,e]})}async remove(t){await this._query({sql:"DELETE FROM `store` WHERE `key` = ? AND BINARY `key` = ?",values:[t,t]})}async doBulk(t){const e=[],r=[];for(const s of t)switch(s.type){case"set":e.push([s.key,s.value]);break;case"remove":r.push(s.key);break;default:throw new Error(`unknown op type: ${s.type}`)}await Promise.all([e.length?this._query({sql:"REPLACE INTO `store` VALUES ?;",values:[e]}):null,r.length?this._query({sql:"DELETE FROM `store` WHERE `key` IN (?) AND BINARY `key` IN (?);",values:[r,r]}):null])}async close(){await E.promisify(this._pool.end.bind(this._pool))()}};exports.Database=A;
@@ -0,0 +1 @@
1
+ "use strict";var c=Object.defineProperty;var T=(E,e,t)=>e in E?c(E,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):E[e]=t;var l=(E,e,t)=>(T(E,typeof e!="symbol"?e+"":e,t),t);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const p=require("../lib/AbstractDatabase.cjs"),y=require("../node_modules/async/dist/async.cjs");require("../node_modules/pg/lib/client.cjs");require("../node_modules/pg/lib/defaults.cjs");require("../node_modules/pg/lib/connection.cjs");require("../node_modules/events/events.cjs");require("../node_modules/pg-protocol/dist/index.cjs");require("../node_modules/pg-types/index.cjs");require("../node_modules/pg/lib/type-overrides.cjs");require("util");require("../node_modules/pg/lib/connection-parameters.cjs");const d=class extends p{constructor(e){super();l(this,"db");l(this,"upsertStatement");typeof e=="string"&&(e={connectionString:e}),this.settings=e,this.settings.cache=e.cache||1e3,this.settings.writeInterval=100,this.settings.json=!0,this.settings.max=this.settings.max||20,this.settings.min=this.settings.min||4,this.settings.idleTimeoutMillis=this.settings.idleTimeoutMillis||1e3,this.db=new(void 0)(this.settings)}init(e){const t="SELECT 1 as exists FROM pg_tables WHERE tablename = 'store'",n='CREATE TABLE IF NOT EXISTS store ("key" character varying(100) NOT NULL, "value" text NOT NULL, CONSTRAINT store_pkey PRIMARY KEY (key))';this.upsertStatement=null;const r=s=>{const o="SELECT ueberdb_insert_or_update($1,$2)",u="INSERT INTO store(key, value) VALUES ($1, $2) ON CONFLICT (key) DO UPDATE SET value = excluded.value",a="CREATE OR REPLACE FUNCTION ueberdb_insert_or_update(character varying, text) RETURNS void AS $$ BEGIN IF EXISTS( SELECT * FROM store WHERE key = $1 ) THEN UPDATE store SET value = $2 WHERE key = $1; ELSE INSERT INTO store(key,value) VALUES( $1, $2 ); END IF; RETURN; END; $$ LANGUAGE plpgsql;",i=`EXPLAIN ${u}`;this.db.query(i,["test-key","test-value"],h=>{if(h){this.upsertStatement=o,this.db.query(a,[],s);return}this.upsertStatement=u,s()})};this.db.query(t,(s,o)=>{if(s!=null)return e(s);o.rows.length===0?this.db.query(n,u=>{if(u!=null)return e(u);r(e)}):r(e)})}get(e,t){this.db.query("SELECT value FROM store WHERE key=$1",[e],(n,r)=>{let s=null;!n&&r.rows.length===1&&(s=r.rows[0].value),t(n,s)})}findKeys(e,t,n){let r="SELECT key FROM store WHERE key LIKE $1";const s=[];e=e.replace(/\*/g,"%"),s.push(e),t!=null&&(t=t.replace(/\*/g,"%"),r+=" AND key NOT LIKE $2",s.push(t)),this.db.query(r,s,(o,u)=>{const a=[];!o&&u.rows.length>0&&u.rows.forEach(i=>{a.push(i.key)}),n(o,a)})}set(e,t,n){if(e.length>100){const r="";n(Error("Your Key can only be 100 chars"),r)}else this.upsertStatement!=null&&this.db.query(this.upsertStatement,[e,t],n)}remove(e,t){this.db.query("DELETE FROM store WHERE key=$1",[e],t)}doBulk(e,t){const n=[];let r="DELETE FROM store WHERE key IN (";const s=[];let o=0;for(const i in e)e[i].type==="set"?n.push([e[i].key,e[i].value]):e[i].type==="remove"&&(o!==0&&(r+=","),o+=1,r+=`$${o}`,s.push(e[i].key));if(r+=");",!this.upsertStatement)return;const u=n.map(i=>h=>this.db.query(this.upsertStatement,i,h)),a=i=>{s.length>1?i():this.db.query(r,s,i)};u.push(a),y.default.parallel(u,t)}close(e){this.db.end(e)}};exports.Database=d;
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const s=require("./postgres_db"),t=class extends s.Database{constructor(e){console.warn("ueberdb: The postgrespool database driver is deprecated and will be removed in a future version. Use postgres instead."),super(e)}};exports.Database=t;
@@ -0,0 +1 @@
1
+ "use strict";var h=Object.defineProperty;var o=(l,i,t)=>i in l?h(l,i,{enumerable:!0,configurable:!0,writable:!0,value:t}):l[i]=t;var u=(l,i,t)=>(o(l,typeof i!="symbol"?i+"":i,t),t);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const _=require("../lib/AbstractDatabase.cjs");require("../node_modules/redis/dist/index.cjs");const a=require("../_virtual/index.cjs"),f=class extends _{constructor(t){super();u(this,"_client");this._client=null,this.settings=t||{}}get isAsync(){return!0}async init(){if(this.settings.url)this._client=a.__exports.createClient({url:this.settings.url});else if(this.settings.host){const t={socket:{host:this.settings.host,port:Number(this.settings.port)}};this.settings.password&&(t.password=this.settings.password),this.settings.user&&(t.username=this.settings.user),this._client=a.__exports.createClient(t)}this._client&&(await this._client.connect(),await this._client.ping())}async get(t){return this._client==null?null:await this._client.get(t)}async findKeys(t,e){if(this._client==null)return null;const[s]=/^([^:*]+):\*$/.exec(t)||[];if(s!=null&&["*:*:*",`${t}:*`].includes(e))return await this._client.sMembers(`ueberDB:keys:${s}`);let r=await this._client.keys(t.replace(/[?[\]\\]/g,"\\$&"));if(e!=null){const c=this.createFindRegex(t,e);r=r.filter(n=>c.test(n))}return r}async set(t,e){if(this._client==null)return null;const s=/^([^:]+):([^:]+)$/.exec(t);await Promise.all([s&&this._client.sAdd(`ueberDB:keys:${s[1]}`,s[0]),this._client.set(t,e)])}async remove(t){if(this._client==null)return null;const e=/^([^:]+):([^:]+)$/.exec(t);await Promise.all([e&&this._client.sRem(`ueberDB:keys:${e[1]}`,e[0]),this._client.del(t)])}async doBulk(t){if(this._client==null)return null;const e=this._client.multi();for(const{key:s,type:r,value:c}of t){const n=/^([^:]+):([^:]+)$/.exec(s);r==="set"?(n&&e.sAdd(`ueberDB:keys:${n[1]}`,n[0]),e.set(s,c)):r==="remove"&&(n&&e.sRem(`ueberDB:keys:${n[1]}`,n[0]),e.del(s))}await e.exec()}async close(){if(this._client==null)return null;await this._client.quit(),this._client=null}};exports.Database=f;
@@ -0,0 +1 @@
1
+ "use strict";var l=Object.defineProperty;var h=(s,t,e)=>t in s?l(s,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):s[t]=e;var r=(s,t,e)=>(h(s,typeof t!="symbol"?t+"":t,e),e);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const b=require("../lib/AbstractDatabase.cjs"),c=require("../node_modules/rethinkdb/rethinkdb.cjs"),u=require("../node_modules/async/dist/async.cjs"),d=class extends b{constructor(t){super();r(this,"host");r(this,"db");r(this,"port");r(this,"table");r(this,"connection");t||(t={}),t.host||(t.host="localhost"),t.port||(t.port=28015),t.db||(t.db="test"),t.table||(t.table="test"),this.host=t.host,this.db=t.db,this.port=t.port,this.table=t.table,this.connection=null}init(t){c.connect(this,(e,o)=>{if(e)throw e;this.connection=o,c.table(this.table).run(this.connection,(i,n)=>{i?c.tableCreate(this.table).run(this.connection,t):t&&t(null,n)})})}get(t,e){c.table(this.table).get(t).run(this.connection,(o,i)=>{e(o,i&&i.content)})}findKeys(t,e,o){const i=[],n=this.createFindRegex(t,e);c.filter(a=>{a.id.search(n)!==-1&&i.push(a.id)}).run(this.connection,o)}set(t,e,o){c.table(this.table).insert({id:t,content:e},{conflict:"replace"}).run(this.connection,o)}doBulk(t,e){const o=[],i=[];for(const n in t)t[n].type==="set"?o.push({id:t[n].key,content:t[n].value}):t[n].type==="remove"&&i.push(t[n].key);u.default.parallel([n=>{c.table(this.table).insert(o,{conflict:"replace"}).run(this.connection,n)},n=>{c.table(this.table).getAll(i).delete().run(this.connection,n)}],e)}remove(t,e){c.table(this.table).get(t).delete().run(this.connection,e)}close(t){this.connection&&this.connection.close(t)}};exports.Database=d;
@@ -0,0 +1,4 @@
1
+ "use strict";var f=Object.defineProperty;var d=(n,a,e)=>a in n?f(n,a,{enumerable:!0,configurable:!0,writable:!0,value:e}):n[a]=e;var h=(n,a,e)=>(d(n,typeof a!="symbol"?a+"":a,e),e);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const T=require("../lib/AbstractDatabase.cjs"),b=require("util");let c;try{c=require("sqlite3").Database}catch{throw new Error(`sqlite3 not found. It was removed from ueberdb's dependencies because it requires compilation which fails on several systems. If you still want to use sqlite, run "npm install sqlite3" in your etherpad-lite ./src directory.`)}const l=n=>`'${n.replace(/'/g,"''")}'`,m=class extends T{constructor(e){super();h(this,"db");this.db=null,(!e||!e.filename)&&(e={filename:":memory:"}),this.settings=e,e.filename===":memory:"?(this.settings.cache=0,this.settings.writeInterval=0,this.settings.json=!0):(this.settings.cache=1e3,this.settings.writeInterval=100,this.settings.json=!0)}init(e){b.callbackify(async()=>{this.db=new c(this.settings.filename),await this._query("CREATE TABLE IF NOT EXISTS store (key TEXT PRIMARY KEY, value TEXT)")})(e)}async _query(e,s=[]){return await new Promise((i,t)=>{this.db&&this.db.all(e,s,(r,o)=>{if(r!=null)return t(r);i(o)})})}_queryCb(e,s,i){const t=this._query(e,s);i&&t.then(r=>i(null,r),r=>i(r||new Error(r)))}get(e,s){this._queryCb("SELECT value FROM store WHERE key = ?",[e],(i,t)=>s(i,i==null&&t&&t.length?t[0].value:null))}findKeys(e,s,i){let t="SELECT key FROM store WHERE key LIKE ?";const r=[];e=e.replace(/\*/g,"%"),r.push(e),s!=null&&(s=s.replace(/\*/g,"%"),t+=" AND key NOT LIKE ?",r.push(s)),this._queryCb(t,r,(o,u)=>{const E=[];!o&&Object.keys(u).length>0&&u.forEach(y=>{E.push(y.key)}),i(o,E)})}set(e,s,i){this._queryCb("REPLACE INTO store VALUES (?,?)",[e,s],i)}remove(e,s){this._queryCb("DELETE FROM store WHERE key = ?",[e],s)}doBulk(e,s){let i=`BEGIN TRANSACTION;
2
+ `;for(const t in e)e[t].type==="set"?i+=`REPLACE INTO store VALUES (${l(e[t].key)}, ${l(e[t].value)});
3
+ `:e[t].type==="remove"&&(i+=`DELETE FROM store WHERE key = ${l(e[t].key)};
4
+ `);i+="END TRANSACTION;",this.db&&this.db.exec(i,t=>{t&&(console.error("ERROR WITH SQL: "),console.error(i)),s(t)})}close(e){e(),this.db&&this.db.close(s=>e(s))}};exports.Database=m;
@@ -0,0 +1 @@
1
+ export * from './databases/dirty_db'
@@ -0,0 +1 @@
1
+ export * from './databases/dirty_git_db'
@@ -0,0 +1 @@
1
+ export * from './databases/elasticsearch_db'
@@ -0,0 +1,85 @@
1
+ import { Settings } from './lib/AbstractDatabase';
2
+ export declare const Database: {
3
+ new (type: undefined | string, dbSettings: Settings | null | string, wrapperSettings?: null | {}, logger?: any): {
4
+ readonly type: any;
5
+ dbModule: any;
6
+ readonly dbSettings: any;
7
+ readonly wrapperSettings: any | {};
8
+ readonly logger: Function | null;
9
+ db: any;
10
+ metrics: any;
11
+ /**
12
+ * @param callback - Deprecated. Node-style callback. If null, a Promise is returned.
13
+ */
14
+ init(callback?: null): Promise<any>;
15
+ /**
16
+ * Wrapper functions
17
+ */
18
+ /**
19
+ * Deprecated synonym of flush().
20
+ *
21
+ * @param callback - Deprecated. Node-style callback. If null, a Promise is returned.
22
+ */
23
+ doShutdown(callback?: null): any;
24
+ /**
25
+ * Writes any unsaved changes to the underlying database.
26
+ *
27
+ * @param callback - Deprecated. Node-style callback. If null, a Promise is returned.
28
+ */
29
+ flush(callback?: null): any;
30
+ /**
31
+ * @param key
32
+ * @param callback - Deprecated. Node-style callback. If null, a Promise is returned.
33
+ */
34
+ get(key: string, callback?: null): any;
35
+ /**
36
+ * @param key
37
+ * @param notKey
38
+ * @param callback - Deprecated. Node-style callback. If null, a Promise is returned.
39
+ */
40
+ findKeys(key: string, notKey: string, callback?: null): any;
41
+ /**
42
+ * Removes an entry from the database if present.
43
+ *
44
+ * @param key
45
+ * @param cb Deprecated. Node-style callback. Called when the write has been committed to the
46
+ * underlying database driver. If null, a Promise is returned.
47
+ * @param deprecated Deprecated callback that is called just after cb. Ignored if cb is null.
48
+ */
49
+ remove(key: string, cb?: null, deprecated?: null): any;
50
+ /**
51
+ * Adds or changes the value of an entry.
52
+ *
53
+ * @param key
54
+ * @param value
55
+ * @param cb Deprecated. Node-style callback. Called when the write has been committed to the
56
+ * underlying database driver. If null, a Promise is returned.
57
+ * @param deprecated Deprecated callback that is called just after cb. Ignored if cb is null.
58
+ */
59
+ set(key: string, value: string, cb?: null, deprecated?: null): any;
60
+ /**
61
+ * @param key
62
+ * @param sub
63
+ * @param callback - Deprecated. Node-style callback. If null, a Promise is returned.
64
+ */
65
+ getSub(key: string, sub: string, callback?: null): any;
66
+ /**
67
+ * Adds or changes a subvalue of an entry.
68
+ *
69
+ * @param key
70
+ * @param sub
71
+ * @param value
72
+ * @param cb Deprecated. Node-style callback. Called when the write has been committed to the
73
+ * underlying database driver. If null, a Promise is returned.
74
+ * @param deprecated Deprecated callback that is called just after cb. Ignored if cb is null.
75
+ */
76
+ setSub(key: string, sub: string, value: string, cb?: null, deprecated?: null): any;
77
+ /**
78
+ * Flushes unwritten changes then closes the connection to the underlying database. After this
79
+ * returns, any future call to a method on this object may result in an error.
80
+ *
81
+ * @param callback - Deprecated. Node-style callback. If null, a Promise is returned.
82
+ */
83
+ close(callback?: null): any;
84
+ };
85
+ };
@@ -0,0 +1 @@
1
+ "use strict";var i=Object.defineProperty;var l=(r,e,t)=>e in r?i(r,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):r[e]=t;var o=(r,e,t)=>(l(r,typeof e!="symbol"?e+"":e,t),t);const g=require("./logging.cjs"),a=g.normalizeLogger(null),s=r=>r.replace(/[.+?^${}()|[\]\\]/g,"\\$&").replace(/\*/g,".*");class c{constructor(){o(this,"logger");o(this,"settings");if(new.target===module.exports)throw new TypeError("cannot instantiate Abstract Database directly");for(const e of["init","close","get","findKeys","remove","set"])if(typeof this[e]!="function")throw new TypeError(`method ${e} not defined`);this.logger=a}createFindRegex(e,t){let n=`^(?=${s(e)}$)`;return t!=null&&(n+=`(?!${s(t)}$)`),new RegExp(n)}doBulk(e,t){throw new Error("the doBulk method must be implemented if write caching is enabled")}get isAsync(){return!1}}module.exports=c;
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const d=require("util");class f{constructor(t,s=(e,i)=>!0){this._capacity=t,this._evictable=s,this._cache=new Map}[Symbol.iterator](){return this._cache.entries()}get(t,s=!0){if(!this._cache.has(t))return;const e=this._cache.get(t);return s&&(this._cache.delete(t),this._cache.set(t,e)),e}set(t,s){this._cache.delete(t),this._cache.set(t,s),this.evictOld()}evictOld(){for(const[t,s]of this._cache.entries()){if(this._cache.size<=this._capacity)break;this._evictable(t,s)&&this._cache.delete(t)}}}class u extends Promise{constructor(t=null){let s;super((e,i)=>{s=(o,n)=>o!=null?i(o):e(n),t!=null&&t(e,i)}),this.done=s}}const g={bulkLimit:0,cache:1e4,writeInterval:100,json:!0,charset:"utf8mb4"},w=class{constructor(t,s,e){if(t.isAsync)this.wrappedDB=t;else{this.wrappedDB={};for(const i of["close","doBulk","findKeys","get","init","remove","set"]){const o=t[i];typeof o=="function"&&(this.wrappedDB[i]=d.promisify(o.bind(t)))}}this.logger=e,this.settings=Object.freeze({...g,...t.settings||{},...s||{}}),this.buffer=new f(this.settings.cache,(i,o)=>!o.dirty&&!o.writingInProgress),this._flushPaused=null,this._locks=new Map,this.metrics={lockAwaits:0,lockAcquires:0,lockReleases:0,reads:0,readsFailed:0,readsFinished:0,readsFromCache:0,readsFromDb:0,readsFromDbFailed:0,readsFromDbFinished:0,writes:0,writesFailed:0,writesFinished:0,writesObsoleted:0,writesToDb:0,writesToDbFailed:0,writesToDbFinished:0,writesToDbRetried:0},this.flushInterval=this.settings.writeInterval>0?setInterval(()=>this.flush(),this.settings.writeInterval):null}async _lock(t){for(;;){const s=this._locks.get(t);if(s==null)break;++this.metrics.lockAwaits,await s}++this.metrics.lockAcquires,this._locks.set(t,new u)}async _unlock(t){++this.metrics.lockReleases,this._locks.get(t).done(),this._locks.delete(t)}_pauseFlush(){this._flushPaused==null&&(this._flushPaused=new u,this._flushPaused.count=0),++this._flushPaused.count}_resumeFlush(){--this._flushPaused.count>0||(this._flushPaused.done(),this._flushPaused=null)}async init(){await this.wrappedDB.init()}async close(){clearInterval(this.flushInterval),await this.flush(),await this.wrappedDB.close(),this.wrappedDB=null}async get(t){let s;await this._lock(t);try{s=await this._getLocked(t)}finally{this._unlock(t)}return c(s)}async _getLocked(t){++this.metrics.reads;try{const s=this.buffer.get(t);if(s!=null)return++this.metrics.readsFromCache,this.logger.isDebugEnabled()&&this.logger.debug(`GET - ${t} - ${JSON.stringify(s.value)} - from ${s.dirty?"dirty buffer":"cache"}`),s.value;let e;++this.metrics.readsFromDb;try{e=await this.wrappedDB.get(t)}catch(i){throw++this.metrics.readsFromDbFailed,i}finally{++this.metrics.readsFromDbFinished}if(this.settings.json)try{e=JSON.parse(e)}catch(i){throw this.logger.error(`JSON-PROBLEM:${e}`),i}return this.settings.cache>0&&this.buffer.set(t,{value:e,dirty:null,writingInProgress:!1}),this.logger.isDebugEnabled()&&this.logger.debug(`GET - ${t} - ${JSON.stringify(e)} - from database `),e}catch(s){throw++this.metrics.readsFailed,s}finally{++this.metrics.readsFinished}}async findKeys(t,s){await this.flush();const e=await this.wrappedDB.findKeys(t,s);return this.logger.isDebugEnabled()&&this.logger.debug(`GET - ${t}-${s} - ${JSON.stringify(e)} - from database `),c(e)}async remove(t){this.logger.isDebugEnabled()&&this.logger.debug(`DELETE - ${t} - from database `),await this.set(t,null)}async set(t,s){s=c(s);let e;this._pauseFlush();try{await this._lock(t);try{e=this._setLocked(t,s)}finally{this._unlock(t)}}finally{this._resumeFlush()}await e}async _setLocked(t,s){++this.metrics.writes;try{let e=this.buffer.get(t);!e||e.writingInProgress?e={}:e.dirty&&++this.metrics.writesObsoleted,e.value=s,e.dirty||(e.dirty=new u),this.buffer.set(t,e);const i=this.settings.writeInterval>0;this.logger.isDebugEnabled()&&this.logger.debug(`SET - ${t} - ${JSON.stringify(s)} - to ${i?"buffer":"database"}`),i||this._write([[t,e]]),await e.dirty}catch(e){throw++this.metrics.writesFailed,e}finally{++this.metrics.writesFinished}}async setSub(t,s,e){e=c(e),this.logger.isDebugEnabled()&&this.logger.debug(`SETSUB - ${t}${JSON.stringify(s)} - ${JSON.stringify(e)}`);let i;this._pauseFlush();try{await this._lock(t);try{let o;try{const n=await this._getLocked(t);o={fullValue:n};const r={obj:o,prop:"fullValue"};for(let a=0;a<s.length;a++){if(s[a]==="__proto__")throw new Error("Modifying object prototype is not supported for security reasons");let h=r.obj[r.prop];if(h==null&&(r.obj[r.prop]=h={}),typeof h!="object")throw new TypeError(`Cannot set property ${JSON.stringify(s[a])} on non-object ${JSON.stringify(h)} (key: ${JSON.stringify(t)} value in db: ${JSON.stringify(n)} sub: ${JSON.stringify(s.slice(0,a+1))})`);r.obj=r.obj[r.prop],r.prop=s[a]}r.obj[r.prop]=e}catch(n){throw++this.metrics.writes,++this.metrics.writesFailed,++this.metrics.writesFinished,n}i=this._setLocked(t,o.fullValue)}finally{this._unlock(t)}}finally{this._resumeFlush()}await i}async getSub(t,s){await this._lock(t);try{let e=await this._getLocked(t);for(const i of s){if((typeof e!="object"||e!=null&&!Object.prototype.hasOwnProperty.call(e,i)||i==="__proto__")&&(e=null),e==null)break;e=e[i]}return this.logger.isDebugEnabled()&&this.logger.debug(`GETSUB - ${t}${JSON.stringify(s)} - ${JSON.stringify(e)}`),c(e)}finally{this._unlock(t)}}async flush(){this._flushDone==null&&(this._flushDone=(async()=>{for(;;){for(;this._flushPaused!=null;)await this._flushPaused;const t=[];for(const s of this.buffer)if(s[1].dirty&&!s[1].writingInProgress&&(t.push(s),this.settings.bulkLimit&&t.length>=this.settings.bulkLimit))break;if(t.length===0)return;await this._write(t)}})()),await this._flushDone,this._flushDone=null}async _write(t){const s=(n,r)=>{n.writingInProgress&&(n.writingInProgress=!1,r!=null&&++this.metrics.writesToDbFailed,++this.metrics.writesToDbFinished),n.dirty.done(r),n.dirty=null},e=[],i=[];for(const[n,r]of t){let a=r.value;try{a=this.settings.json&&a!=null?JSON.stringify(a):c(a)}catch(h){s(r,h);continue}r.writingInProgress=!0,e.push({type:a==null?"remove":"set",key:n,value:a}),i.push(r)}if(e.length===0)return;this.metrics.writesToDb+=e.length;const o=async(n,r)=>{let a=null;try{switch(n.type){case"remove":await this.wrappedDB.remove(n.key);break;case"set":await this.wrappedDB.set(n.key,n.value);break;default:throw new Error(`unsupported operation type: ${n.type}`)}}catch(h){a=h||new Error(h)}s(r,a)};if(e.length===1)await o(e[0],i[0]);else{let n=!1;try{await this.wrappedDB.doBulk(e),n=!0}catch(r){this.logger.error(`Bulk write of ${e.length} ops failed, retrying individually: ${r.stack||r}`),this.metrics.writesToDbRetried+=e.length,await Promise.all(e.map(async(a,h)=>await o(a,i[h])))}n&&i.forEach(r=>s(r,null))}this.buffer.evictOld()}},c=(l,t="")=>{if(l==null||typeof l!="object")return l;if(typeof l.toJSON=="function")return c(l.toJSON(t));if(l instanceof Date){const s=new Date;return s.setTime(l.getTime()),s}if(l instanceof Array){const s=[];for(let e=0,i=l.length;e<i;++e)s[e]=c(l[e],String(e));return s}if(l instanceof Object){const s={};for(const e in l)Object.prototype.hasOwnProperty.call(l,e)&&(s[e]=c(l[e],e));return s}throw new Error("Unable to copy obj! Its type isn't supported.")};exports.Database=w;exports.LRU=f;
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});require("console");require("process");const o=e=>{const r=["debug","info","warn","error"];e=Object.create(e||{});for(const t of r){const n=`is${t.charAt(0).toUpperCase()+t.slice(1)}Enabled`;typeof e[t]!="function"?(e[t]=()=>{},e[n]=()=>!1):typeof e[n]!="function"&&(e[n]=()=>!0)}return e};exports.normalizeLogger=o;
@@ -0,0 +1 @@
1
+ export * from './databases/memory_db'
@@ -0,0 +1 @@
1
+ export * from './databases/mock_db'
@@ -0,0 +1 @@
1
+ export * from './databases/mongodb_db'
@@ -0,0 +1 @@
1
+ export * from './databases/mssql_db'
@@ -0,0 +1 @@
1
+ export * from './databases/mysql_db'
@@ -0,0 +1 @@
1
+ export * from './databases/postgres_db'
@@ -0,0 +1 @@
1
+ export * from './databases/postgrespool_db'
@@ -0,0 +1 @@
1
+ export * from './databases/redis_db'
@@ -0,0 +1 @@
1
+ export * from './databases/rethink_db'
@@ -0,0 +1 @@
1
+ export * from './databases/sqlite_db'
package/package.json CHANGED
@@ -41,23 +41,22 @@
41
41
  "sqlite3": "^5.1.6"
42
42
  },
43
43
  "devDependencies": {
44
+ "vite": "^4.4.9",
45
+ "vite-plugin-dts": "^3.5.3",
46
+ "@rollup/plugin-commonjs": "^25.0.4",
44
47
  "@types/async": "^3.2.20",
45
- "@types/mocha": "^10.0.1",
46
48
  "@types/mssql": "^8.1.2",
47
49
  "@types/mysql": "^2.15.21",
48
- "@types/node": "^20.4.9",
50
+ "@types/node": "^20.5.7",
49
51
  "@types/pg": "^8.10.2",
50
52
  "@types/rethinkdb": "^2.3.17",
51
53
  "cli-table": "^0.3.11",
52
54
  "eslint": "^8.48.0",
53
55
  "eslint-config-etherpad": "^3.0.22",
54
- "mocha": "^10.2.0",
55
- "randexp": "^0.5.3",
56
+ "randexp-ts": "^1.0.5",
57
+ "vitest": "^0.34.3",
56
58
  "typescript": "^4.9.5",
57
59
  "wtfnode": "^0.9.1",
58
- "rollup": "^3.28.1",
59
- "rollup-plugin-typescript2": "^0.35.0",
60
- "@rollup/plugin-node-resolve": "^15.2.1",
61
60
  "glob": "^10.3.3"
62
61
  },
63
62
  "repository": {
@@ -65,23 +64,22 @@
65
64
  "url": "https://github.com/ether/ueberDB.git"
66
65
  },
67
66
  "main": "./dist/index",
68
- "version": "4.1.22",
67
+ "version": "4.1.25",
69
68
  "bugs": {
70
69
  "url": "https://github.com/ether/ueberDB/issues"
71
70
  },
72
71
  "files": [
73
72
  "dist/databases",
74
73
  "dist/index.js",
74
+ "dist/*.d.ts",
75
75
  "dist/lib"
76
76
  ],
77
77
  "homepage": "https://github.com/ether/ueberDB",
78
78
  "scripts": {
79
79
  "lint": "eslint .",
80
80
  "lint:fix": "eslint --fix .",
81
- "test": "mocha ./dist/test/test*.js",
82
- "test:watch": "mocha ./dist/test/test*.js --watch",
83
- "test-debug": "npx rollup -c rollup.config.cjs && mocha --inspect-brk ./dist/test/test*.js",
84
- "build": "npx rollup -c rollup.config.cjs"
81
+ "build": "vite build",
82
+ "test": "vitest"
85
83
  },
86
84
  "_npmUser": {
87
85
  "name": "johnyma22",
@@ -1,235 +0,0 @@
1
- 'use strict';
2
-
3
- var AbstractDatabase = require('../lib/AbstractDatabase.js');
4
- var cassandraDriver = require('cassandra-driver');
5
-
6
- /**
7
- * Licensed under the Apache License, Version 2.0 (the "License");
8
- * you may not use this file except in compliance with the License.
9
- * You may obtain a copy of the License at
10
- *
11
- * http://www.apache.org/licenses/LICENSE-2.0
12
- *
13
- * Unless required by applicable law or agreed to in writing, software
14
- * distributed under the License is distributed on an "AS-IS" BASIS,
15
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
- * See the License for the specific language governing permissions and
17
- * limitations under the License.
18
- */
19
- const Database = class Cassandra_db extends AbstractDatabase {
20
- client;
21
- pool;
22
- /**
23
- * @param {Object} settings The required settings object to initiate the Cassandra database
24
- * @param {String[]} settings.clientOptions See
25
- * http://www.datastax.com/drivers/nodejs/2.0/global.html#ClientOptions for a full set of
26
- * options that can be used
27
- * @param {String} settings.columnFamily The column family that should be used to store data. The
28
- * column family will be created if it doesn't exist
29
- * @param {Function} [settings.logger] Function that will be used to pass on log events emitted by
30
- * the Cassandra driver. See https://github.com/datastax/nodejs-driver#logging for more
31
- * information
32
- */
33
- constructor(settings) {
34
- super();
35
- if (!settings.clientOptions) {
36
- throw new Error('The Cassandra client options should be defined');
37
- }
38
- if (!settings.columnFamily) {
39
- throw new Error('The Cassandra column family should be defined');
40
- }
41
- this.settings = { database: settings.database };
42
- this.settings.clientOptions = settings.clientOptions;
43
- this.settings.columnFamily = settings.columnFamily;
44
- this.settings.logger = settings.logger;
45
- }
46
- /**
47
- * Initializes the Cassandra client, connects to Cassandra and creates the CF if it didn't exist
48
- * already
49
- *
50
- * @param {Function} callback Standard callback method.
51
- * @param {Error} callback.err An error object (if any.)
52
- */
53
- init(callback) {
54
- // Create a client
55
- this.client = new cassandraDriver.Client(this.settings.clientOptions);
56
- // Pass on log messages if a logger has been configured
57
- if (this.settings.logger) {
58
- this.client.on('log', this.settings.logger);
59
- }
60
- // Check whether our column family already exists and create it if necessary
61
- this.client.execute('SELECT columnfamily_name FROM system.schema_columnfamilies WHERE keyspace_name = ?', [this.settings.clientOptions.keyspace], (err, result) => {
62
- if (err) {
63
- return callback(err);
64
- }
65
- let isDefined = false;
66
- const length = result.rows.length;
67
- for (let i = 0; i < length; i++) {
68
- if (result.rows[i].columnfamily_name === this.settings.columnFamily) {
69
- isDefined = true;
70
- break;
71
- }
72
- }
73
- if (isDefined) {
74
- return callback(null);
75
- }
76
- else {
77
- const cql = `CREATE COLUMNFAMILY "${this.settings.columnFamily}" ` +
78
- '(key text PRIMARY KEY, data text)';
79
- this.client && this.client.execute(cql, callback);
80
- }
81
- });
82
- }
83
- /**
84
- * Gets a value from Cassandra
85
- *
86
- * @param {String} key The key for which the value should be retrieved
87
- * @param {Function} callback Standard callback method
88
- * @param {Error} callback.err An error object, if any
89
- * @param {String} callback.value The value for the given key (if any)
90
- */
91
- get(key, callback) {
92
- const cql = `SELECT data FROM "${this.settings.columnFamily}" WHERE key = ?`;
93
- this.client && this.client.execute(cql, [key], (err, result) => {
94
- if (err) {
95
- return callback(err);
96
- }
97
- if (!result.rows || result.rows.length === 0) {
98
- return callback(null, null);
99
- }
100
- return callback(null, result.rows[0].data);
101
- });
102
- }
103
- /**
104
- * Cassandra has no native `findKeys` method. This function implements a naive filter by
105
- * retrieving *all* the keys and filtering those. This should obviously be used with the utmost
106
- * care and is probably not something you want to run in production.
107
- *
108
- * @param {String} key The filter for keys that should match
109
- * @param {String} [notKey] The filter for keys that shouldn't match
110
- * @param {Function} callback Standard callback method
111
- * @param {Error} callback.err An error object, if any
112
- * @param {String[]} callback.keys An array of keys that match the specified filters
113
- */
114
- findKeys(key, notKey, callback) {
115
- let cql = null;
116
- if (!notKey) {
117
- // Get all the keys
118
- cql = `SELECT key FROM "${this.settings.columnFamily}"`;
119
- this.client && this.client.execute(cql, (err, result) => {
120
- if (err) {
121
- return callback(err);
122
- }
123
- // Construct a regular expression based on the given key
124
- const regex = new RegExp(`^${key.replace(/\*/g, '.*')}$`);
125
- const keys = [];
126
- result.rows.forEach((row) => {
127
- if (regex.test(row.key)) {
128
- keys.push(row.key);
129
- }
130
- });
131
- return callback(null, keys);
132
- });
133
- }
134
- else if (notKey === '*:*:*') {
135
- // restrict key to format 'text:*'
136
- const matches = /^([^:]+):\*$/.exec(key);
137
- if (matches) {
138
- // Get the 'text' bit out of the key and get all those keys from a special column.
139
- // We can retrieve them from this column as we're duplicating them on .set/.remove
140
- cql = `SELECT * from "${this.settings.columnFamily}" WHERE key = ?`;
141
- this.client &&
142
- this.client
143
- .execute(cql, [`ueberdb:keys:${matches[1]}`], (err, result) => {
144
- if (err) {
145
- return callback(err);
146
- }
147
- if (!result.rows || result.rows.length === 0) {
148
- return callback(null, []);
149
- }
150
- const keys = result.rows.map((row) => row.data);
151
- return callback(null, keys);
152
- });
153
- }
154
- else {
155
- const msg = 'Cassandra db only supports key patterns like pad:* when notKey is set to *:*:*';
156
- return callback(new Error(msg), null);
157
- }
158
- }
159
- else {
160
- return callback(new Error('Cassandra db currently only supports *:*:* as notKey'), null);
161
- }
162
- }
163
- /**
164
- * Sets a value for a key
165
- *
166
- * @param {String} key The key to set
167
- * @param {String} value The value associated to this key
168
- * @param {Function} callback Standard callback method
169
- * @param {Error} callback.err An error object, if any
170
- */
171
- set(key, value, callback) {
172
- this.doBulk([{ type: 'set', key, value }], callback);
173
- }
174
- /**
175
- * Removes a key and it's value from the column family
176
- *
177
- * @param {String} key The key to remove
178
- * @param {Function} callback Standard callback method
179
- * @param {Error} callback.err An error object, if any
180
- */
181
- remove(key, callback) {
182
- this.doBulk([{ type: 'remove', key }], callback);
183
- }
184
- /**
185
- * Performs multiple operations in one action
186
- *
187
- * @param {Object[]} bulk The set of operations that should be performed
188
- * @param {Function} callback Standard callback method
189
- * @param {Error} callback.err An error object, if any
190
- */
191
- doBulk(bulk, callback) {
192
- const queries = [];
193
- bulk.forEach((operation) => {
194
- // We support finding keys of the form `test:*`. If anything matches, we will try and save
195
- // this
196
- const matches = /^([^:]+):([^:]+)$/.exec(operation.key);
197
- if (operation.type === 'set') {
198
- queries.push({
199
- query: `UPDATE "${this.settings.columnFamily}" SET data = ? WHERE key = ?`,
200
- params: [operation.value, operation.key],
201
- });
202
- if (matches) {
203
- queries.push({
204
- query: `UPDATE "${this.settings.columnFamily}" SET data = ? WHERE key = ?`,
205
- params: ['1', `ueberdb:keys:${matches[1]}`],
206
- });
207
- }
208
- }
209
- else if (operation.type === 'remove') {
210
- queries.push({
211
- query: `DELETE FROM "${this.settings.columnFamily}" WHERE key=?`,
212
- params: [operation.key],
213
- });
214
- if (matches) {
215
- queries.push({
216
- query: `DELETE FROM "${this.settings.columnFamily}" WHERE key = ?`,
217
- params: [`ueberdb:keys:${matches[1]}`],
218
- });
219
- }
220
- }
221
- });
222
- this.client && this.client.batch(queries, { prepare: true }, callback);
223
- }
224
- /**
225
- * Closes the Cassandra connection
226
- *
227
- * @param {Function} callback Standard callback method
228
- * @param {Error} callback.err Error object in case something goes wrong
229
- */
230
- close(callback) {
231
- this.pool.shutdown(callback);
232
- }
233
- };
234
-
235
- exports.Database = Database;