@joystick.js/db-canary 0.0.0-canary.2258 → 0.0.0-canary.2260
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -3
- package/dist/client/index.js +1 -1
- package/dist/server/lib/operations/admin.js +1 -1
- package/dist/server/lib/operations/find.js +1 -1
- package/package.json +2 -2
- package/src/client/index.js +1 -1
- package/src/server/lib/operations/admin.js +3 -2
- package/src/server/lib/operations/find.js +5 -0
package/README.md
CHANGED
|
@@ -60,11 +60,13 @@ JoystickDB is a lightweight, blazing-fast database server that provides MongoDB-
|
|
|
60
60
|
- **TypeScript Support**: Full TypeScript definitions included
|
|
61
61
|
- **Comprehensive Logging**: Detailed logs for debugging and monitoring
|
|
62
62
|
- **Easy Setup**: Get started in minutes with minimal configuration
|
|
63
|
+
- **Clean Code Architecture**: Refactored following Uncle Bob Martin's clean code principles for maintainability
|
|
64
|
+
- **Modular Design**: Small, focused functions with clear responsibilities and minimal dependencies
|
|
63
65
|
|
|
64
66
|
## Installation
|
|
65
67
|
|
|
66
68
|
```bash
|
|
67
|
-
npm install joystick
|
|
69
|
+
npm install @joystick.js/db
|
|
68
70
|
```
|
|
69
71
|
|
|
70
72
|
## Quick Start
|
|
@@ -139,7 +141,7 @@ console.log('✅ Admin user created:', result);
|
|
|
139
141
|
### 4. Connect and Use Your Database
|
|
140
142
|
|
|
141
143
|
```javascript
|
|
142
|
-
import joystickdb from 'joystick
|
|
144
|
+
import joystickdb from '@joystick.js/db';
|
|
143
145
|
|
|
144
146
|
const client = joystickdb.client({
|
|
145
147
|
port: 1983,
|
|
@@ -247,7 +249,7 @@ AWS_SECRET_ACCESS_KEY=your-secret-key
|
|
|
247
249
|
### Programmatic Server Creation
|
|
248
250
|
|
|
249
251
|
```javascript
|
|
250
|
-
import { create_server } from 'joystick
|
|
252
|
+
import { create_server } from '@joystick.js/db/server';
|
|
251
253
|
|
|
252
254
|
const server = await create_server();
|
|
253
255
|
|
package/dist/client/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import h from"net";import{EventEmitter as l}from"events";import{encode as m,decode as p}from"msgpackr";import f from"./database.js";const _=()=>({useFloat32:!1,int64AsType:"number",mapsAsObjects:!0}),g=s=>{const e=m(s,_()),t=Buffer.allocUnsafe(4);return t.writeUInt32BE(e.length,0),Buffer.concat([t,e])},q=(s,e)=>{const t=s.slice(0,e),n=s.slice(e);try{return{message:p(t,_()),buffer:n}}catch(i){throw new Error(`Invalid message format: ${i.message}`)}},y=s=>{if(s.length<4)return{expected_length:null,buffer:s};const e=s.readUInt32BE(0),t=s.slice(4);return{expected_length:e,buffer:t}},b=()=>{let s=Buffer.alloc(0),e=null;return{parse_messages:i=>{s=Buffer.concat([s,i]);const r=[];for(;s.length>0;){if(e===null){const
|
|
1
|
+
import h from"net";import{EventEmitter as l}from"events";import{encode as m,decode as p}from"msgpackr";import f from"./database.js";const _=()=>({useFloat32:!1,int64AsType:"number",mapsAsObjects:!0}),g=s=>{const e=m(s,_()),t=Buffer.allocUnsafe(4);return t.writeUInt32BE(e.length,0),Buffer.concat([t,e])},q=(s,e)=>{const t=s.slice(0,e),n=s.slice(e);try{return{message:p(t,_()),buffer:n}}catch(i){throw new Error(`Invalid message format: ${i.message}`)}},y=s=>{if(s.length<4)return{expected_length:null,buffer:s};const e=s.readUInt32BE(0),t=s.slice(4);return{expected_length:e,buffer:t}},b=()=>{let s=Buffer.alloc(0),e=null;return{parse_messages:i=>{s=Buffer.concat([s,i]);const r=[];for(;s.length>0;){if(e===null){const c=y(s);if(e=c.expected_length,s=c.buffer,e===null)break}if(s.length<e)break;const a=q(s,e);r.push(a.message),s=a.buffer,e=null}return r},reset:()=>{s=Buffer.alloc(0),e=null}}},w=(s,e)=>Math.min(e*Math.pow(2,s-1),3e4),k=(s={})=>({host:s.host||"localhost",port:s.port||1983,password:s.password||null,timeout:s.timeout||5e3,reconnect:s.reconnect!==!1,max_reconnect_attempts:s.max_reconnect_attempts||10,reconnect_delay:s.reconnect_delay||1e3,auto_connect:s.auto_connect!==!1}),x=(s,e,t)=>setTimeout(()=>{s&&!s.destroyed&&(s.destroy(),e(new Error("Connection timeout")))},t),E=(s,e,t)=>setTimeout(()=>{const n=s.get(e);n&&(s.delete(e),n.reject(new Error("Request timeout")))},t),u=(s,e)=>{for(const[t,{reject:n,timeout:i}]of s)clearTimeout(i),n(new Error(e));s.clear()},T=s=>s.ok===1||s.ok===!0,v=s=>s.ok===0||s.ok===!1,B=s=>typeof s.error=="string"?s.error:JSON.stringify(s.error)||"Operation failed";class d extends l{constructor(e={}){super();const t=k(e);this.host=t.host,this.port=t.port,this.password=t.password,this.timeout=t.timeout,this.reconnect=t.reconnect,this.max_reconnect_attempts=t.max_reconnect_attempts,this.reconnect_delay=t.reconnect_delay,this.socket=null,this.message_parser=null,this.is_connected=!1,this.is_authenticated=!1,this.is_connecting=!1,this.reconnect_attempts=0,this.reconnect_timeout=null,this.pending_requests=new Map,this.request_id_counter=0,this.request_queue=[],t.auto_connect&&this.connect()}connect(){if(this.is_connecting||this.is_connected)return;this.is_connecting=!0,this.socket=new h.Socket,this.message_parser=b();const e=x(this.socket,this.handle_connection_error.bind(this),this.timeout);this.setup_socket_handlers(e),this.socket.connect(this.port,this.host,()=>{this.handle_successful_connection(e)})}setup_socket_handlers(e){this.socket.on("data",t=>{this.handle_incoming_data(t)}),this.socket.on("error",t=>{clearTimeout(e),this.handle_connection_error(t)}),this.socket.on("close",()=>{clearTimeout(e),this.handle_disconnect()})}handle_successful_connection(e){clearTimeout(e),this.is_connected=!0,this.is_connecting=!1,this.reconnect_attempts=0,this.emit("connect"),this.password?this.authenticate():this.handle_authentication_complete()}handle_authentication_complete(){this.is_authenticated=!0,this.emit("authenticated"),this.process_request_queue()}handle_incoming_data(e){try{const t=this.message_parser.parse_messages(e);for(const n of t)this.handle_message(n)}catch(t){this.emit("error",new Error(`Message parsing failed: ${t.message}`))}}async authenticate(){if(!this.password){this.emit("error",new Error('Password required for authentication. Provide password in client options: joystickdb.client({ password: "your_password" })')),this.disconnect();return}try{if((await this.send_request("authentication",{password:this.password})).ok===1)this.handle_authentication_complete();else throw new Error("Authentication failed")}catch(e){this.emit("error",new Error(`Authentication error: ${e.message}`)),this.disconnect()}}handle_message(e){this.pending_requests.size>0?this.handle_pending_request_response(e):this.emit("response",e)}handle_pending_request_response(e){const[t,{resolve:n,reject:i,timeout:r}]=this.pending_requests.entries().next().value;if(clearTimeout(r),this.pending_requests.delete(t),T(e))n(e);else if(v(e)){const a=B(e);i(new Error(a))}else n(e)}handle_connection_error(e){this.reset_connection_state(),u(this.pending_requests,"Connection lost"),this.emit("error",e),this.should_attempt_reconnect()?this.schedule_reconnect():this.emit("disconnect")}handle_disconnect(){this.reset_connection_state(),u(this.pending_requests,"Connection closed"),this.should_attempt_reconnect()?this.schedule_reconnect():this.emit("disconnect")}reset_connection_state(){this.is_connecting=!1,this.is_connected=!1,this.is_authenticated=!1,this.socket&&(this.socket.removeAllListeners(),this.socket.destroy(),this.socket=null),this.message_parser&&this.message_parser.reset()}should_attempt_reconnect(){return this.reconnect&&this.reconnect_attempts<this.max_reconnect_attempts}schedule_reconnect(){this.reconnect_attempts++;const e=w(this.reconnect_attempts,this.reconnect_delay);this.emit("reconnecting",{attempt:this.reconnect_attempts,delay:e}),this.reconnect_timeout=setTimeout(()=>{this.connect()},e)}send_request(e,t={},n=!0){return new Promise((i,r)=>{const a=++this.request_id_counter,o={message:{op:e,data:t},resolve:i,reject:r,request_id:a};if(this.should_queue_request(e,n)){this.request_queue.push(o);return}this.send_request_now(o)})}should_queue_request(e,t){const i=!["authentication","setup","ping"].includes(e);return(!this.is_connected||i&&!this.is_authenticated)&&t}send_request_now(e){const{message:t,resolve:n,reject:i,request_id:r}=e,a=E(this.pending_requests,r,this.timeout);this.pending_requests.set(r,{resolve:n,reject:i,timeout:a});try{const c=g(t);this.socket.write(c)}catch(c){clearTimeout(a),this.pending_requests.delete(r),i(c)}}process_request_queue(){for(;this.request_queue.length>0&&this.is_connected&&this.is_authenticated;){const e=this.request_queue.shift();this.send_request_now(e)}}disconnect(){this.reconnect=!1,this.reconnect_timeout&&(clearTimeout(this.reconnect_timeout),this.reconnect_timeout=null),this.socket&&this.socket.end()}async backup_now(){return this.send_request("admin",{admin_action:"backup_now"})}async list_backups(){return this.send_request("admin",{admin_action:"list_backups"})}async restore_backup(e){return this.send_request("admin",{admin_action:"restore_backup",backup_name:e})}async get_replication_status(){return this.send_request("admin",{admin_action:"get_replication_status"})}async add_secondary(e){return this.send_request("admin",{admin_action:"add_secondary",...e})}async remove_secondary(e){return this.send_request("admin",{admin_action:"remove_secondary",secondary_id:e})}async sync_secondaries(){return this.send_request("admin",{admin_action:"sync_secondaries"})}async get_secondary_health(){return this.send_request("admin",{admin_action:"get_secondary_health"})}async get_forwarder_status(){return this.send_request("admin",{admin_action:"get_forwarder_status"})}async ping(){return this.send_request("ping",{},!1)}async reload(){return this.send_request("reload")}async get_auto_index_stats(){return this.send_request("admin",{admin_action:"get_auto_index_stats"})}async setup(){const e=await this.send_request("setup",{},!1);return e.data&&e.data.instructions&&console.log(e.data.instructions),e}async delete_many(e,t={},n={}){return this.send_request("delete_many",{collection:e,filter:t,options:n})}db(e){return new f(this,e)}async list_databases(){return this.send_request("admin",{admin_action:"list_databases"})}async get_stats(){return this.send_request("admin",{admin_action:"stats"})}}class j{constructor(e,t,n){this.client=e,this.database_name=t,this.collection_name=n}async insert_one(e,t={}){return this.client.send_request("insert_one",{database:this.database_name,collection:this.collection_name,document:e,options:t})}async find_one(e={},t={}){return(await this.client.send_request("find_one",{database:this.database_name,collection:this.collection_name,filter:e,options:t})).document}async find(e={},t={}){return(await this.client.send_request("find",{database:this.database_name,collection:this.collection_name,filter:e,options:t})).documents||[]}async update_one(e,t,n={}){return this.client.send_request("update_one",{database:this.database_name,collection:this.collection_name,filter:e,update:t,options:n})}async delete_one(e,t={}){return this.client.send_request("delete_one",{database:this.database_name,collection:this.collection_name,filter:e,options:t})}async delete_many(e={},t={}){return this.client.send_request("delete_many",{database:this.database_name,collection:this.collection_name,filter:e,options:t})}async bulk_write(e,t={}){return this.client.send_request("bulk_write",{database:this.database_name,collection:this.collection_name,operations:e,options:t})}async create_index(e,t={}){return this.client.send_request("create_index",{database:this.database_name,collection:this.collection_name,field:e,options:t})}async upsert_index(e,t={}){return this.client.send_request("create_index",{database:this.database_name,collection:this.collection_name,field:e,options:{...t,upsert:!0}})}async drop_index(e){return this.client.send_request("drop_index",{database:this.database_name,collection:this.collection_name,field:e})}async get_indexes(){return this.client.send_request("get_indexes",{database:this.database_name,collection:this.collection_name})}}d.Collection=j;const C={client:s=>new d(s)};var P=C;export{P as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{get_database as y}from"../query_engine.js";import{get_settings as $}from"../load_settings.js";import{get_write_queue as v}from"../write_queue.js";import{get_auth_stats as q}from"../auth_manager.js";import{get_query_statistics as E,get_auto_index_statistics as D,force_index_evaluation as O,remove_automatic_indexes as P}from"../auto_index_manager.js";import{create_index as N,drop_index as R,get_indexes as j}from"../index_manager.js";import{test_s3_connection as U,create_backup as W,list_backups as A,restore_backup as J,cleanup_old_backups as T}from"../backup_manager.js";import{get_replication_manager as b}from"../replication_manager.js";import{get_write_forwarder as B}from"../write_forwarder.js";import L from"../logger.js";import{performance_monitor as w}from"../performance_monitor.js";const{create_context_logger:h}=L("admin"),I=()=>{try{return $()}catch{return{port:1983}}},G=t=>{try{const e=t.getStats?t.getStats():{};return{pageSize:e.pageSize||0,treeDepth:e.treeDepth||0,treeBranchPages:e.treeBranchPages||0,treeLeafPages:e.treeLeafPages||0,entryCount:e.entryCount||0,mapSize:e.mapSize||0,lastPageNumber:e.lastPageNumber||0}}catch{return{error:"Could not retrieve database stats"}}},H=(t,e)=>{const o={};let r=0;try{for(const{key:n}of t.getRange())if(typeof n=="string"&&n.includes(":")&&!n.startsWith("_")){const a=n.split(":")[0];o[a]=(o[a]||0)+1,r++}}catch(n){e.warn("Could not iterate database range for stats",{error:n.message})}return{collections:o,total_documents:r}},z=()=>{const t=process.memoryUsage();return{rss:Math.round(t.rss/1024/1024),heapTotal:Math.round(t.heapTotal/1024/1024),heapUsed:Math.round(t.heapUsed/1024/1024),external:Math.round(t.external/1024/1024)}},K=t=>t.mapSize>0?Math.round(t.lastPageNumber*t.pageSize/t.mapSize*100):0,Q=t=>({uptime:Math.floor(process.uptime()),uptime_formatted:M(process.uptime()),memory_usage:t,memory_usage_raw:process.memoryUsage(),node_version:process.version,platform:process.platform,arch:process.arch,pid:process.pid,cpu_usage:process.cpuUsage()}),V=(t,e,o,r)=>({total_documents:t,total_collections:Object.keys(e).length,collections:e,stats:o,map_size_usage_percent:r,disk_usage:{map_size_mb:Math.round((o.mapSize||0)/1024/1024),used_space_mb:Math.round((o.lastPageNumber||0)*(o.pageSize||0)/1024/1024)}}),X=()=>{const t=h();try{const e=y(),o=I(),r=G(e),{collections:n,total_documents:a}=H(e,t),s=z(),i=K(r);return{server:Q(s),database:V(a,n,r,i),performance:{ops_per_second:F(),avg_response_time_ms:C()}}}catch(e){throw t.error("Failed to get enhanced stats",{error:e.message}),e}},M=t=>{const e=Math.floor(t/86400),o=Math.floor(t%86400/3600),r=Math.floor(t%3600/60),n=Math.floor(t%60);return e>0?`${e}d ${o}h ${r}m ${n}s`:o>0?`${o}h ${r}m ${n}s`:r>0?`${r}m ${n}s`:`${n}s`};let k=0,S=0,Y=Date.now();const F=()=>{const t=(Date.now()-Y)/1e3;return t>0?Math.round(k/t):0},C=()=>k>0?Math.round(S/k):0,Z=t=>{k++,S+=t},ee=t=>({name:t,document_count:0,indexes:[],estimated_size_bytes:0}),te=(t,e,o)=>{const r={};let n=0;try{for(const{key:a}of t.getRange())if(typeof a=="string"&&a.includes(":")&&!a.startsWith("_")){const s=a.split(":");if(s.length>=3){const i=s[0],c=s[1];i===e&&(r[c]||(r[c]=ee(c)),r[c].document_count++,n++)}}}catch(a){o.warn("Could not iterate database range for collections",{error:a.message})}return{collections_map:r,total_documents:n}},re=(t,e,o)=>{const r=["admin_test","test_collection","queue_test","users","products","orders","sessions","logs","analytics","settings","another_collection","list_test","pagination_test","get_test","query_test","admin_insert_test","admin_update_test","admin_delete_test"];let n=0;for(const a of r)try{const s=`${e}:${a}:`,i=t.getRange({start:s,end:s+"\xFF"});let c=0;for(const _ of i)c++,n++;c>0&&(o[a]={name:a,document_count:c,indexes:[],estimated_size_bytes:c*100})}catch{continue}return n},oe=(t,e,o,r)=>{try{const n=`index:${e}:`,a=t.getRange({start:n,end:n+"\xFF"});for(const{key:s,value:i}of a)if(typeof s=="string"&&s.startsWith(n)){const c=s.substring(n.length),_=c.split(":")[0],u=c.split(":")[1];o[_]&&u&&(o[_].indexes.includes(u)||o[_].indexes.push(u))}}catch(n){r.warn("Could not iterate index range",{error:n.message})}},se=(t="default")=>{const e=h();try{const o=y();let{collections_map:r,total_documents:n}=te(o,t,e);Object.keys(r).length===0&&(n+=re(o,t,r)),oe(o,t,r,e);const a=Object.values(r);return{collections:a,total_collections:a.length,total_documents:n}}catch(o){throw e.error("Failed to list collections",{error:o.message}),o}},ne=(t,e={})=>{const o=h();if(!t)throw new Error("Collection name is required");try{const r=y(),{limit:n=50,skip:a=0,sort_field:s,sort_order:i="asc",database:c="default"}=e,_=[],u=`${c}:${t}:`;let m=0,g=0;for(const{key:d,value:f}of r.getRange({start:u,end:u+"\xFF"}))if(typeof d=="string"&&d.startsWith(u)){if(g<a){g++;continue}if(m>=n)break;try{const l=JSON.parse(f),p=d.substring(u.length);_.push({_id:p,...l}),m++}catch(l){o.warn("Could not parse document",{collection:t,key:d,error:l.message})}}return s&&_.length>0&&_.sort((d,f)=>{const l=d[s],p=f[s];return i==="desc"?p>l?1:p<l?-1:0:l>p?1:l<p?-1:0}),{collection:t,documents:_,count:_.length,skip:a,limit:n,has_more:m===n}}catch(r){throw o.error("Failed to list documents",{collection:t,error:r.message}),r}},ae=(t,e,o="default")=>{const r=h();if(!t||!e)throw new Error("Collection name and document ID are required");try{const n=y(),a=`${o}:${t}:${e}`,s=n.get(a);if(!s)return{found:!1,collection:t,document_id:e};const i=JSON.parse(s);return{found:!0,collection:t,document_id:e,document:{_id:e,...i}}}catch(n){throw r.error("Failed to get document",{collection:t,document_id:e,error:n.message}),n}},ce=(t,e,o,r)=>{switch(t){case"$gt":return o>e;case"$gte":return o>=e;case"$lt":return o<e;case"$lte":return o<=e;case"$ne":return o!==e;case"$in":return Array.isArray(e)&&e.includes(o);case"$regex":const n=r.$options||"";return new RegExp(e,n).test(String(o));default:return o===r}},ie=(t,e)=>Object.keys(e).every(o=>{const r=e[o],n=t[o];return typeof r=="object"&&r!==null?Object.keys(r).every(a=>{const s=r[a];return ce(a,s,n,r)}):n===r}),_e=(t,e,o,r,n)=>{try{const a=JSON.parse(e),i={_id:t.substring(o.length),...a};return ie(i,r)?i:null}catch(a){return n.warn("Could not parse document during query",{key:t,error:a.message}),null}},ue=(t,e={},o={})=>{const r=h();if(!t)throw new Error("Collection name is required");try{const n=y(),{limit:a=100,skip:s=0,database:i="default"}=o,c=[],_=`${i}:${t}:`;let u=0,m=0,g=0;for(const{key:d,value:f}of n.getRange({start:_,end:_+"\xFF"}))if(typeof d=="string"&&d.startsWith(_)){g++;const l=_e(d,f,_,e,r);if(l){if(m<s){m++;continue}if(u>=a)break;c.push(l),u++}}return{collection:t,filter:e,documents:c,count:c.length,total_examined:g,skip:s,limit:a,has_more:u===a}}catch(n){throw r.error("Failed to query documents",{collection:t,filter:e,error:n.message}),n}},le=async(t,e,o,r={})=>await(await import("./insert_one.js")).default(t,e,o,r),de=async(t,e,o,r,n={})=>await(await import("./update_one.js")).default(t,e,o,r,n),me=async(t,e,o,r={})=>await(await import("./delete_one.js")).default(t,e,o,r);var qe=async(t,e={},o,r)=>{const n=h(),a=Date.now();try{let s;switch(t){case"stats":const c=z();s={server:{uptime:Math.floor(process.uptime()),uptime_formatted:M(process.uptime()),node_version:process.version,platform:process.platform,arch:process.arch,pid:process.pid},memory:{heap_used_mb:c.heapUsed,heap_total_mb:c.heapTotal,rss:c.rss,external:c.external},database:{...w.get_database_stats(),map_size_mb:Math.round((w.get_database_stats()?.map_size||0)/1024/1024),used_space_mb:Math.round((w.get_database_stats()?.used_space||0)/1024/1024),usage_percent:w.get_database_stats()?.usage_percent||0},performance:{ops_per_second:F(),avg_response_time_ms:C()},system:w.get_system_stats(),connections:o?.get_stats()||{active:r?.size||0,total:r?.size||0},write_queue:v()?.get_stats()||{},authentication:{authenticated_clients:r?.size||0,...q()},settings:(()=>{try{return{port:$().port||1983}}catch{return{port:1983}}})()};break;case"list_collections":s=se();break;case"list_documents":s=ne(e.collection,{limit:e.limit,skip:e.skip,sort_field:e.sort_field,sort_order:e.sort_order});break;case"get_document":s=ae(e.collection,e.document_id);break;case"query_documents":s=ue(e.collection,e.filter,{limit:e.limit,skip:e.skip});break;case"insert_document":s=await le(e.database||"default",e.collection,e.document,e.options);break;case"update_document":const _=e.document_id?{_id:e.document_id}:e.filter;s=await de(e.database||"default",e.collection,_,e.update,e.options);break;case"delete_document":const u=e.document_id?{_id:e.document_id}:e.filter;s=await me(e.database||"default",e.collection,u,e.options);break;case"test_s3_connection":s=await U();break;case"backup_now":s=await W();break;case"list_backups":s=await A();break;case"restore_backup":if(!e.backup_filename)throw new Error("backup_filename is required for restore operation");s=await J(e.backup_filename);break;case"cleanup_backups":s=await T();break;case"get_auto_index_stats":s=D();break;case"get_query_stats":s=E(e.collection);break;case"evaluate_auto_indexes":s=await O(e.collection);break;case"remove_auto_indexes":if(!e.collection)throw new Error("collection is required for remove_auto_indexes operation");s=await P(e.collection,e.field_names);break;case"create_index":if(!e.collection||!e.field)throw new Error("collection and field are required for create_index operation");s=await N(e.database||"default",e.collection,e.field,e.options);break;case"drop_index":if(!e.collection||!e.field)throw new Error("collection and field are required for drop_index operation");s=await R(e.database||"default",e.collection,e.field);break;case"get_indexes":if(!e.collection)throw new Error("collection is required for get_indexes operation");s={indexes:j(e.database||"default",e.collection)};break;case"get_replication_status":s=b().get_replication_status();break;case"add_secondary":if(!e.id||!e.ip||!e.port||!e.private_key)throw new Error("id, ip, port, and private_key are required for add_secondary operation");s=await b().add_secondary({id:e.id,ip:e.ip,port:e.port,private_key:e.private_key,enabled:!0});break;case"remove_secondary":if(!e.secondary_id)throw new Error("secondary_id is required for remove_secondary operation");s=b().remove_secondary(e.secondary_id);break;case"sync_secondaries":s=await b().sync_secondaries();break;case"get_secondary_health":s=b().get_secondary_health();break;case"get_forwarder_status":s=B().get_forwarder_status();break;default:s={...X(),connections:o?.get_stats()||{},write_queue:v()?.get_stats()||{},authentication:{authenticated_clients:r?.size||0,...q()},settings:(()=>{try{return{port:$().port||1983}}catch{return{port:1983}}})()}}const i=Date.now()-a;return Z(i),n.info("Admin operation completed",{admin_action:t||"default",duration_ms:i,status:"success"}),s}catch(s){const i=Date.now()-a;throw n.error("Admin operation failed",{admin_action:t||"default",duration_ms:i,status:"error",error:s.message}),s}};export{qe as default,Z as track_operation};
|
|
1
|
+
import{get_database as y}from"../query_engine.js";import{get_settings as $}from"../load_settings.js";import{get_write_queue as v}from"../write_queue.js";import{get_auth_stats as q}from"../auth_manager.js";import{get_query_statistics as E,get_auto_index_statistics as D,force_index_evaluation as O,remove_automatic_indexes as P}from"../auto_index_manager.js";import{create_index as N,drop_index as R,get_indexes as U}from"../index_manager.js";import{test_s3_connection as j,create_backup as T,list_backups as W,restore_backup as A,cleanup_old_backups as J}from"../backup_manager.js";import{get_replication_manager as b}from"../replication_manager.js";import{get_write_forwarder as B}from"../write_forwarder.js";import L from"../logger.js";import{performance_monitor as w}from"../performance_monitor.js";const{create_context_logger:h}=L("admin"),I=()=>{try{return $()}catch{return{port:1983}}},G=t=>{try{const e=t.getStats?t.getStats():{};return{pageSize:e.pageSize||0,treeDepth:e.treeDepth||0,treeBranchPages:e.treeBranchPages||0,treeLeafPages:e.treeLeafPages||0,entryCount:e.entryCount||0,mapSize:e.mapSize||0,lastPageNumber:e.lastPageNumber||0}}catch{return{error:"Could not retrieve database stats"}}},H=(t,e)=>{const o={};let r=0;try{for(const{key:n}of t.getRange())if(typeof n=="string"&&n.includes(":")&&!n.startsWith("_")){const a=n.split(":")[0];o[a]=(o[a]||0)+1,r++}}catch(n){e.warn("Could not iterate database range for stats",{error:n.message})}return{collections:o,total_documents:r}},z=()=>{const t=process.memoryUsage();return{rss:Math.round(t.rss/1024/1024),heapTotal:Math.round(t.heapTotal/1024/1024),heapUsed:Math.round(t.heapUsed/1024/1024),external:Math.round(t.external/1024/1024)}},K=t=>t.mapSize>0?Math.round(t.lastPageNumber*t.pageSize/t.mapSize*100):0,Q=t=>({uptime:Math.floor(process.uptime()),uptime_formatted:M(process.uptime()),memory_usage:t,memory_usage_raw:process.memoryUsage(),node_version:process.version,platform:process.platform,arch:process.arch,pid:process.pid,cpu_usage:process.cpuUsage()}),V=(t,e,o,r)=>({total_documents:t,total_collections:Object.keys(e).length,collections:e,stats:o,map_size_usage_percent:r,disk_usage:{map_size_mb:Math.round((o.mapSize||0)/1024/1024),used_space_mb:Math.round((o.lastPageNumber||0)*(o.pageSize||0)/1024/1024)}}),X=()=>{const t=h();try{const e=y(),o=I(),r=G(e),{collections:n,total_documents:a}=H(e,t),s=z(),i=K(r);return{server:Q(s),database:V(a,n,r,i),performance:{ops_per_second:F(),avg_response_time_ms:C()}}}catch(e){throw t.error("Failed to get enhanced stats",{error:e.message}),e}},M=t=>{const e=Math.floor(t/86400),o=Math.floor(t%86400/3600),r=Math.floor(t%3600/60),n=Math.floor(t%60);return e>0?`${e}d ${o}h ${r}m ${n}s`:o>0?`${o}h ${r}m ${n}s`:r>0?`${r}m ${n}s`:`${n}s`};let k=0,S=0,Y=Date.now();const F=()=>{const t=(Date.now()-Y)/1e3;return t>0?Math.round(k/t):0},C=()=>k>0?Math.round(S/k):0,Z=t=>{k++,S+=t},ee=t=>({name:t,document_count:0,indexes:[],estimated_size_bytes:0}),te=(t,e,o)=>{const r={};let n=0;try{for(const{key:a}of t.getRange())if(typeof a=="string"&&a.includes(":")&&!a.startsWith("_")){const s=a.split(":");if(s.length>=3){const i=s[0],c=s[1];i===e&&(r[c]||(r[c]=ee(c)),r[c].document_count++,n++)}}}catch(a){o.warn("Could not iterate database range for collections",{error:a.message})}return{collections_map:r,total_documents:n}},re=(t,e,o)=>{const r=["admin_test","test_collection","queue_test","users","products","orders","sessions","logs","analytics","settings","another_collection","list_test","pagination_test","get_test","query_test","admin_insert_test","admin_update_test","admin_delete_test"];let n=0;for(const a of r)try{const s=`${e}:${a}:`,i=t.getRange({start:s,end:s+"\xFF"});let c=0;for(const _ of i)c++,n++;c>0&&(o[a]={name:a,document_count:c,indexes:[],estimated_size_bytes:c*100})}catch{continue}return n},oe=(t,e,o,r)=>{try{const n=`index:${e}:`,a=t.getRange({start:n,end:n+"\xFF"});for(const{key:s,value:i}of a)if(typeof s=="string"&&s.startsWith(n)){const c=s.substring(n.length),_=c.split(":")[0],u=c.split(":")[1];o[_]&&u&&(o[_].indexes.includes(u)||o[_].indexes.push(u))}}catch(n){r.warn("Could not iterate index range",{error:n.message})}},se=(t="default")=>{const e=h();try{const o=y();let{collections_map:r,total_documents:n}=te(o,t,e);Object.keys(r).length===0&&(n+=re(o,t,r)),oe(o,t,r,e);const a=Object.values(r);return{collections:a,total_collections:a.length,total_documents:n}}catch(o){throw e.error("Failed to list collections",{error:o.message}),o}},ne=(t,e={})=>{const o=h();if(!t)throw new Error("Collection name is required");try{const r=y(),{limit:n=50,skip:a=0,sort_field:s,sort_order:i="asc",database:c="default"}=e,_=[],u=`${c}:${t}:`;let m=0,g=0;for(const{key:d,value:f}of r.getRange({start:u,end:u+"\xFF"}))if(typeof d=="string"&&d.startsWith(u)){if(g<a){g++;continue}if(m>=n)break;try{const l=JSON.parse(f),p=d.substring(u.length);_.push({_id:p,...l}),m++}catch(l){o.warn("Could not parse document",{collection:t,key:d,error:l.message})}}return s&&_.length>0&&_.sort((d,f)=>{const l=d[s],p=f[s];return i==="desc"?p>l?1:p<l?-1:0:l>p?1:l<p?-1:0}),{collection:t,documents:_,count:_.length,skip:a,limit:n,has_more:m===n}}catch(r){throw o.error("Failed to list documents",{collection:t,error:r.message}),r}},ae=(t,e,o="default")=>{const r=h();if(!t||!e)throw new Error("Collection name and document ID are required");try{const n=y(),a=`${o}:${t}:${e}`,s=n.get(a);if(!s)return{found:!1,collection:t,document_id:e};const i=JSON.parse(s);return{found:!0,collection:t,document_id:e,document:{_id:e,...i}}}catch(n){throw r.error("Failed to get document",{collection:t,document_id:e,error:n.message}),n}},ce=(t,e,o,r)=>{switch(t){case"$gt":return o>e;case"$gte":return o>=e;case"$lt":return o<e;case"$lte":return o<=e;case"$ne":return o!==e;case"$in":return Array.isArray(e)&&e.includes(o);case"$regex":const n=r.$options||"";return new RegExp(e,n).test(String(o));default:return o===r}},ie=(t,e)=>Object.keys(e).every(o=>{const r=e[o],n=t[o];return typeof r=="object"&&r!==null?Object.keys(r).every(a=>{const s=r[a];return ce(a,s,n,r)}):n===r}),_e=(t,e,o,r,n)=>{try{const a=JSON.parse(e),i={_id:t.substring(o.length),...a};return ie(i,r)?i:null}catch(a){return n.warn("Could not parse document during query",{key:t,error:a.message}),null}},ue=(t,e={},o={})=>{const r=h();if(!t)throw new Error("Collection name is required");try{const n=y(),{limit:a=100,skip:s=0,database:i="default"}=o,c=[],_=`${i}:${t}:`;let u=0,m=0,g=0;for(const{key:d,value:f}of n.getRange({start:_,end:_+"\xFF"}))if(typeof d=="string"&&d.startsWith(_)){g++;const l=_e(d,f,_,e,r);if(l){if(m<s){m++;continue}if(u>=a)break;c.push(l),u++}}return{collection:t,filter:e,documents:c,count:c.length,total_examined:g,skip:s,limit:a,has_more:u===a}}catch(n){throw r.error("Failed to query documents",{collection:t,filter:e,error:n.message}),n}},le=async(t,e,o,r={})=>await(await import("./insert_one.js")).default(t,e,o,r),de=async(t,e,o,r,n={})=>await(await import("./update_one.js")).default(t,e,o,r,n),me=async(t,e,o,r={})=>await(await import("./delete_one.js")).default(t,e,o,r);var qe=async(t,e={},o,r)=>{const n=h(),a=Date.now();try{let s;switch(t){case"stats":const c=z();s={server:{uptime:Math.floor(process.uptime()),uptime_formatted:M(process.uptime()),node_version:process.version,platform:process.platform,arch:process.arch,pid:process.pid},memory:{heap_used_mb:c.heapUsed,heap_total_mb:c.heapTotal,rss_mb:c.rss,external_mb:c.external,heap_used_percent:c.heapTotal>0?Math.round(c.heapUsed/c.heapTotal*100):0},database:{...w.get_database_stats(),map_size_mb:Math.round((w.get_database_stats()?.map_size||0)/1024/1024),used_space_mb:Math.round((w.get_database_stats()?.used_space||0)/1024/1024),usage_percent:w.get_database_stats()?.usage_percent||0},performance:{ops_per_second:F(),avg_response_time_ms:C()},system:w.get_system_stats(),connections:o?.get_stats()||{active:r?.size||0,total:r?.size||0},write_queue:v()?.get_stats()||{},authentication:{authenticated_clients:r?.size||0,...q()},settings:(()=>{try{return{port:$().port||1983}}catch{return{port:1983}}})()};break;case"list_collections":s=se();break;case"list_documents":s=ne(e.collection,{limit:e.limit,skip:e.skip,sort_field:e.sort_field,sort_order:e.sort_order});break;case"get_document":s=ae(e.collection,e.document_id);break;case"query_documents":s=ue(e.collection,e.filter,{limit:e.limit,skip:e.skip});break;case"insert_document":s=await le(e.database||"default",e.collection,e.document,e.options);break;case"update_document":const _=e.document_id?{_id:e.document_id}:e.filter;s=await de(e.database||"default",e.collection,_,e.update,e.options);break;case"delete_document":const u=e.document_id?{_id:e.document_id}:e.filter;s=await me(e.database||"default",e.collection,u,e.options);break;case"test_s3_connection":s=await j();break;case"backup_now":s=await T();break;case"list_backups":s=await W();break;case"restore_backup":if(!e.backup_filename)throw new Error("backup_filename is required for restore operation");s=await A(e.backup_filename);break;case"cleanup_backups":s=await J();break;case"get_auto_index_stats":s=D();break;case"get_query_stats":s=E(e.collection);break;case"evaluate_auto_indexes":s=await O(e.collection);break;case"remove_auto_indexes":if(!e.collection)throw new Error("collection is required for remove_auto_indexes operation");s=await P(e.collection,e.field_names);break;case"create_index":if(!e.collection||!e.field)throw new Error("collection and field are required for create_index operation");s=await N(e.database||"default",e.collection,e.field,e.options);break;case"drop_index":if(!e.collection||!e.field)throw new Error("collection and field are required for drop_index operation");s=await R(e.database||"default",e.collection,e.field);break;case"get_indexes":if(!e.collection)throw new Error("collection is required for get_indexes operation");s={indexes:U(e.database||"default",e.collection)};break;case"get_replication_status":s=b().get_replication_status();break;case"add_secondary":if(!e.id||!e.ip||!e.port||!e.private_key)throw new Error("id, ip, port, and private_key are required for add_secondary operation");s=await b().add_secondary({id:e.id,ip:e.ip,port:e.port,private_key:e.private_key,enabled:!0});break;case"remove_secondary":if(!e.secondary_id)throw new Error("secondary_id is required for remove_secondary operation");s=b().remove_secondary(e.secondary_id);break;case"sync_secondaries":s=await b().sync_secondaries();break;case"get_secondary_health":s=b().get_secondary_health();break;case"get_forwarder_status":s=B().get_forwarder_status();break;default:s={...X(),connections:o?.get_stats()||{},write_queue:v()?.get_stats()||{},authentication:{authenticated_clients:r?.size||0,...q()},settings:(()=>{try{return{port:$().port||1983}}catch{return{port:1983}}})()}}const i=Date.now()-a;return Z(i),n.info("Admin operation completed",{admin_action:t||"default",duration_ms:i,status:"success"}),s}catch(s){const i=Date.now()-a;throw n.error("Admin operation failed",{admin_action:t||"default",duration_ms:i,status:"error",error:s.message}),s}};export{qe as default,Z as track_operation};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{get_database as O,build_collection_key as F}from"../query_engine.js";import{can_use_index as E,find_documents_by_index as x}from"../index_manager.js";import{record_query as D,record_index_usage as J}from"../auto_index_manager.js";import N from"../logger.js";const{create_context_logger:R}=N("find"),m=r=>r.split("."),b=r=>r==null,S=(r,e)=>{const t=[];for(let n=0;n<r.length;n++){const s=r[n];if(typeof s=="object"&&s!==null){const o=j(s,e);o!==void 0&&(Array.isArray(o)?t.push(...o):t.push(o))}}return t.length>0?t:void 0},j=(r,e)=>{const t=m(e);let n=r;for(let s=0;s<t.length;s++){const o=t[s];if(b(n))return;if(n=n[o],Array.isArray(n)&&s<t.length-1){const i=t.slice(s+1).join(".");return S(n,i)}}return n},C=(r,e)=>r.hasOwnProperty(e),P=(r,e)=>{const t=m(e);let n=r;for(let s=0;s<t.length;s++){if(b(n)||typeof n!="object")return!1;if(s===t.length-1)return C(n,t[s]);n=n[t[s]]}return!1},k=(r,e)=>r.includes(e),p=(r,e,t)=>{for(let n=0;n<r.length;n++)if(t(r[n],e))return!0;return!1},$=(r,e)=>Array.isArray(r)?k(r,e):r===e,U=(r,e)=>Array.isArray(r)?!k(r,e):r!==e,z=(r,e)=>Array.isArray(r)?p(r,e,(t,n)=>t>n):r>e,B=(r,e)=>Array.isArray(r)?p(r,e,(t,n)=>t>=n):r>=e,G=(r,e)=>Array.isArray(r)?p(r,e,(t,n)=>t<n):r<e,H=(r,e)=>Array.isArray(r)?p(r,e,(t,n)=>t<=n):r<=e,I=(r,e)=>Array.isArray(e)?Array.isArray(r)?p(r,e,(t,n)=>n.includes(t)):e.includes(r):!1,K=(r,e)=>{if(!Array.isArray(e))return!1;if(Array.isArray(r)){for(let t=0;t<r.length;t++)if(e.includes(r[t]))return!1;return!0}return!e.includes(r)},L=(r,e,t)=>{const n=P(r,e);return t?n:!n},M=(r,e,t="")=>{const n=new RegExp(e,t);return Array.isArray(r)?p(r,n,(s,o)=>typeof s=="string"&&o.test(s)):n.test(r)},Q=(r,e,t,n)=>{for(const[s,o]of Object.entries(n))switch(s){case"$eq":if(!$(t,o))return!1;break;case"$ne":if(!U(t,o))return!1;break;case"$gt":if(!z(t,o))return!1;break;case"$gte":if(!B(t,o))return!1;break;case"$lt":if(!G(t,o))return!1;break;case"$lte":if(!H(t,o))return!1;break;case"$in":if(!I(t,o))return!1;break;case"$nin":if(!K(t,o))return!1;break;case"$exists":if(!L(r,e,o))return!1;break;case"$regex":const i=n.$options||"";if(!M(t,o,i))return!1;break;case"$options":break;default:throw new Error(`Unsupported query operator: ${s}`)}return!0},T=(r,e)=>{for(let t=0;t<e.length;t++)if(y(r,e[t]))return!0;return!1},y=(r,e)=>{if(!e||Object.keys(e).length===0)return!0;if(e.$or&&Array.isArray(e.$or)){if(!T(r,e.$or))return!1;const t={...e};return delete t.$or,Object.keys(t).length>0?y(r,t):!0}for(const[t,n]of Object.entries(e)){const s=j(r,t);if(typeof n=="object"&&n!==null&&!Array.isArray(n)){if(!Q(r,t,s,n))return!1}else if(!$(s,n))return!1}return!0},V=r=>Object.values(r).some(e=>e===1||e===!0),W=(r,e)=>{const t={_id:r._id};for(const[n,s]of Object.entries(e))n==="_id"&&(s===0||s===!1)?delete t._id:(s===1||s===!0)&&(t[n]=r[n]);return t},X=(r,e)=>{const t={...r};for(const[n,s]of Object.entries(e))(s===0||s===!1)&&delete t[n];return t},Y=(r,e)=>!e||Object.keys(e).length===0?r:V(e)?W(r,e):X(r,e),Z=(r,e,t)=>{if(r===e)return 0;if(r===void 0)return 1;if(e===void 0)return-1;const n=r<e?-1:r>e?1:0;return t===-1?-n:n},v=(r,e)=>!e||Object.keys(e).length===0?r:r.sort((t,n)=>{for(const[s,o]of Object.entries(e)){const i=Z(t[s],n[s],o);if(i!==0)return i}return 0}),rr=(r,e)=>{if(!r)throw new Error("Database name is required");if(!e)throw new Error("Collection name is required")},er=(r,e,t,n,s)=>{const{field:o,operators:i}=s,c=n[o],_=[];J(e,t,o);let a=null;if(typeof c=="object"&&c!==null&&!Array.isArray(c)){for(const f of i)if(c[f]!==void 0){a=x(e,t,o,f,c[f]);break}}else i.includes("eq")&&(a=x(e,t,o,"eq",c));if(a)for(const f of a){const u=F(e,t,f),l=r.get(u);if(l){const d=JSON.parse(l);y(d,n)&&_.push(d)}}return _},tr=(r,e,t,n)=>{const s=[],o=`${e}:${t}:`,i=r.getRange({start:o,end:o+"\xFF"});for(const{key:c,value:_}of i){const a=JSON.parse(_);y(a,n)&&s.push(a)}return s},nr=(r,e,t)=>{let n=r;return e>0&&(n=n.slice(e)),t&&t>0&&(n=n.slice(0,t)),n},sr=(r,e,t,n,s,o)=>{try{D(e,t,n,s,o)}catch(i){r.warn("Failed to record query for auto-indexing",{error:i.message})}},or=(r,e,t,n,s,o,i,c)=>{r.info("Find operation completed",{database:e,collection:t,documents_found:n,total_matching:s,used_index:o,indexed_field:i,execution_time_ms:c})},ir=async(r,e,t={},n={})=>{const s=R();rr(r,e);const o=O(),{projection:i,sort:c,limit:_,skip:a=0}=n,f=Date.now();try{let u=[],l=!1,d=null;const g=E(r,e,t);g&&(d=g.field,u=er(o,r,e,t,g),l=u.length>0),l||(u=tr(o,r,e,t));const q=v(u,c),h=nr(q,a,_).map(w=>Y(w,i)),A=Date.now()-f;return sr(s,e,t,A,l,d),or(s,r,e,h.length,u.length,l,d,A),h}catch(u){throw s.error("Failed to find documents",{database:r,collection:e,error:u.message}),u}};var _r=ir;export{_r as default};
|
|
1
|
+
import{get_database as O,build_collection_key as F}from"../query_engine.js";import{can_use_index as E,find_documents_by_index as x}from"../index_manager.js";import{record_query as D,record_index_usage as J}from"../auto_index_manager.js";import N from"../logger.js";const{create_context_logger:R}=N("find"),m=r=>r.split("."),b=r=>r==null,S=(r,e)=>{const t=[];for(let n=0;n<r.length;n++){const s=r[n];if(typeof s=="object"&&s!==null){const o=j(s,e);o!==void 0&&(Array.isArray(o)?t.push(...o):t.push(o))}}return t.length>0?t:void 0},j=(r,e)=>{const t=m(e);let n=r;for(let s=0;s<t.length;s++){const o=t[s];if(b(n))return;if(n=n[o],Array.isArray(n)&&s<t.length-1){const i=t.slice(s+1).join(".");return S(n,i)}}return n},C=(r,e)=>r.hasOwnProperty(e),P=(r,e)=>{const t=m(e);let n=r;for(let s=0;s<t.length;s++){if(b(n)||typeof n!="object")return!1;if(s===t.length-1)return C(n,t[s]);n=n[t[s]]}return!1},k=(r,e)=>r.includes(e),p=(r,e,t)=>{for(let n=0;n<r.length;n++)if(t(r[n],e))return!0;return!1},$=(r,e)=>Array.isArray(r)?k(r,e):r===e,U=(r,e)=>Array.isArray(r)?!k(r,e):r!==e,z=(r,e)=>Array.isArray(r)?p(r,e,(t,n)=>t>n):r>e,B=(r,e)=>Array.isArray(r)?p(r,e,(t,n)=>t>=n):r>=e,G=(r,e)=>Array.isArray(r)?p(r,e,(t,n)=>t<n):r<e,H=(r,e)=>Array.isArray(r)?p(r,e,(t,n)=>t<=n):r<=e,I=(r,e)=>Array.isArray(e)?Array.isArray(r)?p(r,e,(t,n)=>n.includes(t)):e.includes(r):!1,K=(r,e)=>{if(!Array.isArray(e))return!1;if(Array.isArray(r)){for(let t=0;t<r.length;t++)if(e.includes(r[t]))return!1;return!0}return!e.includes(r)},L=(r,e,t)=>{const n=P(r,e);return t?n:!n},M=(r,e,t="")=>{const n=new RegExp(e,t);return Array.isArray(r)?p(r,n,(s,o)=>typeof s=="string"&&o.test(s)):typeof r!="string"?!1:n.test(r)},Q=(r,e,t,n)=>{for(const[s,o]of Object.entries(n))switch(s){case"$eq":if(!$(t,o))return!1;break;case"$ne":if(!U(t,o))return!1;break;case"$gt":if(!z(t,o))return!1;break;case"$gte":if(!B(t,o))return!1;break;case"$lt":if(!G(t,o))return!1;break;case"$lte":if(!H(t,o))return!1;break;case"$in":if(!I(t,o))return!1;break;case"$nin":if(!K(t,o))return!1;break;case"$exists":if(!L(r,e,o))return!1;break;case"$regex":const i=n.$options||"";if(!M(t,o,i))return!1;break;case"$options":break;default:throw new Error(`Unsupported query operator: ${s}`)}return!0},T=(r,e)=>{for(let t=0;t<e.length;t++)if(y(r,e[t]))return!0;return!1},y=(r,e)=>{if(!e||Object.keys(e).length===0)return!0;if(e.$or&&Array.isArray(e.$or)){if(!T(r,e.$or))return!1;const t={...e};return delete t.$or,Object.keys(t).length>0?y(r,t):!0}for(const[t,n]of Object.entries(e)){const s=j(r,t);if(typeof n=="object"&&n!==null&&!Array.isArray(n)){if(!Q(r,t,s,n))return!1}else if(!$(s,n))return!1}return!0},V=r=>Object.values(r).some(e=>e===1||e===!0),W=(r,e)=>{const t={_id:r._id};for(const[n,s]of Object.entries(e))n==="_id"&&(s===0||s===!1)?delete t._id:(s===1||s===!0)&&(t[n]=r[n]);return t},X=(r,e)=>{const t={...r};for(const[n,s]of Object.entries(e))(s===0||s===!1)&&delete t[n];return t},Y=(r,e)=>!e||Object.keys(e).length===0?r:V(e)?W(r,e):X(r,e),Z=(r,e,t)=>{if(r===e)return 0;if(r===void 0)return 1;if(e===void 0)return-1;const n=r<e?-1:r>e?1:0;return t===-1?-n:n},v=(r,e)=>!e||Object.keys(e).length===0?r:r.sort((t,n)=>{for(const[s,o]of Object.entries(e)){const i=Z(t[s],n[s],o);if(i!==0)return i}return 0}),rr=(r,e)=>{if(!r)throw new Error("Database name is required");if(!e)throw new Error("Collection name is required")},er=(r,e,t,n,s)=>{const{field:o,operators:i}=s,c=n[o],_=[];J(e,t,o);let a=null;if(typeof c=="object"&&c!==null&&!Array.isArray(c)){for(const f of i)if(c[f]!==void 0){a=x(e,t,o,f,c[f]);break}}else i.includes("eq")&&(a=x(e,t,o,"eq",c));if(a)for(const f of a){const u=F(e,t,f),l=r.get(u);if(l){const d=JSON.parse(l);y(d,n)&&_.push(d)}}return _},tr=(r,e,t,n)=>{const s=[],o=`${e}:${t}:`,i=r.getRange({start:o,end:o+"\xFF"});for(const{key:c,value:_}of i){const a=JSON.parse(_);y(a,n)&&s.push(a)}return s},nr=(r,e,t)=>{let n=r;return e>0&&(n=n.slice(e)),t&&t>0&&(n=n.slice(0,t)),n},sr=(r,e,t,n,s,o)=>{try{D(e,t,n,s,o)}catch(i){r.warn("Failed to record query for auto-indexing",{error:i.message})}},or=(r,e,t,n,s,o,i,c)=>{r.info("Find operation completed",{database:e,collection:t,documents_found:n,total_matching:s,used_index:o,indexed_field:i,execution_time_ms:c})},ir=async(r,e,t={},n={})=>{const s=R();rr(r,e);const o=O(),{projection:i,sort:c,limit:_,skip:a=0}=n,f=Date.now();try{let u=[],l=!1,d=null;const g=E(r,e,t);g&&(d=g.field,u=er(o,r,e,t,g),l=u.length>0),l||(u=tr(o,r,e,t));const q=v(u,c),h=nr(q,a,_).map(w=>Y(w,i)),A=Date.now()-f;return sr(s,e,t,A,l,d),or(s,r,e,h.length,u.length,l,d,A),h}catch(u){throw s.error("Failed to find documents",{database:r,collection:e,error:u.message}),u}};var _r=ir;export{_r as default};
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@joystick.js/db-canary",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.0.0-canary.
|
|
5
|
-
"canary_version": "0.0.0-canary.
|
|
4
|
+
"version": "0.0.0-canary.2260",
|
|
5
|
+
"canary_version": "0.0.0-canary.2259",
|
|
6
6
|
"description": "JoystickDB - A minimalist database server for the Joystick framework",
|
|
7
7
|
"main": "./dist/server/index.js",
|
|
8
8
|
"scripts": {
|
package/src/client/index.js
CHANGED
|
@@ -729,8 +729,9 @@ export default async (admin_action, data = {}, connection_manager, authenticated
|
|
|
729
729
|
memory: {
|
|
730
730
|
heap_used_mb: memory_usage.heapUsed,
|
|
731
731
|
heap_total_mb: memory_usage.heapTotal,
|
|
732
|
-
|
|
733
|
-
|
|
732
|
+
rss_mb: memory_usage.rss,
|
|
733
|
+
external_mb: memory_usage.external,
|
|
734
|
+
heap_used_percent: memory_usage.heapTotal > 0 ? Math.round((memory_usage.heapUsed / memory_usage.heapTotal) * 100) : 0
|
|
734
735
|
},
|
|
735
736
|
database: {
|
|
736
737
|
...performance_monitor.get_database_stats(),
|
|
@@ -291,6 +291,11 @@ const handle_regex_operator = (field_value, pattern, options = '') => {
|
|
|
291
291
|
});
|
|
292
292
|
}
|
|
293
293
|
|
|
294
|
+
// Only test regex on string values
|
|
295
|
+
if (typeof field_value !== 'string') {
|
|
296
|
+
return false;
|
|
297
|
+
}
|
|
298
|
+
|
|
294
299
|
return regex.test(field_value);
|
|
295
300
|
};
|
|
296
301
|
|