├── .babelrc
├── .gitignore
├── README.md
├── client
├── 404
│ └── 404.jsx
├── actions
│ ├── schemaAction.jsx
│ └── signupAction.jsx
├── components
│ ├── Logo.png
│ ├── Logo.png.zip
│ ├── app.jsx
│ ├── container.jsx
│ ├── footer.jsx
│ ├── githublogo.png
│ ├── navbar.jsx
│ └── sparq.png
├── home
│ ├── Info.jsx
│ ├── home.jsx
│ └── homelogin.jsx
├── index.html
├── login
│ ├── login.jsx
│ ├── loginPanel.jsx
│ ├── loginbutton.jsx
│ └── loginfield.jsx
├── main.css
├── profile
│ ├── profile.jsx
│ ├── sideComponents
│ │ ├── forms
│ │ │ └── fakeRoute.jsx
│ │ ├── graphiQL.jsx
│ │ ├── schemaFields
│ │ │ ├── input.jsx
│ │ │ ├── relationships.jsx
│ │ │ ├── saved.jsx
│ │ │ └── schemaField.jsx
│ │ └── table.jsx
│ ├── sidebar.jsx
│ └── table-view.jsx
├── signout
│ └── signout.jsx
└── signup
│ └── signup.jsx
├── dbConfig.js
├── fixture
├── postcall_fixture.js
└── test_fixture.js
├── package.json
├── public
└── favicon.ico
├── server.js
├── server
├── controllers
│ ├── authController.js
│ └── userController.js
├── db
│ ├── sparqDb.js
│ └── sparq_schema.js
└── middleware
│ ├── createDb.js
│ ├── devUserController.js
│ └── setSchema.js
├── transpiler
├── db_transpiler.js
├── db_transpiler_methods.js
├── gqlschema_transpiler.js
└── gqlschema_transpiler_methods.js
└── webpack.config.js
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": ["es2015"]
3 | }
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | bundle.js
3 | config.json
4 | npm-debug.log
5 | .DS_Store
6 | devUserDbs
7 | devUserGql
8 | **/.DS_Store
9 | .env
10 | **/.env
11 |
12 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # SparQ
2 |
3 | 
4 |
5 | SparQ is an open-source project providing user the ability to create a full functional GraphQL enabled back-end in minutes.
6 |
7 | SparQ is currently in Alpha. We welcome any feedback you might have.
8 |
9 | ### Usage
10 | 1. Sign Up / Login
11 | 2. Define table names
12 | 3. Define table fields
13 | 4. Click Save
14 | 5. Enter table relationships
15 | 6. Click Save
16 | 7. Navigate to client to perform queries
17 |
18 | ### Examples
19 |
20 | **Example:** query to retrieve data.
21 | Table Name: Person
22 | Data: firstName, age, email, id
23 | ```
24 | {
25 | person {
26 | firstName
27 | age
28 | email
29 | id
30 | }
31 | }
32 | ```
33 |
34 |
35 | **Example:** mutation to create new person.
36 | Table Name: Person
37 | Data: firstName, age, email, id
38 | ```
39 | mutation addPersonExample {
40 | addPerson(firstName: "Erlich", age: 30, email: "erlich@bachman.com") {
41 | id
42 | firstName
43 | }
44 | }
45 | ```
46 |
47 | ### Contributors
48 |
49 | [Derrick Ung](https://github.com/derrickrung)
50 |
51 | [Jayce Tan](https://github.com/jaycetan)
52 |
53 | [Stephen Langdon](https://github.com/stphnlngdncoding)
54 |
--------------------------------------------------------------------------------
/client/404/404.jsx:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react';
2 |
3 | class NotFound extends Component {
4 | render() {
5 | return (
6 |
This page is not found!
7 | )
8 | }
9 | }
10 |
11 | export default NotFound;
--------------------------------------------------------------------------------
/client/actions/schemaAction.jsx:
--------------------------------------------------------------------------------
1 | import axios from 'axios';
2 |
3 | function createFixture(data) {
4 |
5 | let values = Object.assign([], data)
6 |
7 | let fixture = {
8 | "userID": '',
9 | "UserPassword": '',
10 | "DBName": "DBNAME123ABC",
11 | "tables": [],
12 | "hasRelationships": false,
13 | "relationships": [],
14 | "relationshipsString": ""
15 | }
16 |
17 | let tableValues = {
18 | "tableName": "",
19 | "fields": []
20 | }
21 |
22 | let fieldValues = {
23 | "fieldName": "",
24 | "type": "",
25 | "required": false,
26 | "mutable": false
27 | }
28 |
29 |
30 | //loop through large array full of smaller arrays that represent each form in schema
31 | for(let i = 0; i < values.length; i++) {
32 | fixture.tables.push(Object.assign({}, tableValues))
33 |
34 | //set the name of the table
35 | fixture.tables[i].tableName = values[i][0]
36 |
37 | //variable for relationship of the table
38 | const relations = values[i].slice(-2)
39 |
40 | //variable for length to save calculation time
41 | let leng = values[i].length - 2
42 |
43 | let temp = []
44 |
45 | for(let j = 1; j < leng; j += 4) {
46 |
47 | //account for empty field names
48 | if(values[i][j] !== '') {
49 | let field = Object.assign({}, fieldValues)
50 |
51 | //insert all the appropriate values for the specific field
52 | field.fieldName = values[i][j][0].toLowerCase() + values[i][j].slice(1);
53 | field.type = values[i][j + 1];
54 | field.required = values[i][j + 2];
55 | field.mutable = values[i][j + 3];
56 |
57 | temp.push(field)
58 | }
59 | }
60 |
61 | //account for relationships
62 | if(relations[0] !== 'none') {
63 | fixture.hasRelationships = true;
64 | fixture.relationships.push({"Master": values[i][0], "Slave": relations[1], "Verb": relations[0]})
65 | }
66 |
67 | fixture.tables[i].fields = temp
68 | }
69 |
70 | let id = (() => {
71 | var value = "; " + document.cookie;
72 | var parts = value.split("; " + 'devId' + "=");
73 | if (parts.length == 2) return parts.pop().split(";").shift();
74 | })
75 |
76 | const devId = id()
77 |
78 |
79 | fixture.userID = devId;
80 | fixture.DBName = fixture.userID;
81 |
82 | //create relationship strings
83 | fixture.relationships.map((item) => {
84 | let str = item.Master + '.' + item.Verb + '(' + item.Slave + ');\n'
85 | fixture.relationshipsString += str;
86 | })
87 |
88 | //console.log(fixture, 'fixture')
89 |
90 | return axios.post('/edit', fixture)
91 | .then((response) => console.log('Successfully Saved'))
92 | .catch((err) => console.log(err));
93 | }
94 |
95 |
96 | export default createFixture;
--------------------------------------------------------------------------------
/client/actions/signupAction.jsx:
--------------------------------------------------------------------------------
1 | import axios from 'axios';
2 |
3 | export default function Signup(data) {
4 | return (data) => axios.post('/signup', data)
5 | .then((response) => console.log(response))
6 | .catch((err) => console.log(err));
7 | }
--------------------------------------------------------------------------------
/client/components/Logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TeamJSD/SparQ/419b5b72f2b1e937d98ea1542d754464d67165b5/client/components/Logo.png
--------------------------------------------------------------------------------
/client/components/Logo.png.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TeamJSD/SparQ/419b5b72f2b1e937d98ea1542d754464d67165b5/client/components/Logo.png.zip
--------------------------------------------------------------------------------
/client/components/app.jsx:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react';
2 | import ReactDOM from 'react-dom';
3 | import { Router, Route, Link, IndexRoute, hashHistory, browserHistory } from 'react-router';
4 | import Home from './../home/home.jsx';
5 | import Login from './../login/login.jsx';
6 | import Profile from './../profile/profile.jsx';
7 | import NotFound from './../404/404.jsx';
8 | import Container from './container.jsx';
9 | import Signup from './../signup/signup.jsx';
10 | import Signout from './../signout/signout.jsx';
11 |
12 | class App extends Component {
13 | render() {
14 | return (
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 | )
26 | }
27 | }
28 |
29 | ReactDOM.render(
30 | ,
31 | document.getElementById('app')
32 | )
--------------------------------------------------------------------------------
/client/components/container.jsx:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react';
2 | import NavBar from './navbar.jsx';
3 |
4 | class Container extends Component {
5 | render() {
6 | return (
7 |
8 |
9 | {this.props.children}
10 |
11 | )
12 | }
13 | }
14 |
15 | export default Container;
--------------------------------------------------------------------------------
/client/components/footer.jsx:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react';
2 |
3 | class Footer extends Component {
4 | render() {
5 | return (
6 |
14 | )
15 | }
16 | }
17 |
18 | export default Footer;
--------------------------------------------------------------------------------
/client/components/githublogo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TeamJSD/SparQ/419b5b72f2b1e937d98ea1542d754464d67165b5/client/components/githublogo.png
--------------------------------------------------------------------------------
/client/components/navbar.jsx:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react';
2 | import { Router, Route, Link, IndexRoute, hashHistory, browserHistory } from 'react-router';
3 | import Logo from './Logo.png';
4 |
5 | class NavBar extends Component {
6 | constructor() {
7 | super();
8 | }
9 |
10 |
11 | getCookie(name) {
12 | var value = "; " + document.cookie;
13 | var parts = value.split("; " + name + "=");
14 | if (parts.length == 2) return parts.pop().split(";").shift();
15 | }
16 |
17 | render() {
18 | let indicator = this.getCookie('devId')
19 | let link;
20 | let notLoggedIn;
21 | if(indicator) {
22 | link = Sign Out
23 | notLoggedIn = '/profile'
24 | } else {
25 | link = Login
26 | notLoggedIn = '/login'
27 | }
28 |
29 | return (
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 | Home
38 | Profile
39 | { link }
40 |
41 |
42 |
43 | )
44 | }
45 | }
46 |
47 | export default NavBar;
--------------------------------------------------------------------------------
/client/components/sparq.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TeamJSD/SparQ/419b5b72f2b1e937d98ea1542d754464d67165b5/client/components/sparq.png
--------------------------------------------------------------------------------
/client/home/Info.jsx:
--------------------------------------------------------------------------------
1 | //Info
2 | import React, {Component} from 'react';
3 |
4 | class Info extends Component {
5 | render() {
6 | return (
7 |
8 |
SparQ
9 |
10 | SparQ is a platform that offers GraphQL as a service, giving developers infinite possibilities to create their dream application.
11 | With just a few clicks, developers can spin up a whole backend that can be queried using GraphQL- the most intuitive and user-friendly query language available.
12 |
13 |
14 | )
15 | }
16 | }
17 |
18 | export default Info;
19 |
--------------------------------------------------------------------------------
/client/home/home.jsx:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react';
2 | import Info from './Info.jsx';
3 | import HomeLogin from './homelogin.jsx';
4 | import Footer from './../components/footer.jsx';
5 |
6 | class Home extends Component {
7 | render() {
8 | return (
9 |
10 |
11 |
12 |
SparQ
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 | )
24 | }
25 | }
26 |
27 | export default Home;
--------------------------------------------------------------------------------
/client/home/homelogin.jsx:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react';
2 | import pic from './../components/githublogo.png';
3 | import { Link } from 'react-router';
4 |
5 | class HomeLogin extends Component {
6 | constructor(){
7 | super();
8 | }
9 |
10 | getCookie(name) {
11 | var value = "; " + document.cookie;
12 | var parts = value.split("; " + name + "=");
13 | if (parts.length == 2) return parts.pop().split(";").shift();
14 | }
15 |
16 | render() {
17 | let indicator = this.getCookie('devId')
18 | let link;
19 | if(indicator) {
20 | link = My Profile
21 | } else {
22 | link = Login
23 | }
24 |
25 | return (
26 |
27 |
Log into SparQ
28 | { link }
29 |
30 | )
31 | }
32 | }
33 |
34 | export default HomeLogin;
--------------------------------------------------------------------------------
/client/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | SparQ
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/client/login/login.jsx:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react';
2 | import LoginPanel from './loginPanel.jsx';
3 | import Signup from './../actions/signupAction.jsx';
4 | import axios from 'axios';
5 | import { Link } from 'react-router';
6 |
7 | class Login extends Component {
8 | constructor(props) {
9 | super(props);
10 | this.state = {
11 | username: '',
12 | password: '',
13 | };
14 | this.onChange = this.onChange.bind(this);
15 | this.onSubmit = this.onSubmit.bind(this);
16 | }
17 |
18 | onChange(e) {
19 | this.setState({ [e.target.name]: e.target.value });
20 | }
21 |
22 | onSubmit(e) {
23 | e.preventDefault();
24 | axios.post('/login', this.state).then((response) => {
25 | console.log(response, 'this is the response')
26 | window.location = response.data.redirectUrl
27 | }).catch((err) => console.log(err))
28 | }
29 |
30 | render() {
31 | const style = {border: '1px solid black'};
32 |
33 | return (
34 |
48 | )
49 | }
50 | }
51 |
52 | export default Login;
--------------------------------------------------------------------------------
/client/login/loginPanel.jsx:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react';
2 | import LoginButton from './loginbutton.jsx';
3 | import LoginField from './loginfield.jsx';
4 | import pic from './../components/githublogo.png';
5 |
6 | class LoginPanel extends Component {
7 | constructor(){
8 | super();
9 | }
10 |
11 | render() {
12 | return (
13 |
14 |
Log into SparQ
15 |
21 |
22 | )
23 | }
24 | }
25 |
26 | export default LoginPanel;
--------------------------------------------------------------------------------
/client/login/loginbutton.jsx:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react';
2 |
3 | class LoginButton extends Component {
4 | constructor() {
5 | super()
6 | }
7 |
8 | render() {
9 | return (
10 |
13 | )
14 | }
15 | }
16 |
17 | export default LoginButton;
--------------------------------------------------------------------------------
/client/login/loginfield.jsx:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react';
2 |
3 | class LoginField extends Component {
4 | constructor(props) {
5 | super(props)
6 | }
7 |
8 | render() {
9 | return (
10 |
11 |
16 |
17 | )
18 | }
19 | }
20 |
21 | export default LoginField;
--------------------------------------------------------------------------------
/client/main.css:
--------------------------------------------------------------------------------
1 | /*general*/
2 | * {
3 | font-family: 'Quicksand', sans-serif;
4 | }
5 |
6 | body {
7 | margin: 0;
8 | }
9 |
10 | h1 {
11 | font-size: 60px;
12 | color: #333;
13 | }
14 |
15 | p {
16 | color: #666;
17 | font-size: 30px;
18 | }
19 |
20 | input {
21 | width: 300px;
22 | }
23 |
24 | select {
25 | margin-right: 20px;
26 | background-color: white;
27 | height: 25px;
28 | color: #666;
29 | }
30 |
31 | button {
32 | width: 200px;
33 | height: 60px;
34 | size: 20px;
35 | font-size: 25px;
36 | background: white;
37 | border: 0.5px solid #333;
38 | margin: 25px auto 20px auto;
39 | }
40 |
41 | button:hover {
42 | background: #333;
43 | color: white;
44 | cursor: pointer;
45 | }
46 |
47 | /*navbar*/
48 | #nav-container {
49 | background: white;
50 | }
51 |
52 | .navbar {
53 | display: flex;
54 | flex-flow: row nowrap;
55 | justify-content: flex-end;
56 | align-items: center;
57 | margin: 0;
58 | border-bottom: 1px solid #E0E0E0;
59 | }
60 |
61 | #spacer {
62 | visibility: hidden;
63 | flex-grow: 1;
64 | }
65 |
66 | #logo {
67 |
68 | }
69 |
70 | #logo img {
71 | width: 30%;
72 | }
73 |
74 | #nav {
75 | padding-right: 30px;
76 | }
77 |
78 | .navbar a {
79 | margin-left: 40px;
80 | text-decoration: none;
81 | color: #666;
82 | font-size: 20px;
83 | }
84 |
85 | .navbar a:hover {
86 | color: black;
87 | }
88 |
89 | /*home*/
90 | #home-container {
91 | /* display: flex;
92 | flex-flow: row nowrap;
93 | justify-content: flex-end;
94 | align-items: center;
95 | padding: 0;
96 | margin: 40px 0 150px 0;*/
97 | }
98 |
99 | #home-welcome {
100 | background-image:linear-gradient(
101 | rgba(0, 0, 0, 0.5),
102 | rgba(0, 0, 0, 0.5)
103 | ),
104 | url(https://wallpaperscraft.com/image/danboard_boxes_robot_mood_sparkler_sparks_48969_1920x1080.jpg);
105 | background-size: cover;
106 | background-position: center center;
107 | height: 800px;
108 | vertical-align: middle;
109 | text-align: center;
110 | line-height: 700px;
111 | font-family: 'Lato', sans-serif;
112 | }
113 |
114 | #home-welcome h1, h2 {
115 | color: white;
116 | margin: 0;
117 | font-family: 'Lato', sans-serif;
118 | font-weight: lighter;
119 | }
120 |
121 |
122 | #info {
123 | background-color: #efefef;
124 | text-align: center;
125 | padding: 120px 80px;
126 | }
127 |
128 | #info h1 {
129 | margin: 0;
130 | }
131 |
132 | #info p {
133 |
134 | }
135 |
136 | #panel {
137 | padding: 0 60px;
138 | width: 30%;
139 | text-align: center;
140 | margin: 50px auto;
141 | }
142 |
143 | #githubimg {
144 | width: 200px;
145 | margin-bottom: 40px;
146 | text-align: center;
147 | }
148 |
149 | #footer {
150 | text-align: center;
151 | padding: 20px 0;
152 | border-top: 1px solid #E0E0E0;
153 | }
154 |
155 | #footer a {
156 | font-weight: bold;
157 | text-decoration: none;
158 | color: blue;
159 | }
160 |
161 | #login-view {
162 | text-align: center;
163 | }
164 |
165 | #login-view a {
166 | text-decoration: none;
167 | }
168 |
169 | #login-view h1 {
170 | font-size: 30px;
171 | }
172 |
173 | #login-header h1 {
174 | display: inline-block;
175 | }
176 |
177 | #sign-up {
178 | color: white;
179 | text-shadow:
180 | -1px -1px 0 #000,
181 | 1px -1px 0 #000,
182 | -1px 1px 0 #000,
183 | 1px 1px 0 #000;
184 | padding: 0px;
185 | text-decoration: none;
186 | }
187 |
188 |
189 | #sign-up:hover {
190 | cursor: pointer;
191 | text-shadow: none;
192 | color: #333;
193 | }
194 |
195 |
196 | #login-panel {
197 | border: 1px solid black;
198 | padding-bottom: 60px;
199 | width: 500px;
200 | margin: 0 auto 60px auto;
201 | }
202 |
203 | #login-field input {
204 | font-size: 20px;
205 | width: 196px;
206 | height: 30px;
207 | color: black;
208 | margin: 0;
209 | }
210 |
211 | #submit {
212 | width: 202px;
213 | }
214 |
215 | #profile {
216 | display: flex;
217 | flex-flow: row nowrap;
218 | justify-content: flex-end;
219 | }
220 |
221 | #sidebar {
222 | padding: 30px 0;
223 | height: 100%;
224 | }
225 |
226 | #sidebar h3 {
227 | color: #666;
228 | margin: 0;
229 | padding: 20px 30px;
230 | }
231 |
232 | #sidebar h3:hover {
233 | cursor: pointer;
234 | color: black;
235 | background-color: #f6f6f6;
236 | }
237 |
238 | #viewer {
239 | padding: 0 0 200px 50px;
240 | flex-grow: 1;
241 | border-left: 1px solid #E0E0E0;
242 | background-color: #fdfdfd;
243 | }
244 |
245 | #create-table, #save-schema {
246 | margin-top: 30px;
247 | height: 50px;
248 | width: 200px;
249 | font-size: 20px;
250 | border: none;
251 | border-radius: 10px;
252 | margin-right: 30px;
253 | color: white;
254 | background-color: #ffbb3f;
255 | box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
256 | }
257 |
258 | #create-table:hover, #save-schema:hover {
259 | color: white;
260 | background-color: orange;
261 | }
262 |
263 | .add-input, .delete-table {
264 | width: 40px;
265 | height: 40px;
266 | font-size: 23px;
267 | margin: 25px 20px 0px 0px;
268 | border: 1px solid #ffbb3f;
269 | border-radius: 50%;
270 | color: white;
271 | background-color: #ffbb3f;
272 | font-weight: bolder;
273 | box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
274 | }
275 |
276 | .add-input:hover, .delete-table:hover {
277 | color: white;
278 | background-color: orange;
279 | }
280 |
281 | #sign-up-page-button {
282 | width: 100px;
283 | height: 30px;
284 | font-size: 13px;
285 | margin-top: 25px;
286 | }
287 |
288 | .schema-form {
289 | border: 1px solid #d6d6d6;
290 | border-radius: 10px;
291 | padding: 25px;
292 | width: 80%;
293 | margin-bottom: 30px;
294 | background-color: white;
295 | box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
296 | }
297 |
298 | .input {
299 | margin: 20px 0;
300 | width: 95%;
301 | padding: 5px 10px;
302 | box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
303 | }
304 |
305 | .input select {
306 | border: none;
307 | -webkit-appearance:none;
308 | font-size: 12px;
309 | }
310 |
311 | .schema-form input {
312 | width: 65%;
313 | border: none;
314 | margin: 0 20px;
315 | font-size: 18px;
316 | color: orange;
317 | }
318 |
319 | .form-header {
320 | font-weight: bold;
321 | font-size: 20px;
322 | color: #666;
323 | }
324 |
325 | .schema-input {
326 | height: 26px;
327 | border: none;
328 | }
329 |
330 | .delete-input {
331 | font-size: 16px;
332 | display: inline-block;
333 | margin: 0px;
334 | }
335 |
336 | .delete-input:hover {
337 | cursor: pointer;
338 | color: black;
339 | font-weight: bold;
340 | }
341 |
342 |
343 | .Dropdown-root:hover {
344 | cursor: pointer;
345 | display: inline;
346 | }
347 |
348 | .Dropdown-placeholder {
349 | border-bottom: 1px solid black;
350 | width: 50px;
351 | text-align: center;
352 | }
353 |
354 |
355 | #database-view button, input {
356 | width: 100px;
357 | height: 30px;
358 | font-size: 13px;
359 | margin-top: 25px;
360 | }
361 |
362 | .schema-type-input {
363 | box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
364 | padding-left: 10px;
365 | }
366 |
367 | #database-information {
368 | border-bottom: 1px solid black;
369 | margin-top: 20px;
370 | width: 80%;
371 | text-align: center;
372 | }
373 |
374 | #database-information h3 {
375 | color: orange;
376 | size: 25px;
377 | }
378 |
379 |
380 |
381 |
382 |
383 |
384 |
385 |
386 |
387 |
388 |
389 |
390 |
391 |
--------------------------------------------------------------------------------
/client/profile/profile.jsx:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react';
2 | import SideBar from './sidebar.jsx';
3 | import Viewer from './table-view.jsx';
4 |
5 | class Profile extends Component {
6 | constructor() {
7 | super();
8 | this.state = {
9 | choice: '',
10 | }
11 |
12 | this.onClick = this.onClick.bind(this);
13 | }
14 |
15 | onClick(e) {
16 | this.setState({choice: e.target.innerHTML})
17 | }
18 |
19 | render() {
20 |
21 | return (
22 |
23 |
24 |
25 |
26 | )
27 | }
28 | }
29 |
30 | export default Profile;
--------------------------------------------------------------------------------
/client/profile/sideComponents/forms/fakeRoute.jsx:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react';
2 |
3 | class Route extends Component {
4 | constructor(){
5 | super()
6 | }
7 |
8 | render() {
9 | return (
10 |
11 |
Your route: /graphql/a1b2c3
12 |
13 | )
14 | }
15 | }
16 |
17 | export default Route;
18 |
19 |
--------------------------------------------------------------------------------
/client/profile/sideComponents/graphiQL.jsx:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react';
2 | //import GraphiQL from 'graphiql';
3 |
4 | class GraphiQL extends Component {
5 | constructor() {
6 | super()
7 | }
8 |
9 | render() {
10 | return (
11 |
12 |
GraphiQL
13 |
14 | )
15 | }
16 | }
17 |
18 | export default GraphiQL;
--------------------------------------------------------------------------------
/client/profile/sideComponents/schemaFields/input.jsx:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react';
2 |
3 | class Input extends Component {
4 | constructor() {
5 | super()
6 | }
7 |
8 | render() {
9 | return (
10 |
11 |
this.props.handleChange(event, this.props.schemaIndex, (this.props.index * 4) + 1)}
17 | >
18 |
19 |
20 |
this.props.handleChange(event, this.props.schemaIndex, (this.props.index * 4) + 2)}>
21 | String
22 | ID
23 | Number
24 | Float
25 | Boolean
26 | Date
27 |
28 |
29 |
this.props.handleChange(event, this.props.schemaIndex, (this.props.index * 4) + 3)}>
30 | Required
31 | Not required
32 |
33 |
34 |
this.props.handleChange(event, this.props.schemaIndex, (this.props.index * 4) + 4)}>
35 | Mutable
36 | Immutable
37 |
38 |
this.props.deleteInput(event, this.props.schemaIndex, this.props.index)}>x
39 |
40 |
41 |
42 | )
43 | }
44 | }
45 |
46 | export default Input;
--------------------------------------------------------------------------------
/client/profile/sideComponents/schemaFields/relationships.jsx:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react';
2 |
3 | class Relationships extends Component {
4 | constructor() {
5 | super()
6 | }
7 |
8 | render() {
9 |
10 | return (
11 |
12 |
13 | this.props.relationshipChange(event, this.props.schemaIndex, 0)}>
14 | None
15 | Belongs To
16 | Has One
17 | Belongs To Many
18 | Has Many
19 |
20 |
21 | this.props.relationshipChange(event, this.props.schemaIndex, 1)}>
22 | None
23 | {this.props.relationshipOptions.map((item, index) => {
24 | return {item} ;
25 | })
26 | }
27 |
28 |
29 |
30 | )
31 | }
32 | }
33 |
34 | export default Relationships;
--------------------------------------------------------------------------------
/client/profile/sideComponents/schemaFields/saved.jsx:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react';
2 |
3 | class Saved extends Component {
4 | constructor() {
5 | super()
6 | }
7 |
8 | render() {
9 | return (
10 |
11 |
Schema Saved!
12 |
13 | )
14 | }
15 | }
16 |
17 | export default Saved;
--------------------------------------------------------------------------------
/client/profile/sideComponents/schemaFields/schemaField.jsx:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react';
2 | import Input from './input.jsx';
3 | import Saved from './saved.jsx';
4 | import Relationships from './relationships.jsx'
5 | import createFixture from './../../../actions/schemaAction.jsx';
6 |
7 | class SchemaField extends Component {
8 | constructor() {
9 | super()
10 | this.onSubmit = this.onSubmit.bind(this)
11 | }
12 |
13 | onSubmit(e) {
14 | //when you click on add field, it won't submit the form
15 | e.preventDefault();
16 | }
17 |
18 | render() {
19 |
20 | const test = [];
21 |
22 | (() => {
23 | for(let i = 0; i < this.props.inputs; i++) {
24 | test.push(Input)
25 | }
26 | })()
27 |
28 | const inputs = test.map((Element, index) => {
29 | return
40 | })
41 |
42 | return (
43 |
44 |
84 | )
85 | }
86 | }
87 |
88 | export default SchemaField;
--------------------------------------------------------------------------------
/client/profile/sideComponents/table.jsx:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react';
2 | import SchemaField from './schemaFields/schemaField.jsx';
3 | import Input from './schemaFields/input.jsx';
4 | import Saved from './schemaFields/saved.jsx';
5 | import createFixture from './../../actions/schemaAction.jsx';
6 | import axios from 'axios';
7 |
8 | class Table extends Component {
9 | constructor() {
10 | super()
11 | this.state = {
12 | data: [],
13 | schemas: [],
14 | inputs:[],
15 | relationshipOptions: [],
16 | relationships: [],
17 | }
18 | this.createTable = this.createTable.bind(this);
19 | this.saveSchema = this.saveSchema.bind(this);
20 | this.deleteTable = this.deleteTable.bind(this);
21 | this.handleChange = this.handleChange.bind(this);
22 | this.relationshipChange = this.relationshipChange.bind(this);
23 | this.addInput = this.addInput.bind(this);
24 | this.deleteInput = this.deleteInput.bind(this);
25 | }
26 |
27 | componentDidMount() {
28 | //get request for data
29 | let data = [];
30 | let obj = [];
31 | let id = this.getCookie('devId')
32 |
33 | axios.get(`/devUserSchema/${id}`)
34 | .then((response) => {
35 |
36 | if(!response.data) {
37 | //put one initial form with one initial input field if there is no saved data
38 | obj.push(SchemaField);
39 | data.push(["Table Name", "Field Name", "STRING", "true", "true"])
40 | this.state.relationships.push(["none", "none"])
41 | this.state.inputs.push(1)
42 | this.setState({ schemas: obj, data: data})
43 |
44 | } else {
45 |
46 | data = this.collectData(response.data)
47 |
48 | for(let i = 0; i < data.length; i++) {
49 | obj = obj.concat(SchemaField)
50 | let num = 0
51 |
52 | for(let j = 0; j < data[i].length - 2; j += 4) {
53 | if(j === 0) {
54 | this.state.relationshipOptions.push(data[i][j]);
55 | j++
56 | }
57 | num++;
58 | }
59 |
60 | this.state.relationships.push(Object.assign([], data[i].splice(-2)))
61 | this.state.inputs.push(num)
62 | }
63 |
64 | this.setState({ schemas: obj, data: data })
65 | }
66 | })
67 | .catch((err) => console.log(err))
68 | }
69 |
70 | getCookie(name) {
71 | var value = "; " + document.cookie;
72 | var parts = value.split("; " + name + "=");
73 | if (parts.length == 2) return parts.pop().split(";").shift();
74 | }
75 |
76 | collectData(obj) {
77 | let data = [];
78 | let fixture = obj;
79 | for(let i = 0; i < fixture.tables.length; i++) {
80 | let temp = [];
81 | temp.push(fixture.tables[i].tableName);
82 | let fields = fixture.tables[i].fields
83 | for(let j = 0; j < fields.length; j++) {
84 | temp.push(fields[j].fieldName);
85 | temp.push(fields[j].type);
86 | temp.push(fields[j].required);
87 | temp.push(fields[j].mutable);
88 | }
89 |
90 | let slave = 'none',
91 | verb = 'none';
92 |
93 | if(fixture.relationships[i]) {
94 | if(fixture.relationships[i].Master !== fixture.tables[i].tableName) {
95 | fixture.relationships.splice(i, 0, fixture.relationships[i])
96 | fixture.relationships[i] = '';
97 | } else {
98 | slave = fixture.relationships[i].Slave
99 | verb = fixture.relationships[i].Verb
100 | }
101 | }
102 |
103 | temp.push(verb)
104 | temp.push(slave)
105 |
106 | data.push(temp)
107 | }
108 | return data;
109 | }
110 |
111 | saveSchema(e){
112 | e.preventDefault();
113 | let fixtureValues = []
114 |
115 | //get all existing form elements
116 | let children = (Array.prototype.slice.call(e.nativeEvent.target.children));
117 | children.splice(-2)
118 |
119 | //loop through form elements to get the inputs
120 | for(let i = 0; i < children.length; i++) {
121 |
122 | let childForm = children[i].children[0].elements
123 | let tempValues = []
124 |
125 | //loop through inputs to get the individual values
126 | for(let j = 0; j < childForm.length - 2; j++) {
127 | //collect input values of each form
128 | tempValues.push(childForm[j].value)
129 | }
130 |
131 | //push individual form values into whole collection (fixture values)
132 | fixtureValues.push(tempValues)
133 | }
134 |
135 | return createFixture(fixtureValues)
136 | }
137 |
138 | createTable(e) {
139 | e.preventDefault();
140 | let newState = Object.assign({}, this.state)
141 | newState.schemas.push(SchemaField);
142 | newState.data.push(["", "", "STRING", "none", "none"])
143 | newState.relationships.push(["none", "none"])
144 | newState.inputs.push(1)
145 | this.setState(newState);
146 | }
147 |
148 | deleteTable(e) {
149 | let newState = Object.assign({}, this.state)
150 | newState.data.splice(e, 1)
151 | newState.schemas.splice(e, 1)
152 | newState.inputs.splice(e, 1)
153 | newState.relationshipOptions.splice(e, 1)
154 | newState.relationships.splice(e, 1)
155 | this.setState(newState);
156 | }
157 |
158 | addInput(e, index) {
159 | e.preventDefault();
160 | let copy = Object.assign([], this.state.inputs)
161 | let data = Object.assign([], this.state.data)
162 | copy[index]++
163 | data[index].push('', 'STRING', 'true', 'true')
164 | this.setState({ data: data, inputs: copy })
165 | }
166 |
167 | deleteInput(e, schemaIndex, index) {
168 | let copy = this.state
169 | copy.inputs[schemaIndex]--
170 | copy.data[schemaIndex].splice(((index * 4) + 1), 4)
171 | this.setState({ copy })
172 | }
173 |
174 | handleChange(event, schemaIndex, index) {
175 | let copy = this.state.data
176 | copy[schemaIndex][index] = event.target.value
177 | this.setState({ data: copy });
178 | }
179 |
180 | relationshipChange(event, schemaIndex, index) {
181 | let copy = this.state.relationships
182 | copy[schemaIndex][index] = event.target.value
183 | this.setState({ relationships: copy })
184 | }
185 |
186 |
187 | render() {
188 | const schemas = this.state.schemas.map((Element, index) => {
189 | return
203 | })
204 |
205 | const id = this.getCookie('devId')
206 |
207 |
208 | return (
209 |
210 |
211 |
Your Route: www.sparq.rocks/graphQL/{id}
212 |
213 |
214 |
My Tables
215 |
220 |
221 | )
222 | }
223 | }
224 |
225 | export default Table;
--------------------------------------------------------------------------------
/client/profile/sidebar.jsx:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react';
2 |
3 | class SideBar extends Component {
4 | constructor(){
5 | super()
6 | }
7 |
8 | render() {
9 | return (
10 |
14 | )
15 | }
16 | }
17 |
18 | export default SideBar;
19 |
20 |
21 |
--------------------------------------------------------------------------------
/client/profile/table-view.jsx:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react';
2 | import GraphiQL from './sideComponents/graphiQL.jsx';
3 | import Table from './sideComponents/table.jsx';
4 | //import GraphiQL from 'graphiQL'
5 |
6 |
7 | class Viewer extends Component {
8 | constructor() {
9 | super()
10 | }
11 |
12 |
13 | render() {
14 | let component;
15 | if(this.props.view === 'GraphiQL') {
16 | component =
17 | } else {
18 | component =
19 | }
20 |
21 | return (
22 |
23 | {component}
24 |
25 | )
26 | }
27 | }
28 |
29 | export default Viewer;
--------------------------------------------------------------------------------
/client/signout/signout.jsx:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react';
2 | import { Link } from 'react-router';
3 |
4 | class Signout extends Component {
5 | constructor() {
6 | super()
7 | this.clearCookie = this.clearCookie.bind(this)
8 | }
9 |
10 | clearCookie() {
11 | document.cookie = 'devId=; expires=Thu, 01 Jan 1970 00:00:01 GMT;';
12 | }
13 |
14 | render() {
15 |
16 | return (
17 |
18 |
Sign Out?
19 | Yes
20 |
21 | )
22 | }
23 | }
24 |
25 | export default Signout;
--------------------------------------------------------------------------------
/client/signup/signup.jsx:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react';
2 | import axios from 'axios';
3 |
4 | class Signup extends Component {
5 | constructor() {
6 | super()
7 | this.state = {
8 | username: '',
9 | password: ''
10 | }
11 | this.onSubmit = this.onSubmit.bind(this)
12 | this.onChange = this.onChange.bind(this)
13 | }
14 |
15 | onSubmit(e) {
16 | e.preventDefault();
17 | console.log(this.state); //check console to see what object is being passed over
18 | axios.post('/signup', this.state).then((response) => window.location = response.data.redirectUrl).catch((err) => console.log(err))
19 | }
20 |
21 | onChange(e) {
22 | this.setState({ [e.target.name]: e.target.value })
23 | }
24 |
25 | render() {
26 | return (
27 |
28 |
Sign Up
29 |
55 |
56 | )
57 | }
58 | }
59 |
60 | export default Signup;
61 |
--------------------------------------------------------------------------------
/dbConfig.js:
--------------------------------------------------------------------------------
1 | const dbConfig = {};
2 | dbConfig.dbname = 'kcafmbns';
3 | dbConfig.username = 'kcafmbns';
4 | dbConfig.password = 'FayjdFpQ4eXUo8QdWbyKc9X7oCAuty4U';
5 | dbConfig.dialect = 'postgres';
6 | dbConfig.host = 'tantor.db.elephantsql.com';
7 |
8 | module.exports = dbConfig;
--------------------------------------------------------------------------------
/fixture/postcall_fixture.js:
--------------------------------------------------------------------------------
1 | let fixture =
2 |
3 | {
4 | "userID": "z1y2x3",
5 | "UserPassword": "",
6 | "DBName": "",
7 | "tables": [{
8 | "tableName": "Person",
9 | "fields": [{
10 | "fieldName": "email",
11 | "type": "STRING",
12 | "required": true,
13 | "mutable": false
14 | }, {
15 | "fieldName": "firstName",
16 | "type": "STRING",
17 | "required": true,
18 | "mutable": false
19 | }, {
20 | "fieldName": "age",
21 | "type": "INTEGER",
22 | "required": false,
23 | "mutable": true
24 | }]
25 | }, {
26 | "tableName": "Post",
27 | "fields": [{
28 | "fieldName": "Title",
29 | "type": "STRING",
30 | "required": true,
31 | "mutable": false
32 | }, {
33 | "fieldName": "Content",
34 | "type": "STRING",
35 | "required": true,
36 | "mutable": false
37 | }]
38 | }],
39 | "hasRelationships": true,
40 | "relationships": [{
41 | "Master": "Person",
42 | "Slave": "Post",
43 | "Verb": "hasMany"
44 | },
45 | {
46 | "Master": "Post",
47 | "Verb": "belongsTo",
48 | "Slave": "Person"
49 | }
50 | ],
51 | "relationshipsString": "Person.hasMany(Post);\nPost.belongsTo(Person);"
52 | }
53 |
54 | module.exports = fixture;
--------------------------------------------------------------------------------
/fixture/test_fixture.js:
--------------------------------------------------------------------------------
1 | let fixture =
2 |
3 | {
4 | "userID": "z1y2x3",
5 | "UserPassword": "",
6 | "DBName": "",
7 | "tables": [{
8 | "tableName": "Book",
9 | "fields": [{
10 | "fieldName": "title",
11 | "type": "STRING",
12 | "required": true,
13 | "mutable": false
14 | }, {
15 | "fieldName": "author",
16 | "type": "STRING",
17 | "required": true,
18 | "mutable": false
19 | }]
20 | }, {
21 | "tableName": "Booklet",
22 | "fields": [{
23 | "fieldName": "Title",
24 | "type": "STRING",
25 | "required": true,
26 | "mutable": false
27 | }, {
28 | "fieldName": "Content",
29 | "type": "STRING",
30 | "required": true,
31 | "mutable": false
32 | }]
33 | }],
34 | "hasRelationships": false,
35 | "relationships": [{
36 | "Master": "Person",
37 | "Slave": "Post",
38 | "Verb": "hasMany"
39 | },
40 | {
41 | "Master": "Post",
42 | "Verb": "belongsTo",
43 | "Slave": "Person"
44 | }
45 | ],
46 | "relationshipsString": "Person.hasMany(Post);\nPost.belongsTo(Person);"
47 | }
48 |
49 | module.exports = fixture;
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "sparq",
3 | "version": "1.0.0",
4 | "description": "gSpark",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1",
8 | "start": "babel-node server.js",
9 | "start-server": "node server"
10 | },
11 | "author": "TeamJSD",
12 | "license": "MIT",
13 | "dependencies": {
14 | "apollo-server": "^0.3.2",
15 | "axios": "^0.14.0",
16 | "babel-cli": "^6.16.0",
17 | "babel-preset-node5": "^11.1.0",
18 | "body-parser": "^1.15.2",
19 | "bootstrap": "^3.3.7",
20 | "commander": "^2.9.0",
21 | "cookie-parser": "^1.4.3",
22 | "cors": "^2.8.1",
23 | "css-loader": "^0.25.0",
24 | "dotenv": "^2.0.0",
25 | "express": "^4.14.0",
26 | "express-graphql": "^0.5.4",
27 | "file-loader": "^0.9.0",
28 | "fs": "0.0.1-security",
29 | "graphiql": "^0.7.8",
30 | "graphql": "^0.7.1",
31 | "lodash": "^4.16.4",
32 | "nodemon": "^1.10.2",
33 | "passport": "^0.3.2",
34 | "passport-local": "^1.0.0",
35 | "path": "^0.12.7",
36 | "pg": "^6.1.0",
37 | "pg-pool": "^1.5.0",
38 | "querystring": "^0.2.0",
39 | "react": "^15.3.2",
40 | "react-dom": "^15.3.2",
41 | "react-dropdown": "^1.1.0",
42 | "react-router": "^2.8.1",
43 | "request": "^2.75.0",
44 | "sequelize": "^3.24.3",
45 | "shortid": "^2.2.6",
46 | "style-loader": "^0.13.1",
47 | "url-loader": "^0.5.7",
48 | "watchify": "^3.7.0",
49 | "webpack": "^1.13.2"
50 | },
51 | "devDependencies": {
52 | "babel-core": "^6.17.0",
53 | "babel-loader": "^6.2.5",
54 | "babel-preset-es2015": "^6.16.0",
55 | "babel-preset-react": "^6.16.0",
56 | "babel-preset-stage-0": "^6.16.0",
57 | "babelify": "^7.3.0",
58 | "faker": "^3.1.0"
59 | },
60 | "repository": {
61 | "type": "git",
62 | "url": "git+https://github.com/TeamJSD/SparQ.git"
63 | },
64 | "keywords": [
65 | "graphql",
66 | "baas",
67 | "sparq"
68 | ],
69 | "bugs": {
70 | "url": "https://github.com/TeamJSD/SparQ/issues"
71 | },
72 | "homepage": "https://github.com/TeamJSD/SparQ#readme"
73 | }
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TeamJSD/SparQ/419b5b72f2b1e937d98ea1542d754464d67165b5/public/favicon.ico
--------------------------------------------------------------------------------
/server.js:
--------------------------------------------------------------------------------
1 | const express = require('express');
2 | const path = require('path');
3 | const bodyParser = require('body-parser');
4 | const graphqlHTTP = require('express-graphql');
5 | const { graphql } = require('graphql');
6 | // const authCtrl = require('./server/controllers/authController.js');
7 | const cors = require('cors');
8 | const cookieParser = require('cookie-parser');
9 |
10 | const setSchema = require('./server/middleware/setSchema');
11 | const devUserCtrl = require('./server/middleware/devUserController');
12 |
13 | const passport = require('passport')
14 | const LocalStrategy = require('passport-local').Strategy;
15 |
16 | import { apolloExpress, graphiqlExpress } from 'apollo-server';
17 |
18 | import GQLSchemaTranspiler from './transpiler/gqlschema_transpiler.js';
19 | import DBTranspiler from './transpiler/db_transpiler.js';
20 |
21 | import devUserSchema from './server/db/sparq_schema.js'
22 | // import gqlTestSchema from './compiler/a1b2c3_schema.js';
23 | require('dotenv').config();
24 |
25 | const app = express();
26 |
27 | app.use(bodyParser.urlencoded({ extended: true }));
28 | app.use(bodyParser.json());
29 | app.use(bodyParser.text());
30 |
31 | app.use(cors())
32 | app.use(express.static(__dirname + '/'));
33 | app.use(cookieParser());
34 |
35 | app.get('/', (req, res) => {
36 | res.sendFile(path.join(__dirname, '/client/index.html'));
37 | })
38 |
39 | app.get('/main.css', (req, res) => {
40 | res.sendFile(path.join(__dirname, '/client/main.css'));
41 | })
42 |
43 | app.post('/signup',
44 | devUserCtrl.createDevUser,
45 | devUserCtrl.createDevUserDb,
46 | (req, res) => {
47 | res.send({ redirectUrl: '/#profile' })
48 | })
49 |
50 | app.post('/login', devUserCtrl.authenticateDevUser, (req, res) => {
51 | res.send({ redirectUrl: '/#profile' })
52 | })
53 |
54 | app.get('/devUserSchema/:devId',
55 | devUserCtrl.getUserSchema, //check to see if user schema exists in db, if not returns null.
56 | (req, res) => {
57 | // let jsonSchemaModel = JSON.parse(req.body.schemaModel);
58 | res.send(req.body.schemaModel);
59 | })
60 | // app.get('/authorize', authCtrl.authGitUser, authCtrl.setCookie, (req, res) => {
61 | // res.redirect('http://localhost:3000/#/profile');
62 | // })
63 |
64 | app.post('/edit',
65 | devUserCtrl.setDevUserSchema, //saves the schema model to devUser DB.
66 | // devUserCtrl.constructScaffold, //constructs scaffold and attaches to req.body
67 | devUserCtrl.buildSequelizeSchema, //builds sequelize file
68 | devUserCtrl.buildGqlSchema, //builds gql file
69 | (req, res) => {
70 | console.log("req.body.tables", req.body.tables);
71 | console.log("hit edit route");
72 | console.log("this is the cookie coming in", req.cookies.devId);
73 | //find proper user
74 |
75 | // console.log("this is the dev id", req.params.devId);
76 | //check cookies to see which user's schema to update
77 | //should call db_compiler
78 | //should call gqlschema_compilter
79 |
80 | res.end();
81 | })
82 |
83 | //works
84 |
85 | // app.use('/graphql/a1b2c3', graphqlHTTP({
86 | // schema: gqlTestSchema,
87 | // graphiql: true
88 | // }))
89 | // works
90 | // app.use('/graphql/', apolloExpress({
91 | // schema: gqlTestSchema,
92 | // }))
93 |
94 | // app.get('/graphql/:devId', setSchema, apolloExpress( req => ({
95 | // schema: req.devSchema
96 | app.use('/graphiql/:devId', graphiqlExpress({
97 | endpointURL: '/graphqlq/r1kMnmfWe'
98 | }))
99 |
100 | app.post('/graphql/:devId',
101 | setSchema, //middleware that grabs gql file and attaches to req body.
102 | // devUserCtrl.devUserQuery,
103 | apolloExpress(function(req) { //apollo middleware to support the routing of devUser queries.
104 | // console.log("req.devSchema", req.devSchema)
105 | //some weird export thing... because we're not using import'
106 | return { schema: req.devSchema.default }
107 | }))
108 |
109 | app.post('/graphqlq/:devId',
110 | setSchema, //middleware that grabs gql file and attaches to req body.
111 | apolloExpress(function(req) { //apollo middleware to support the routing of devUser queries.
112 | // console.log("req.devSchema", req.devSchema)
113 | //some weird export thing... because we're not using import'
114 | return { schema: req.devSchema.default }
115 | }))
116 |
117 | app.post('/createdb', (req, res) => {
118 | // const devDb = req.body;
119 | // console.log("this is the req body", devDb);
120 | // dbController.createDevUserDb(devDb.dbname)
121 | res.end();
122 | })
123 |
124 | //////////this block is to test invoking o the compilers////////////
125 | // import userDefinedSchema from './fixture/postcall_fixture.js';
126 | // console.log('invoking dbcomp', DBTranspiler(userDefinedSchema));
127 | // console.log('invoking gqlcomp', GQLSchemaTranspiler(userDefinedSchema));
128 |
129 | app.listen(process.env.NODE_PORT, () => console.log(`started server at ${process.env.NODE_PORT}`));
--------------------------------------------------------------------------------
/server/controllers/authController.js:
--------------------------------------------------------------------------------
1 | const request = require('request');
2 | const qs = require('querystring');
3 | const Config = require('./../../config.json');
4 | const cookieParser = require('cookie-parser')
5 |
6 | function authUser(req, res, next) {
7 |
8 | console.log(req.body)
9 | next();
10 | }
11 |
12 | function authGitUser(req, res, next) {
13 | console.log(req.query.code)
14 | const redirect = 'http://localhost:3000/authorize';
15 | const code = req.query.code;
16 | const url = 'https://github.com/login/oauth/access_token?client_id=' + Config.id + '&redirect_uri=' + redirect + '&client_secret=' + Config.secret + '&code=' + code + '&scope=user:email'
17 |
18 | request(url, function(err, res, body) {
19 | let obj = qs.parse(body);
20 | console.log(obj);
21 | req.body.access_token = obj.access_token;
22 | next();
23 | })
24 |
25 | }
26 |
27 | function setCookie(req, res, next) {
28 | let cookieID = req.body.access_token;
29 | res.cookie('userID', cookieID, { httpOnly: true });
30 | next();
31 | }
32 |
33 | module.exports = { authUser, authGitUser, setCookie }
--------------------------------------------------------------------------------
/server/controllers/userController.js:
--------------------------------------------------------------------------------
1 | const db =require('./../db');
2 |
3 | const Developer = db.Developer;
4 | const sequelize = db.Conn;
5 |
6 | function addUser(req, res, next) {
7 | Developer.create(req.body[0], err => {
8 | if(err) console.log(err);
9 | });
10 | next();
11 | }
12 |
13 | function assignId(req, res, next) {
14 |
15 | }
16 |
17 | module.exports = { addUser }
--------------------------------------------------------------------------------
/server/db/sparqDb.js:
--------------------------------------------------------------------------------
1 | const Sequelize = require('sequelize');
2 | const faker = require('faker');
3 | const testFixture = require('../../fixture/postcall_fixture.js');
4 | require('dotenv').config();
5 |
6 | let sampleSchemaModel = JSON.stringify(testFixture);
7 | // console.log('this is the sampleSchemaModel:', sampleSchemaModel)
8 |
9 | const Conn = new Sequelize(
10 | process.env.NODE_DBNAME,
11 | null, //replace later with process.env.NODE_DBUSERNAME,
12 | null //replace later with process.env.NODE_DBPASSWORD
13 | , {
14 | dialect: 'postgres', //always postgres
15 | host: process.env.NODE_DBHOST
16 | }
17 | );
18 |
19 | console.log('db conn', process.env.NODE_DBNAME, process.env.NODE_DBUSERNAME, process.env.NODE_DBPASSWORD,
20 | process.env.NODE_DBHOST);
21 |
22 | const DevUser = Conn.define('devUser', {
23 | username: {
24 | type: Sequelize.STRING,
25 | allowNull: false,
26 | unique: true
27 | },
28 | password: {
29 | type: Sequelize.STRING,
30 | allowNull: false
31 | },
32 | devId: {
33 | type: Sequelize.STRING,
34 | allowNull: false
35 | },
36 | dbName: {
37 | type: Sequelize.STRING,
38 | },
39 | dbUsername: {
40 | type: Sequelize.STRING
41 | },
42 | dbPassword: {
43 | type: Sequelize.STRING
44 | },
45 | gqlSchemaPath: {
46 | type: Sequelize.STRING
47 | },
48 | schemaModel: {
49 | type: Sequelize.TEXT
50 | }
51 | });
52 |
53 | // Conn.sync({ force: true })
54 | // .then(() => {
55 | // DevUser.create({
56 | // devId: 'a1b2c3',
57 | // username: 'stevedesk',
58 | // password: '12345',
59 | // dbName: 'test1',
60 | // dbUsername: '',
61 | // dbPassword: '',
62 | // gqlSchemaPath: 'a1b2c3_schema.js',
63 | // schemaModel: 'this: {that: other}'
64 | // })
65 | // DevUser.create({
66 | // devId: 'z1y2x3',
67 | // username: 'jayceman',
68 | // password: 'password',
69 | // dbName: 'test2',
70 | // dbUsername: '',
71 | // dbPassword: '',
72 | // gqlSchemaPath: 'a1b2c3_schema.js',
73 | // schemaModel: '{[()]}'
74 | // })
75 | // DevUser.create({
76 | // devId: 'aabbcc',
77 | // username: 'derrick',
78 | // password: 'a1b2c3',
79 | // dbName: 'test3',
80 | // dbUsername: '',
81 | // dbPassword: '',
82 | // gqlSchemaPath: 'a1b2c3_schema.js',
83 | // schemaModel: '[{}]'
84 | // })
85 | // })
86 | Conn.sync();
87 |
88 | export default Conn;
--------------------------------------------------------------------------------
/server/db/sparq_schema.js:
--------------------------------------------------------------------------------
1 | import {
2 | GraphQLObjectType,
3 | GraphQLInt,
4 | GraphQLString,
5 | GraphQLBoolean,
6 | GraphQLList,
7 | GraphQLSchema,
8 | GraphQLNonNull
9 | } from 'graphql';
10 | import sparqDb from './sparqDb.js';
11 |
12 | const DevUser = new GraphQLObjectType({
13 | name: 'devUser',
14 | description: 'this represents a devUser',
15 | fields: () => {
16 | return {
17 | username: {
18 | type: GraphQLString,
19 | resolve(devUser) {
20 | return devUser.username
21 | }
22 | },
23 | //may need to rethink this...
24 | password: {
25 | type: GraphQLString,
26 | resolve(devUser) {
27 | return devUser.password
28 | }
29 | },
30 | devId: {
31 | type: GraphQLString,
32 | resolve(devUser) {
33 | return devUser.devId
34 | }
35 | },
36 | dbName: {
37 | type: GraphQLString,
38 | resolve(devUser) {
39 | return devUser.dbName
40 | }
41 | },
42 | dbUsername: {
43 | type: GraphQLString,
44 | resolve(devUser) {
45 | return devUser.dbUsername
46 | }
47 | },
48 | dbPassword: {
49 | type: GraphQLString,
50 | resolve(devUser) {
51 | return devUser.dbPassword
52 | }
53 | },
54 | gqlSchemaPath: {
55 | type: GraphQLString,
56 | resolve(devUser) {
57 | return devUser.gqlSchemaPath
58 | }
59 | },
60 | schemaModel: {
61 | type: GraphQLString,
62 | resolve(devUser) {
63 | return devUser.schemaModel
64 | }
65 | }
66 | }
67 | }
68 | })
69 | //defend against stuff in resolve function... like trying to create
70 | //new users...
71 | const Mutation = new GraphQLObjectType({
72 | name: 'Mutation',
73 | description: 'Functions to create stuff',
74 | fields() {
75 | return {
76 | addDevUser: {
77 | type: DevUser,
78 | args: {
79 | username: {
80 | type: new GraphQLNonNull(GraphQLString)
81 | },
82 | password: {
83 | type: new GraphQLNonNull(GraphQLString)
84 | },
85 | devId: {
86 | type: new GraphQLNonNull(GraphQLString)
87 | }
88 | },
89 | resolve(_, args) {
90 | return sparqDb.models.devUser.create({
91 | username: args.username,
92 | password: args.password,
93 | devId: args.devId
94 | })
95 | }
96 | }
97 | }
98 | }
99 | })
100 |
101 | const Query = new GraphQLObjectType({
102 | name: 'Query',
103 | description: 'this is a root query',
104 | fields: () => {
105 | return {
106 | devUser: {
107 | type: new GraphQLList(DevUser),
108 | resolve(root, args) {
109 | return sparqDb.models.devUser.findAll({where: args});
110 | }
111 | }
112 | }
113 | }
114 | })
115 |
116 | const Schema = new GraphQLSchema({
117 | query: Query,
118 | mutation: Mutation
119 | });
120 |
121 | export default Schema;
--------------------------------------------------------------------------------
/server/middleware/createDb.js:
--------------------------------------------------------------------------------
1 | const exec = require('child_process').exec;
2 |
3 |
4 |
5 | const createDevUserDb = function(name) {
6 | console.log("name inside createDB.js", name)
7 | function execCreateDb(name) {
8 | exec(`createdb ${name}`, function (error, stdout, stderr) {
9 | console.log('stdout: ' + stdout);
10 | console.log('stderr: ' + stderr);
11 | if (error !== null) {
12 | console.log('exec error: ' + error);
13 | }
14 | });
15 | }
16 | execCreateDb(name)
17 | }
18 |
19 | module.exports = createDevUserDb;
20 |
21 |
22 |
--------------------------------------------------------------------------------
/server/middleware/devUserController.js:
--------------------------------------------------------------------------------
1 | import sparqDb from './../db/sparqDb';
2 | import createDBFile from './../../transpiler/db_transpiler';
3 | import createGqlSchemaFile from './../../transpiler/gqlschema_transpiler';
4 | const createDevUserDb = require('./createDb');
5 | const shortid = require('shortid');
6 |
7 | //check to see if user already exists... uniqueness
8 | //sessions?
9 | //create id
10 |
11 | const devUserController = {};
12 |
13 | //create devUser in sparDB
14 | devUserController.createDevUser = function(req, res, next) {
15 | console.log("this is the req body in createdevuser", req.body)
16 | const devId = shortid.generate();
17 | console.log("this is the devid generated. it should match below: ", devId)
18 | sparqDb.models.devUser.create({
19 | username: req.body.username,
20 | password: req.body.password,
21 | devId: devId
22 | })
23 | .then(data => {
24 | console.log("user created ");
25 | })
26 | .catch(err => {
27 | console.log("error!", err)
28 | })
29 | req.devId = devId;
30 | res.cookie('devId', devId);
31 | next();
32 | }
33 |
34 | devUserController.createDevUserDb = function(req, res, next) {
35 | console.log("this is the devId inside createdb. the db created should match this:", req.devId)
36 | createDevUserDb(req.devId);
37 | next();
38 | }
39 |
40 | //basic login authentication
41 | devUserController.authenticateDevUser = function(req, res, next) {
42 | const submittedPassword = req.body.password;
43 | const submittedUsername = req.body.username;
44 | sparqDb.models.devUser.findOne({ where: { username: submittedUsername } })
45 | .then((user) => {
46 | if (user.password !== submittedPassword) {
47 | console.log("password was in correct... redirecting")
48 | } else {
49 | console.log("authentication successful");
50 | res.cookie('devId', user.devId)
51 | next();
52 | }
53 | })
54 | .catch((err) => {
55 | console.log("there was an error. Either the user does not exist or some other error");
56 | })
57 | }
58 |
59 | //writes userSchema tables to the DB.
60 | devUserController.setDevUserSchema = function(req, res, next) {
61 | console.log("this is the req.body", req.body)
62 | const devId = req.cookies.devId;
63 | const newScaffold = JSON.stringify(req.body);
64 | sparqDb.models.devUser.findOne({ where: { devId: devId } })
65 | .then((user) => {
66 | user.updateAttributes({
67 | schemaModel: newScaffold
68 | })
69 | next();
70 | })
71 | .catch((err) => {
72 | console.log("there was an error. maybe the user doesnt exist")
73 | })
74 | }
75 |
76 | // devUserController.constructScaffold = function(req, res, next) {
77 | // //create fixture object
78 | // const scaffold = {};
79 | // scaffold.userID = req.cookies.devId;
80 | // scaffold.UserPassword = '';
81 | // //change this
82 | // scaffold.DBName = 'edittest';
83 | // scaffold.tables = req.body.tables;
84 | // req.body.scaffold = scaffold;
85 | // next();
86 | // }
87 |
88 | //creates db file using transpiler from scaffold which was attached to req.body.
89 | devUserController.buildSequelizeSchema = function(req, res, next) {
90 | console.log("this is the req.body", req.body)
91 | const scaffold = req.body;
92 | createDBFile(scaffold);
93 | next();
94 | }
95 |
96 | //creates gql file using transpiler from scaffold which was attached to req.body.
97 | devUserController.buildGqlSchema = function(req, res, next) {
98 | console.log("inside buildGqlSchema");
99 | const scaffold = req.body;
100 | createGqlSchemaFile(scaffold);
101 | next();
102 | }
103 |
104 | //contstructs scaffold and attaches to req.body.
105 |
106 | //queries db for existing userSchema.
107 | devUserController.getUserSchema = function(req, res, next) {
108 | const devId = req.params.devId;
109 | console.log("this is the devId", devId);
110 | sparqDb.models.devUser.findOne({ where: { devId: devId } })
111 | .then(user => {
112 | console.log("got this schema", user.schemaModel)
113 | //may have to JSON.parse?
114 | req.body.schemaModel = user.schemaModel
115 | next();
116 | })
117 |
118 | }
119 |
120 | //trying to support user queries not from graphiql
121 | // devUserController.devUserQuery = function(req, res, next) {
122 | // let GQLQuery = req.body;
123 | // console.log(typeof GQLQuery);
124 |
125 | // req.body = { "query": GQLQuery }
126 | // console.log('req.body', req.body);
127 |
128 | // next();
129 |
130 | // //test mutation
131 | // //mutation steveSucks { addPerson(firstName: "steve23", age: 252, email: "steve2@desk.com"){ id firstName } }
132 | // //test query
133 | // // {person{ firstName age email id }}
134 | // };
135 |
136 | module.exports = devUserController;
--------------------------------------------------------------------------------
/server/middleware/setSchema.js:
--------------------------------------------------------------------------------
1 | const setSchema = function(req, res, next) {
2 | console.log("re.q.params.devId", req.params);
3 | let devSchema = require(`../../devUserGql/${req.params.devId}_schema.js`)
4 | // console.log(devSchema)
5 | req.devSchema = devSchema
6 | next();
7 | }
8 |
9 | module.exports = setSchema;
--------------------------------------------------------------------------------
/transpiler/db_transpiler.js:
--------------------------------------------------------------------------------
1 | import fs from 'fs';
2 | import dbTransMethods from './db_transpiler_methods.js';
3 |
4 | function createDBFile(userDefinedSchema) {
5 | //create db file and append dependency block.
6 | fs.writeFile(__dirname + `/../devUserDbs/${userDefinedSchema.userID}_db.js`, dbTransMethods.createDependenciesblock(userDefinedSchema), (err) => {
7 | if (err) { console.log(err) }
8 | //append connection template block to db file.
9 | fs.appendFile(__dirname + `/../devUserDbs/${userDefinedSchema.userID}_db.js`, dbTransMethods.createConnectionsBlock(userDefinedSchema), (err) => {
10 | if (err) { console.log(err) }
11 | //append schema block to db file.
12 | fs.appendFile(__dirname + `/../devUserDbs/${userDefinedSchema.userID}_db.js`, dbTransMethods.createTablesBlock(userDefinedSchema.tables), (err) => {
13 | if (err) { console.log(err) }
14 | //append relationships if defined by user.
15 | if (userDefinedSchema.hasRelationships) {
16 | fs.appendFile(__dirname + `/../devUserDbs/${userDefinedSchema.userID}_db.js`, userDefinedSchema.relationshipsString + `\nConn.sync({ force: true }).then(function(err) { console.log('It worked!'); }, function (err) { console.log('An error occurred while creating the table:', err); });\nexport default Conn;`, (err) => {
17 | if (err) { console.log(err) };
18 | });
19 | //if no relationships exist.
20 | } else {
21 | fs.appendFile(__dirname + `/../devUserDbs/${userDefinedSchema.userID}_db.js`, `\nConn.sync({ force: true }).then(function(err) { console.log('database created'); }, function (err) { console.log('An error occurred while creating the database:', err); });\nexport default Conn;`, (err) => {
22 | if (err) { console.log(err) };
23 | });
24 | }
25 | });
26 | });
27 | })
28 | };
29 |
30 | export default createDBFile
--------------------------------------------------------------------------------
/transpiler/db_transpiler_methods.js:
--------------------------------------------------------------------------------
1 | let dbTransMethods = {};
2 |
3 | dbTransMethods.createFieldsBlock = function(fieldArr) {
4 | let output = '';
5 | fieldArr.forEach((element, index, array) => {
6 | output = output + `${element.fieldName}: {
7 | type: Sequelize.${element.type},
8 | allowNull: ${!element.required}
9 | },\n`
10 | });
11 | return output
12 | };
13 |
14 | dbTransMethods.createTable = function(table) {
15 | let defineBlock = `const ${table.tableName} = Conn.define('${table.tableName.toLowerCase()}', {\n${this.createFieldsBlock(table.fields)}});\n\n`
16 | return defineBlock;
17 | };
18 |
19 | dbTransMethods.createTablesBlock = function(tables) {
20 | let output = '';
21 | tables.forEach((element, index, array) => {
22 | output = output + this.createTable(element);
23 | });
24 | return output;
25 | };
26 |
27 | dbTransMethods.createDependenciesblock = function(userDefinedSchema) {
28 | return `import Sequelize from 'sequelize';
29 | import _ from 'lodash';\n\n`
30 | };
31 |
32 | dbTransMethods.createConnectionsBlock = function(userDefinedSchema) {
33 | return `const Conn = new Sequelize(
34 | '${userDefinedSchema.userID}', //name of users individual db.
35 | null, //replace later with process.env.NODE_DBUSERNAME,
36 | null //replace later with process.env.NODE_DBPASSWORD
37 | , {
38 | dialect: 'postgres', //always postgres
39 | host: process.env.NODE_DBHOST
40 | }
41 | );\n\n`
42 | };
43 |
44 | export default dbTransMethods;
--------------------------------------------------------------------------------
/transpiler/gqlschema_transpiler.js:
--------------------------------------------------------------------------------
1 | import fs from 'fs';
2 | import _ from 'lodash';
3 | import GQLTransMethods from './gqlschema_transpiler_methods.js';
4 |
5 | //Write to file.
6 | function createSchemaFile(userSchema) {
7 | //create schema file and append dep block.
8 | fs.writeFile(__dirname + `/../devUserGql/${userSchema.userID}_schema.js`, GQLTransMethods.GQLDepBuilder(userSchema.userID), (err) => {
9 | if (err) { console.log(err) }
10 | //create DB schema block and append to file.
11 | fs.appendFile(__dirname + `/../devUserGql/${userSchema.userID}_schema.js`, GQLTransMethods.GQLDBSchema(userSchema), (err) => {
12 | if (err) { console.log(err) }
13 | //create GQL query and append to file.
14 | fs.appendFile(__dirname + `/../devUserGql/${userSchema.userID}_schema.js`, GQLTransMethods.GQLQueryBlock(userSchema), (err) => {
15 | if (err) { console.log(err) }
16 | //create GQL mutation and append to file.
17 | fs.appendFile(__dirname + `/../devUserGql/${userSchema.userID}_schema.js`, `${GQLTransMethods.GQLMutationBlock(userSchema)}\n\n`, (err) => {
18 | if (err) { console.log(err) }
19 | //create export block and append to file.
20 | fs.appendFile(__dirname + `/../devUserGql/${userSchema.userID}_schema.js`, `const Schema = new GraphQLSchema({ query: Query, mutation: Mutation});\nexport default Schema;`, (err) => {
21 | if (err) { console.log(err) }
22 | });
23 | });
24 |
25 | });
26 | });
27 | });
28 | };
29 |
30 | export default createSchemaFile
--------------------------------------------------------------------------------
/transpiler/gqlschema_transpiler_methods.js:
--------------------------------------------------------------------------------
1 | let GQLTransMethods = {};
2 |
3 | //compiles import block in support of GQL dependencies
4 | GQLTransMethods.GQLDepBuilder = function(userID) {
5 | return `import { GraphQLObjectType, GraphQLInt, GraphQLString, GraphQLBoolean, GraphQLList, GraphQLSchema, GraphQLNonNull } from 'graphql'; import Db from './../devUserDbs/${userID}_db.js';\n\n`
6 | };
7 |
8 | //compiles relationships block.
9 | GQLTransMethods.GQLSchemaRelationsBlock = function(rels) {
10 | return ` ${rels.Slave.toLowerCase()}: { type: new GraphQLList(${rels.Slave}), resolve(${rels.Master.toLowerCase()}) { return ${rels.Master.toLowerCase()}.get${rels.Slave}s(); } }`
11 | };
12 |
13 | //compiles schema fields block by invoking prior functions.
14 | GQLTransMethods.GQLSchemaFieldsBlock = function(userSchema, fieldArr, tableName) {
15 | let relationshipFieldBlock = ``;
16 | //invokes relationship function if relationships are necessary.
17 | if (userSchema.hasRelationships) {
18 | userSchema.relationships.forEach((element, index, array) => {
19 | if (tableName === element.Master) {
20 | relationshipFieldBlock = this.GQLSchemaRelationsBlock(element);
21 | }
22 | });
23 | };
24 | //adds id field.
25 | let output = `id: {\ntype: GraphQLInt,\nresolve(${tableName.toLowerCase()}) { \nreturn ${tableName.toLowerCase()}.id; } },`;
26 | let GQLType = {
27 | "STRING": "GraphQLString",
28 | "INTEGER": "GraphQLInt",
29 | "BOOLEAN": "GraphQLBoolean",
30 | };
31 | //adds each field to the block with necessary GQL type.
32 | fieldArr.forEach((element, index, array) => {
33 | output = output + `${element.fieldName}: { type: ${GQLType[element.type]}, resolve(${tableName.toLowerCase()}) { return ${tableName.toLowerCase()}.${element.fieldName}; } },\n`
34 | });
35 | return output + relationshipFieldBlock + `\n`;
36 | };
37 |
38 | GQLTransMethods.GQLSchemaTableBlock = function(userSchema, table) {
39 | let defineBlock = `const ${table.tableName} = new GraphQLObjectType({ name: '${table.tableName}', description: 'This represents a ${table.tableName}', fields: () => { return { ${this.GQLSchemaFieldsBlock(userSchema,table.fields,table.tableName)}} } });\n\n`
40 | return defineBlock;
41 | };
42 |
43 | //combines all schema tables blocks
44 | GQLTransMethods.GQLDBSchema = function(userSchema) {
45 | let output = '';
46 | userSchema.tables.forEach((element, index, array) => {
47 | output = output + this.GQLSchemaTableBlock(userSchema, element);
48 | });
49 | return output;
50 | };
51 |
52 | //compiles fields by traversing all tables.
53 | GQLTransMethods.GQLQueryTablesBlock = function(tables) {
54 | let output = '';
55 | tables.forEach((element, index, array) => {
56 | output = output + `${element.tableName.toLowerCase()}: { type: new GraphQLList(${element.tableName}), resolve(root, args) { return Db.models.${element.tableName.toLowerCase()}.findAll({ where: args }); } },`
57 | });
58 | return output
59 | };
60 |
61 | //combines all the tables and fields blocks.
62 | GQLTransMethods.GQLQueryBlock = function(data) {
63 | let QueryBlock = `const Query = new GraphQLObjectType({ name: 'Query', description: 'this is a root query', fields: () => { return { ${this.GQLQueryTablesBlock(data.tables)} } } });\n\n`;
64 | return QueryBlock
65 | };
66 |
67 | //compiles all argument fields for each mutation if field is indicated as mutable.
68 | GQLTransMethods.GQLMutationArgsFieldBuilder = function(fields, tableName, userSchema, hasRelations) {
69 | let fieldsBlock = ``;
70 | let GQLType = {
71 | "STRING": "GraphQLString",
72 | "INTEGER": "GraphQLInt",
73 | "BOOLEAN": "GraphQLBoolean",
74 | };
75 | if (hasRelations) {
76 | userSchema.relationships.forEach(function(element) {
77 | if (element.Verb === "belongsTo" && element.Master === tableName) {
78 | fieldsBlock += `id: { \ntype: new GraphQLNonNull(GraphQLInt),\n },`
79 | }
80 | });
81 | };
82 | fields.forEach(function(element) {
83 | fieldsBlock += `${element.fieldName}: {\n type: new GraphQLNonNull \n (${GQLType[element.type]}),\n },`
84 | });
85 | return fieldsBlock;
86 | };
87 |
88 | //creates resolver block for each table.
89 | GQLTransMethods.GQLMutationResolverBuilder = function(fields, tableName, userSchema, hasRelations) {
90 | let resolverFields = ``;
91 | if (hasRelations) {
92 | userSchema.relationships.forEach(function(element) {
93 | if (element.Verb === "belongsTo" && element.Master === tableName) {
94 | resolverFields += `${element.Slave.toLowerCase()}Id: args.id,`
95 | }
96 | });
97 | }
98 | fields.forEach(function(element) {
99 | resolverFields += `${element.fieldName}: args.${element.fieldName},`
100 | });
101 | let resolverBlock = `resolve(_, args) {\n return Db.models.${tableName.toLowerCase()}.create({\n ${resolverFields} }); }`;
102 | return resolverBlock;
103 | };
104 |
105 | //combines all mutation blocks in to single block.
106 | GQLTransMethods.GQLMutationBlock = function(userSchema) {
107 | let tables = ``;
108 | userSchema.tables.forEach(function(element) {
109 | tables += `\n add${element.tableName}: { type: ${element.tableName}, args: {\n ${GQLTransMethods.GQLMutationArgsFieldBuilder(element.fields,element.tableName,userSchema,userSchema.hasRelationships)}}, ${GQLTransMethods.GQLMutationResolverBuilder(element.fields,element.tableName,userSchema,userSchema.hasRelationships)}},`
110 |
111 | });
112 | let mutationBlock = `const Mutation = new GraphQLObjectType({\nname: 'Mutation',\ndescription: 'This is a mutation, functions that create things',\nfields() {\nreturn {${tables}}}\n})`
113 | return mutationBlock;
114 | };
115 |
116 | export default GQLTransMethods;
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | entry: "./client/components/app.jsx",
3 | output: {
4 | path: __dirname,
5 | filename: "bundle.js"
6 | },
7 | module: {
8 | loaders: [
9 | { test: /\.css$/, loader: "style!css" },
10 | { test: /\.jpe?g$|\.gif$|\.png$|\.svg$|\.woff$|\.ttf$|\.wav$|\.mp3$/, loader: "url-loader" },
11 | {
12 | test: /\.jsx$/,
13 | loader: 'babel-loader',
14 | exclude: /node_modules/,
15 | query: {
16 | presets: ['es2015', 'react', 'stage-0']
17 | }
18 | }
19 | ]
20 | }
21 | };
--------------------------------------------------------------------------------