Skip to content

Commit

Permalink
Merge branch 'main' of https://github.com/hemedani/funql into main
Browse files Browse the repository at this point in the history
  • Loading branch information
etefaghian committed Sep 29, 2021
2 parents 762be99 + 4ea5071 commit 90cf9b0
Show file tree
Hide file tree
Showing 9 changed files with 324 additions and 61 deletions.
Empty file added docs/implementation.md
Empty file.
31 changes: 31 additions & 0 deletions docs/specification.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# **Lesan** Specification:

> Standardizing the output through the use of "data modeling" based on NoSQL
The following documentation attempts to clarify the motivation behind the "Lesan".

## Design Philosophy:

The inital concept of "Lesan" was first conceived during a project using GraphQL. As you may already know, GraphQL deals with the data in a graph structure with a view to solving some limitation in REST APIs, namely "overfetch" and "underfetch".

The first design decision for "Lesan" was to introduce the idea of using functions/methods that we can declare to selectively return the amount and type of data.

Using "NoSQL" documents as the underpinning way to store large amount of data, a few utility interface models are specified for each entity in our model domain.

- inRelation: In order to minimize the number of queries to obtain a piece of information, some data are embedded in a document, for instance, a user can be saved within a blog document.
- outRelation: A document within a collection has the capacity to store 16MB of data, thus, in a specific context the data that you have chosen to embed might grow large enough to exceed this number.
To proactively design our program to deal with this situation, a part of the data is stored within the document in the form of "paginate" as an embedded collection of data.
The rationale behind this decision was that, in a example of a blog with comments, more often than not only a piece of the large number of comments is needed, so by stroing only a chunk of this data within a blog, we prevent unnecessary queries to retireve all the comments.
-pureRelation: These are the properties that are native to a model

## Performance:

Due to the fact that the number of queries are minimized to the least number possible and having information stored as embedded piece of information, the number of aggregate queries are greatly reduced.

To shed some light on why this can happen, let's compare the number of queries for a real case scnenario.

In the first step, we have 1 query for both SQL and NoSQL, as the relations expands the number of queries in a SQL database increases dramatically; however, in our design we keep the queries in control by retrieving information in the most optimal fashion.

### Updating documents

Updating a field of a document could result in a cascade of updates in different relationships between different entities in our models. For instance, if a user decides to updates his name on his profile, his name must get updated in hundreds if not thousands of documents. In order to optimize this heavy and resouce-consuming operation a **\*Query Queue** is incorporated in "Lesan" which is capable of merging the relationship to make optimal update queries in the system.
30 changes: 15 additions & 15 deletions play/generatePlay.ts

Large diffs are not rendered by default.

