@wxn0brp/db 0.0.1

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 (53) hide show
  1. package/CollectionManager.js +119 -0
  2. package/LICENSE +21 -0
  3. package/README.md +194 -0
  4. package/action.js +250 -0
  5. package/cacheManager.js +83 -0
  6. package/database.js +208 -0
  7. package/executor.js +54 -0
  8. package/file/find.js +88 -0
  9. package/file/index.js +3 -0
  10. package/file/remove.js +75 -0
  11. package/file/update.js +83 -0
  12. package/file/utils.js +27 -0
  13. package/format.js +29 -0
  14. package/gen.js +97 -0
  15. package/graph.js +130 -0
  16. package/more.js +103 -0
  17. package/package.json +32 -0
  18. package/remote/client/database.js +229 -0
  19. package/remote/client/graph.js +139 -0
  20. package/remote/client/index.js +10 -0
  21. package/remote/server/auth.js +100 -0
  22. package/remote/server/db.js +197 -0
  23. package/remote/server/function.js +43 -0
  24. package/remote/server/graph.js +121 -0
  25. package/remote/server/gui/css/main.css +130 -0
  26. package/remote/server/gui/css/scrool.css +81 -0
  27. package/remote/server/gui/css/style.css +61 -0
  28. package/remote/server/gui/favicon.svg +12 -0
  29. package/remote/server/gui/html/data.html +15 -0
  30. package/remote/server/gui/html/main.html +46 -0
  31. package/remote/server/gui/html/nav.html +25 -0
  32. package/remote/server/gui/html/popup.html +51 -0
  33. package/remote/server/gui/index.html +49 -0
  34. package/remote/server/gui/js/api.js +166 -0
  35. package/remote/server/gui/js/index.js +17 -0
  36. package/remote/server/gui/js/loadHTML.js +16 -0
  37. package/remote/server/gui/js/popUp.js +72 -0
  38. package/remote/server/gui/js/queryApi.js +51 -0
  39. package/remote/server/gui/js/queryDb.js +79 -0
  40. package/remote/server/gui/js/queryGraph.js +144 -0
  41. package/remote/server/gui/js/render.js +64 -0
  42. package/remote/server/gui/js/templates.js +31 -0
  43. package/remote/server/gui/js/utils.js +36 -0
  44. package/remote/server/gui/js/vars.js +9 -0
  45. package/remote/server/gui/libs/core.js +176 -0
  46. package/remote/server/gui/libs/d3.v7.min.js +2 -0
  47. package/remote/server/gui/libs/handlebars.min.js +29 -0
  48. package/remote/server/gui/libs/json5.min.js +1 -0
  49. package/remote/server/index.js +63 -0
  50. package/remote/server/initDataBases.js +20 -0
  51. package/remote/server/pathUtils.js +7 -0
  52. package/remote/server/secret.js +23 -0
  53. package/remote/serverMgmt/index.js +86 -0
