├── .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 | ![logo](http://i.imgur.com/pdtR6wo.png) 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 | 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 = 21 | } else { 22 | link = 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 |
35 |
36 |

Not a member?

    37 |

Sign Up.

38 |
39 |
40 | 46 |
47 |
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 |
11 | 12 |
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 |
12 |
13 |
14 | 15 |
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 | 28 | 29 | 33 | 34 | 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 | 20 | 21 | 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 |
45 |
46 |
47 | Table name: 48 | 49 | this.props.handleChange(event, this.props.index, 0)}> 54 |

55 |
56 | 57 | Fields:
58 | 59 | { inputs } 60 | 61 | Has Relationships:

62 | 68 | 69 | 74 | 75 | 81 | 82 | 83 |
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 |
216 | { schemas } 217 | 218 | 219 |
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 | 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 |
30 | 31 | 37 |
38 | 39 | 45 |
46 | 47 | 53 | 54 | 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 | }; --------------------------------------------------------------------------------