27 changes: 27 additions & 0 deletions playground/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import Select from "react-select";
import Code from "./code.svg";
import Doc from "./component/Doc";
import { makeObjectData } from "./component/function";
import History from "./component/History";
import InputTextarea from "./component/InputTextarea";
import { Logo } from "./component/Logo";
import Setting from "./component/Seteting";
Expand Down Expand Up @@ -51,6 +52,7 @@ const App: React.FC<Props> = () => {
const [isStatic, setIsStatic] = useState<boolean>(false); //this state is for react-select models management
const [isTextarea, setIsTextarea] = useState<boolean>(false); //this state is for react-select models management
const [collapse, setCollapse] = useState<[boolean, boolean]>([false, false]);
const [history, setHistory] = useState<boolean>(false);

//this variable for set json schema
let dataSchemaDynamic: any = [];
Expand Down Expand Up @@ -150,6 +152,29 @@ const App: React.FC<Props> = () => {
)
.then(function (response) {
setResult(JSON.stringify(response.data.body));

const history: string = localStorage.getItem("history")
? localStorage.getItem("history")!
: JSON.stringify([]);

localStorage.setItem(
"history",
JSON.stringify([
...JSON.parse(history),
{
request: {
contents: isStatic ? "static" : "dynamic",
details: dataCustom,
wants: {
model: models ? models.value : "",
doit: doits ? doits.value : "",
},
},
response: response.data.body,
},
])
);
// console.log(JSON.parse(history!.split("^^^")[1]), "slam");
})
.catch(function (error) {
console.log(error.response, "err");
Expand All @@ -163,6 +188,7 @@ const App: React.FC<Props> = () => {
const [graphPage, setGraphPage] = useState(false);
return (
<Container onSubmit={handleSubmit(onSubmit)}>
<History setHistory={setHistory} history={history} />
{graphPage ? (
<OrgChartTree
port={port}
Expand Down Expand Up @@ -397,6 +423,7 @@ const App: React.FC<Props> = () => {
>
<img
src={test}
onClick={() => setHistory(true)}
style={{
height: "2.5rem",
padding: "0.5rem",
Expand Down
119 changes: 119 additions & 0 deletions playground/src/component/History.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
import React, { useEffect, useRef, useState } from "react";
import JSONPretty from "react-json-pretty";
import "react-json-pretty/themes/monikai.css";
import styled from "styled-components";
import ModalBox from "./Modalbox";

interface Props {
setHistory: any;
history: boolean;
}
const History: React.FC<Props> = ({ history, setHistory }) => {
const scroll: any = useRef(null);

const [itemHistory, setItemHistory] = useState(
localStorage.getItem("history") &&
JSON.parse(localStorage.getItem("history")!)
);
useEffect(() => {
console.log("i call", JSON.parse(localStorage.getItem("history")!));
setItemHistory(JSON.parse(localStorage.getItem("history")!));
}, [localStorage.getItem("history")]);
// setItemHistory(
// localStorage.getItem("history") &&
// JSON.parse(localStorage.getItem("history")!)
// );
// console.log(itemHistory, JSON.parse(localStorage.getItem("history")!));
const Delete = (item: number) => {
setItemHistory(
itemHistory.filter((value: any) => itemHistory[item] !== value)
);
};

return (
<ModalBox open={history} setOpen={setHistory} textHeader="History">
<ContHistory ref={scroll}>
<Tag
onClick={() => {
setItemHistory([]);
localStorage.removeItem("history");
}}
>
Clear All
</Tag>
<Body>
{itemHistory &&
itemHistory.map((item: any, index: number) => {
return (
<Item>
<Close onClick={() => Delete(index)}>&times;</Close>
<ItemBody>
<Side>
<JSONPretty
id="json-pretty-history"
data={item.request}
></JSONPretty>
</Side>
<Side>
<JSONPretty
id="json-pretty-history"
data={item.response}
></JSONPretty>
</Side>
</ItemBody>
</Item>
);
})}
</Body>
</ContHistory>
</ModalBox>
);
};

export default History;
const ContHistory = styled.div`
overflow-x: hidden;
height: 100%;
`;
const Body = styled.div`
padding: 0 0 1rem 0;
display: flex;
overflow-x: auto;
height: 85%;
`;

const Item = styled.div`
display: flex;
border: rgb(119, 82, 190) solid 0.1rem;
min-width: 35rem;
border-radius: 0.5rem;
flex-direction: column;
margin-right: 1.5rem;
`;
const ItemBody = styled.div`
display: flex;
height: 93%;
`;
const Side = styled.div`
display: flex;
margin: 0.5rem;
border-radius: 0.5rem;
overflow-x: auto;
flex: 1;
`;
const Close = styled.span`
text-align: start;
font-size: 1.5rem;
padding-left: 0.5rem;
`;

const Tag = styled.p`
color: white;
width: 6rem;
font-size: 0.9rem;
padding: 0.3rem 0;
margin: 0.5rem;
text-align: center;
border-radius: 0.2rem;
background-color: #ffb1b1;
`;
20 changes: 11 additions & 9 deletions playground/src/component/Modalbox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ import styled from "styled-components";

interface Props {
textHeader: string;
open: any;
open: boolean;
setOpen: any;
width?: string;
}
interface ContainMI {
open: string;
open: boolean;
width?: string;
}
const ModalBox: React.FC<Props> = ({
Expand All @@ -20,7 +20,7 @@ const ModalBox: React.FC<Props> = ({
}) => {
return (
<>
<Modal open={open} onClick={() => setOpen("")}></Modal>
<Modal open={open} onClick={() => setOpen(false)}></Modal>

<ContainerModal width={width} open={open}>
<HeaderModal>
Expand All @@ -34,9 +34,9 @@ const ModalBox: React.FC<Props> = ({
export default ModalBox;

const Modal = styled.div<ContainMI>`
display: ${(props) => (props.open !== "" ? "flex" : "none")};
display: ${(props) => (props.open ? "flex" : "none")};
flex-direction: column;
z-index: 1;
z-index: 10;
left: 0;
justify-content: center;
align-items: center;
Expand All @@ -48,10 +48,12 @@ const Modal = styled.div<ContainMI>`
background-color: rgba(0, 0, 0, 0.4);
`;
const ContainerModal = styled.div<ContainMI>`
display: ${(props) => (props.open !== "" ? "flex" : "none")};
display: ${(props) => (props.open ? "flex" : "none")};
border-radius: 0.8rem;
width: ${(props) => (props.width ? props.width : "65%")};
z-index: 2;
z-index: 11;
position: absolute;
margin: 5rem auto;
height: 80%;
background-color: white;
Expand All @@ -78,8 +80,8 @@ const TextHeader = styled.h3`
// `;
const BodyModal = styled.div`
display: flex;
justify-content: center;
padding: 2rem 0 3rem 0;
align-items: center;
height: 100%;
flex-wrap: wrap;
overflow-y: auto;
`;
9 changes: 5 additions & 4 deletions playground/src/component/function.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,11 @@ export const makeObjectData = (data: any) => {
delete data[key];
} else {
const arr: [] = key.split(" ");
// console.log(
// IsJsonString(data[key]) && parseInt(data[key]).toString() == "NaN"
// );

try {
isNaN(data[key]) && (data[key] = JSON.parse(data[key]));
} catch (error) {
console.log(error.message);
}
_.defaultsDeep(
dataCustom,
makeNestedObjWithArrayItemsAsKeys(arr, data[key])
Expand Down
6 changes: 5 additions & 1 deletion playground/src/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,12 @@ code {
}
.__json-pretty__ {
height: 100%;
margin: 0;
/* margin-top: 2.5rem; */
}
#json-pretty-history {
width: 100%;
}
@keyframes fadeIn {
0% {
display: flex;
Expand All @@ -27,8 +31,8 @@ code {
}
::-webkit-scrollbar {
width: 5px;
height: 5px;
}

/* Track */
::-webkit-scrollbar-track {
box-shadow: inset 0 0 5px grey;
Expand Down
Loading

0 comments on commit 90cf9b0

Please sign in to comment.