@@ -0,0 +1,51 @@
1
+ const dbActionUtils = {
2
+ async query(data, path){
3
+ if(!vars.selectedServer) return false;
4
+ if(!vars.selectedDb) return false;
5
+ if(!vars.selectedTable) return false;
6
+
7
+ const body = {
8
+ db: vars.selectedDb,
9
+ collection: vars.selectedTable,
10
+ ...data
11
+ }
12
+
13
+ const server = serversMeta[vars.selectedServer];
14
+ const res = await fetch(server.url + "db/" + path, {
15
+ method: "POST",
16
+ headers: {
17
+ "Content-Type": "application/json",
18
+ "Authorization": server.token
19
+ },
20
+ body: JSON.stringify(body)
21
+ }).then(res => res.json());
22
+ if(res.err){
23
+ alert(res.msg);
24
+ return false;
25
+ }
26
+
27
+ return res.result;
28
+ }
29
+ }
30
+
31
+ const dbActions = {
32
+ async find(query, context=undefined, opts=undefined){
33
+ const body = {
34
+ search: query,
35
+ context,
36
+ opts
37
+ }
38
+
39
+ return await dbActionUtils.query(body, "database/find");
40
+ },
41
+ }
42
+
43
+ const graphActions = {
44
+ async find(node){
45
+ return await dbActionUtils.query({ node }, "graph/find");
46
+ },
47
+
48
+ async getAll(){
49
+ return await dbActionUtils.query({}, "graph/getAll");
50
+ },
51
+ }
@@ -0,0 +1,79 @@
1
+ const queryDbFunc = {
2
+ queryInput: document.querySelector("#query"),
3
+ queryTypeSelect: document.querySelector("#query-type"),
4
+ queryContextInput: document.querySelector("#query-context"),
5
+ queryContextLabel: document.querySelector("#query-context-label"),
6
+ queryOptsInput: document.querySelector("#query-opts"),
7
+
8
+ renderData(){
9
+ if(!db_data || db_data.length == 0){
10
+ data_output.innerHTML = "<p>No data</p>";
11
+ return;
12
+ }
13
+ data_output.innerHTML = templates.tableData({ data: db_data });
14
+ },
15
+
16
+ init(){
17
+ document.querySelector("#query-db-btn").addEventListener("click", async () => {
18
+ let query = queryDbFunc.queryInput.value.trim();
19
+ let type = queryDbFunc.queryTypeSelect.value.trim();
20
+ let context = queryDbFunc.queryContextInput.value.trim();
21
+ let opts = queryDbFunc.queryOptsInput.value.trim();
22
+
23
+ if(!query) query = "{}";
24
+ if(!type) type = "json";
25
+ if(!context) context = "{}";
26
+ if(!opts) opts = "{}";
27
+
28
+ switch(type){
29
+ case "js-function":
30
+ try{
31
+ (new Function("return " + query))();
32
+ }catch{
33
+ return alert("Invalid query context");
34
+ }
35
+ break;
36
+ case "json5":
37
+ if(!query.startsWith("{")) query = "{" + query + "}";
38
+ query = JSON5.parse(query);
39
+ break;
40
+ case "json":
41
+ query = JSON.parse(query);
42
+ break;
43
+ }
44
+
45
+ context = JSON5.parse(context);
46
+ opts = JSON5.parse(opts);
47
+ if(!context) context = {};
48
+ if(!opts) opts = {};
49
+
50
+ const data = await dbActions.find(query, context, opts);
51
+ if(!data) return;
52
+ db_data = data;
53
+ queryDbFunc.renderData();
54
+ });
55
+
56
+ queryDbFunc.queryTypeSelect.addEventListener("change", () => {
57
+ queryDbFunc.queryContextLabel.style.display = queryTypeSelect.value == "js-function" ? "block" : "none";
58
+ });
59
+
60
+ document.querySelector("#sortData").addEventListener("click", () => {
61
+ const sortKey = prompt("Enter key to sort by:");
62
+ if(!sortKey) return;
63
+ queryDbFunc.sortData(sortKey);
64
+ });
65
+ },
66
+
67
+ sortData(key){
68
+ db_data.sort((a, b) => {
69
+ const aValue = a[key] !== undefined ? a[key] : "";
70
+ const bValue = b[key] !== undefined ? b[key] : "";
71
+ if(aValue > bValue) return 1;
72
+ if(aValue < bValue) return -1;
73
+ return 0;
74
+ });
75
+ this.renderData();
76
+ }
77
+ }
78
+
79
+ queryDbFunc.init();
@@ -0,0 +1,144 @@
1
+ const queryGraphFunc = {
2
+ queryInput: document.querySelector("#query-graph-node"),
3
+ outputMethodSelect: document.querySelector("#query-graph-output-method"),
4
+
5
+ init(){
6
+ document.querySelector("#query-graph-btn").addEventListener("click", async () => {
7
+ const node = queryGraphFunc.queryInput.value.trim();
8
+ const edges = await graphActions.find(node);
9
+ db_data = edges;
10
+ queryGraphFunc.displayEdges();
11
+ });
12
+
13
+ document.querySelector("#query-graph-all-btn").addEventListener("click", async () => {
14
+ const edges = await graphActions.getAll();
15
+ db_data = edges;
16
+ queryGraphFunc.displayEdges();
17
+ });
18
+ },
19
+
20
+ displayEdges(){
21
+ const method = queryGraphFunc.outputMethodSelect.value;
22
+
23
+ switch(method){
24
+ case "table":
25
+ if(!db_data || db_data.length == 0){
26
+ data_output.innerHTML = "<p>No data</p>";
27
+ return;
28
+ }
29
+ data_output.innerHTML = templates.tableData({ data: db_data });
30
+ break;
31
+ case "graph":
32
+ queryGraphFunc.displayEdgesGraph();
33
+ break;
34
+ }
35
+ },
36
+
37
+ displayEdgesGraph(){
38
+ if(!db_data || db_data.length == 0){
39
+ data_output.innerHTML = "<p>No data</p>";
40
+ return;
41
+ }
42
+ data_output.innerHTML = "";
43
+ const { nodes, links } = queryGraphFunc.transformData(db_data);
44
+
45
+ const div = document.createElement("div");
46
+ div.style.height = "500px";
47
+ div.style.width = "99%";
48
+ data_output.appendChild(div);
49
+
50
+ const width = div.clientWidth;
51
+ const height = div.clientHeight;
52
+
53
+ const zoom = d3.zoom()
54
+ .scaleExtent([0.1, 4])
55
+ .on("zoom", (event) => {
56
+ g.attr("transform", event.transform);
57
+ })
58
+
59
+ const svg = d3.create("svg")
60
+ .attr("width", width)
61
+ .attr("height", height)
62
+ .call(zoom);
63
+
64
+ const g = svg.append("g");
65
+
66
+ const simulation = d3.forceSimulation(nodes)
67
+ .force("link", d3.forceLink().id(d => d.id).distance(90))
68
+ .force("charge", d3.forceManyBody().strength(-90))
69
+ .force("center", d3.forceCenter(width / 2, height / 2))
70
+ .force("collision", d3.forceCollide().radius(50))
71
+ .force("gravity", d3.forceManyBody().strength(20));
72
+
73
+ const link = g.append("g")
74
+ .attr("class", "links")
75
+ .selectAll("line")
76
+ .data(links)
77
+ .enter().append("line")
78
+ .attr("stroke-width", 2)
79
+ .style("stroke", "var(--accent)");
80
+
81
+ const node = g.append("g")
82
+ .attr("class", "nodes")
83
+ .selectAll("g")
84
+ .data(nodes)
85
+ .enter().append("g");
86
+
87
+ node.append("circle")
88
+ .attr("r", 8)
89
+ .attr("fill", "var(--accent)");
90
+
91
+ node.append("text")
92
+ .attr("dx", 12)
93
+ .attr("dy", ".35em")
94
+ .attr("fill", "var(--txt)")
95
+ .text(d => d.id)
96
+ .style("cursor", "pointer")
97
+ .on("click", function(event, d) {
98
+ queryGraphFunc.copyToClipboard(d.id);
99
+ });
100
+
101
+ simulation
102
+ .nodes(nodes)
103
+ .on("tick", () => {
104
+ link.attr("x1", d => d.source.x)
105
+ .attr("y1", d => d.source.y)
106
+ .attr("x2", d => d.target.x)
107
+ .attr("y2", d => d.target.y);
108
+
109
+ node.attr("transform", d => `translate(${d.x},${d.y})`);
110
+ });
111
+
112
+ simulation.force("link").links(links);
113
+ div.appendChild(svg.node());
114
+
115
+ const resetView = document.createElement("button");
116
+ resetView.innerText = "Reset view";
117
+ resetView.addEventListener("click", () => {
118
+ svg.transition().duration(750)
119
+ .call(zoom.transform, d3.zoomIdentity);
120
+ });
121
+ data_output.appendChild(resetView);
122
+ },
123
+
124
+ transformData(inputData){
125
+ const nodesSet = new Set();
126
+
127
+ const links = inputData.map(({ a, b }) => {
128
+ nodesSet.add(a);
129
+ nodesSet.add(b);
130
+ return { source: a, target: b };
131
+ });
132
+
133
+ const nodes = Array.from(nodesSet).map(id => ({ id }));
134
+ return { nodes, links };
135
+ },
136
+
137
+ copyToClipboard(text){
138
+ navigator.clipboard.writeText(text).then(() => alert("Copied in clipboard!")).catch(() => {
139
+ alert("Failed to copy in clipboard. Manually select and copy it:\n" + text);
140
+ });
141
+ },
142
+ }
143
+
144
+ queryGraphFunc.init();
@@ -0,0 +1,64 @@
1
+ const databaseServerList = document.querySelector("#database-server-list");
2
+ const data_output = document.querySelector("#data-output");
3
+ const queryDivDb = document.querySelector("#query-div-db");
4
+ const queryDivGraph = document.querySelector("#query-div-graph");
5
+
6
+ const renderFunc = {
7
+ renderServerList(){
8
+ const serversList = [];
9
+ Object.keys(serversMeta).forEach(id => {
10
+ serversList.push({
11
+ id,
12
+ name: serversMeta[id].name,
13
+ saved: serversMeta[id].saved || false
14
+ });
15
+ })
16
+ databaseServerList.innerHTML = templates.databasesList({ serversList });
17
+
18
+ Object.keys(serversMeta).forEach(id => {
19
+ renderFunc.rednerServer(id);
20
+ })
21
+ },
22
+
23
+ async rednerServer(id){
24
+ const server = serversMeta[id];
25
+ if(!server) return;
26
+ const nav = document.querySelector("#database-nav-"+id);
27
+ nav.innerHTML = "";
28
+
29
+ const dbsObj = await databaseGetMetaFunc.loadDbList(id);
30
+ const dbsArray = [];
31
+ Object.keys(dbsObj).forEach(db => {
32
+ dbsArray.push({
33
+ serverId: id,
34
+ name: db
35
+ });
36
+ })
37
+ nav.innerHTML = templates.databaseNav({ dbs: dbsArray });
38
+ },
39
+
40
+ async renderTables(serverId, dbName){
41
+ const nav = document.querySelector("#database-nav-"+serverId+"-"+dbName);
42
+ nav.innerHTML = "";
43
+ vars.selectedServer = serverId;
44
+ vars.selectedDb = dbName;
45
+ vars.selectedTable = null;
46
+ renderFunc.updateQueryStyle();
47
+ const tables = await databaseGetMetaFunc.getDbTables(serverId, dbName);
48
+ nav.innerHTML = templates.databasesTables({ tables, server: serverId, db: dbName });
49
+ },
50
+
51
+ updateQueryStyle(){
52
+ const dbType = getSelectedDatabase().type;
53
+ switch(dbType){
54
+ case "database":
55
+ queryDivDb.style.display = "block";
56
+ queryDivGraph.style.display = "none";
57
+ break;
58
+ case "graph":
59
+ queryDivDb.style.display = "none";
60
+ queryDivGraph.style.display = "block";
61
+ break;
62
+ }
63
+ },
64
+ }
@@ -0,0 +1,31 @@
1
+ const templatesUtils = {
2
+ load(id){
3
+ const templateEle = document.querySelector("#"+id);
4
+ const html = templateEle.innerHTML;
5
+ const template = Handlebars.compile(html);
6
+ templateEle.remove();
7
+ return template;
8
+ }
9
+ }
10
+
11
+ Handlebars.registerHelper("isObject", function (value){
12
+ return typeof value === "object" && value !== null;
13
+ });
14
+
15
+ Handlebars.registerHelper("json5", function (context){
16
+ const json5 = JSON5.stringify(context, null, 4);
17
+ return json5.substring(1, json5.length - 1);
18
+ });
19
+
20
+ Handlebars.registerHelper("br", function(height){
21
+ return new Handlebars.SafeString(`<div style="height: ${height}px;"></div>`);
22
+ });
23
+
24
+ const templates = {
25
+ databasesList: templatesUtils.load("databases-list-template"),
26
+ databaseNav: templatesUtils.load("database-nav-template"),
27
+ databasesTables: templatesUtils.load("databases-tables-template"),
28
+ tableData: templatesUtils.load("table-data-template"),
29
+ addServer: templatesUtils.load("addServer-template"),
30
+ menageServers: templatesUtils.load("menageServers-template"),
31
+ }
@@ -0,0 +1,36 @@
1
+ class AutoUpdater{
2
+ constructor(obj, key, selector, updateCB){
3
+ this.obj = obj;
4
+ this.key = key;
5
+ this.element = document.querySelector(selector);
6
+ this.updateCB = updateCB;
7
+ this.init();
8
+ }
9
+
10
+ init(){
11
+ this.updateElement();
12
+ this.watch();
13
+ }
14
+
15
+ updateElement(){
16
+ let value = this.obj[this.key];
17
+ const formattedValue = this.updateCB ? this.updateCB(value) : value;
18
+ this.element.innerHTML = formattedValue;
19
+ }
20
+
21
+ watch(){
22
+ let currentValue = this.obj[this.key];
23
+
24
+ Object.defineProperty(this.obj, this.key, {
25
+ set: (newValue) => {
26
+ currentValue = newValue;
27
+ this.updateElement();
28
+ },
29
+ get: () => currentValue
30
+ });
31
+ }
32
+ }
33
+
34
+ function getSelectedDatabase(){
35
+ return serversData[vars.selectedServer][vars.selectedDb];
36
+ }
@@ -0,0 +1,9 @@
1
+ let serversData = {};
2
+ let serversMeta = {};
3
+ let db_data = [];
4
+
5
+ const vars = {
6
+ selectedServer: null,
7
+ selectedDb: null,
8
+ selectedTable: null,
9
+ }
@@ -0,0 +1,176 @@
1
+ var lo = console.log;
2
+ const delay = ms => new Promise(res => setTimeout(res, ms));
3
+
4
+ const cw = {};
5
+
6
+ cw.proto = {
7
+ html(v){
8
+ if(this.innerHTML != undefined){
9
+ this.innerHTML = v;
10
+ return this;
11
+ }else{
12
+ return this.innerHTML;
13
+ }
14
+ },
15
+
16
+ v(v){
17
+ if(this.value != undefined){
18
+ this.value = v;
19
+ return this;
20
+ }else{
21
+ return this.value;
22
+ }
23
+ },
24
+
25
+ on(event, fn){
26
+ this.addEventListener(event, fn);
27
+ },
28
+
29
+ css(style, val=null){
30
+ const ele = this;
31
+ if(typeof style == "string"){
32
+ if(val != null){
33
+ ele.style[style] = val;
34
+ }else{
35
+ ele.style = style;
36
+ }
37
+ }else if(typeof style == "object"){
38
+ Object.assign(ele.style, style);
39
+ }
40
+ },
41
+
42
+ atrib(att, arg=null){
43
+ if(arg){
44
+ this.setAttribute(att, arg);
45
+ }else{
46
+ return this.getAttribute(att);
47
+ }
48
+ return this;
49
+ },
50
+
51
+ clA(arg){
52
+ this.classList.add(arg);
53
+ return this;
54
+ },
55
+
56
+ clR(arg){
57
+ this.classList.remove(arg);
58
+ return this;
59
+ },
60
+
61
+ clT(className){
62
+ this.classList.toggle(className);
63
+ return this;
64
+ },
65
+
66
+ animateFade(from, { time=200, cb=null }){
67
+ const style = this.style;
68
+ const steps = 50;
69
+ const timeToStep = time / steps;
70
+ const d = (from == 0 ? 1 : -1)/steps;
71
+ let index = 0;
72
+ style.opacity = from;
73
+
74
+ const interval = setInterval(() => {
75
+ if(index >= steps){
76
+ clearInterval(interval);
77
+ if(cb && typeof cb == "function") cb();
78
+ return;
79
+ }
80
+ style.opacity = parseFloat(style.opacity) + d;
81
+ index++;
82
+ }, timeToStep);
83
+ return this;
84
+ },
85
+
86
+ fadeIn(display="block", cb=null){
87
+ if(typeof display == "function"){
88
+ cb = display;
89
+ display = "block";
90
+ }
91
+
92
+ this.css("display", display);
93
+ this.animateFade(0, { cb });
94
+ this.fade = true;
95
+ return this;
96
+ },
97
+
98
+ fadeOut(cb=null){
99
+ this.animateFade(1, { time: 300, cb });
100
+ setTimeout(() => this.css("display", "none"), 300);
101
+ this.fade = false;
102
+ return this;
103
+ },
104
+
105
+ fade: true,
106
+ fadeToogle(){
107
+ if(this.fade){
108
+ this.fadeOut();
109
+ }else{
110
+ this.fadeIn();
111
+ }
112
+ return this;
113
+ },
114
+
115
+ add(child){
116
+ this.appendChild(child);
117
+ return this;
118
+ },
119
+
120
+ addUp(child){
121
+ this.insertBefore(child, this.firstChild);
122
+ return this;
123
+ },
124
+ };
125
+
126
+ cw.init = function(){
127
+ Object.assign(HTMLElement.prototype, this.proto);
128
+ }
129
+ cw.init();
130
+
131
+
132
+ cw.grid = function(doc=document.body){
133
+ function getSize(className, size){
134
+ const match = className.match(new RegExp(`${size}_(\\d+)`));
135
+ return match ? parseInt(match[0].replace(size+"_","")) : 12;
136
+ }
137
+ function add(ele, start, size){
138
+ for(let i=start; i<prefixes.length; i++){
139
+ ele.classList.add(prefixes[i] + "_" + size);
140
+ }
141
+ }
142
+ const prefixes = "smlu";
143
+ const elementy = doc.querySelectorAll(".s, [class^='s_']");
144
+ elementy.forEach(ele => {
145
+ const cm = ele.className;
146
+ let foundPrefix = 0;
147
+ for(let i=0; i<prefixes.length; i++){
148
+ if(!cm.includes(prefixes[i] + "_")) continue;
149
+ foundPrefix = i;
150
+ }
151
+ const size = getSize(cm, prefixes[foundPrefix])
152
+ add(ele, foundPrefix, size);
153
+ });
154
+ }
155
+
156
+ cw.rand = function(min, max){
157
+ return Math.round(Math.random() * (max-min) + min);
158
+ }
159
+
160
+ cw.round = function(a, b){
161
+ const factor = Math.pow(10, b);
162
+ return Math.round(a*factor)/factor;
163
+ }
164
+
165
+ cw.get = function(url){
166
+ if(!url) return false;
167
+ const xhr = new XMLHttpRequest();
168
+ xhr.open("GET", url, false);
169
+ xhr.send();
170
+
171
+ if(xhr.status == 200){
172
+ return xhr.responseText;
173
+ }else if(xhr.status == 404){
174
+ return false;
175
+ }else return null;
176
+ }