├── .gitignore ├── LICENSE ├── README.md ├── config.go ├── db_logic.go ├── db_main.go ├── db_struct.go ├── go.mod ├── go.sum ├── gql_logic.go ├── gql_schema.go ├── gql_struct.go ├── main.go ├── public ├── asset-manifest.json ├── favicon.ico ├── index.html ├── manifest.json ├── precache-manifest.322cc1a0981814470fa95698ad009295.js ├── service-worker.js └── static │ ├── css │ ├── main.e344f020.chunk.css │ └── main.e344f020.chunk.css.map │ └── js │ ├── 2.3cd3ed05.chunk.js │ ├── 2.3cd3ed05.chunk.js.map │ ├── main.ef6f36c7.chunk.js │ ├── main.ef6f36c7.chunk.js.map │ ├── runtime~main.a8a9905a.js │ └── runtime~main.a8a9905a.js.map ├── sec_http.go ├── sec_password.go ├── sec_token.go └── util.go /.gitignore: -------------------------------------------------------------------------------- 1 | # Binaries for programs and plugins 2 | *.exe 3 | *.exe~ 4 | *.dll 5 | *.so 6 | *.dylib 7 | 8 | # Test binary, build with `go test -c` 9 | *.test 10 | 11 | # Output of the go coverage tool, specifically when used with LiteIDE 12 | *.out 13 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Jonathan Hecl 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Golang+GraphQL+MongoDB Server 1.0.0 2 | 3 | Uses the following packages: 4 | - go.mongodb.org/mongo-driver/mongo - MongoDB Driver API 5 | - github.com/graphql-go/graphql - GraphQL 6 | - github.com/dgrijalva/jwt-go - JSON Web Tokens (JWT) 7 | - golang.org/x/crypto/bcrypt - Package bcrypt 8 | 9 | # Features! 10 | 11 | - Authorization Header 12 | - SignUp/SignIn users 13 | - Users Profiles 14 | - List recipes 15 | - Recipe pages 16 | - Add/Edit/Delete recipes 17 | - Like/Unlike recipes 18 | 19 | ### Config.go file 20 | 21 | ``` 22 | var config = configModel{ 23 | mongoUri: "mongodb://admin:admin@localhost:37812/react-recipes", // Mongo Uri 24 | mongoDb: "react-recipes", // DB name 25 | tokenSecret: "secret", // Secret to use in Tokens 26 | tokenExp: "1h", // Expiration of Token 27 | serveUri: ":4444", // Serve 28 | } 29 | ``` 30 | 31 | ### Models 32 | 33 | #### Recipe 34 | 35 | |key|type| 36 | |-|-| 37 | |_id|ID| 38 | |name|string| 39 | |imageUrl|string| 40 | |category|string| 41 | |description|string| 42 | |instructions|string| 43 | |createdDate|unixtime| 44 | |likes|int| 45 | |username|string| 46 | 47 | #### User 48 | 49 | |key|type| 50 | |-|-| 51 | |_id|ID| 52 | |username|string| 53 | |password|string| 54 | |email|string| 55 | |joinDate|unixtime| 56 | |favorites|array[Recipe]| 57 | 58 | ### GraphQL 59 | 60 | #### getAllRecipes 61 | ``` 62 | { 63 | getAllRecipes { 64 | ...MinimalRecipe 65 | } 66 | } 67 | 68 | fragment MinimalRecipe on Recipe { 69 | _id 70 | name 71 | imageUrl 72 | category 73 | } 74 | ``` 75 | 76 | #### searchRecipes 77 | ``` 78 | query ($searchTerm: String) { 79 | searchRecipes(searchTerm: $searchTerm) { 80 | _id 81 | name 82 | likes 83 | } 84 | } 85 | ``` 86 | 87 | #### getRecipe 88 | ``` 89 | query ($_id: ID!) { 90 | getRecipe(_id: $_id) { 91 | ...CompleteRecipe 92 | } 93 | } 94 | 95 | fragment CompleteRecipe on Recipe { 96 | _id 97 | name 98 | imageUrl 99 | category 100 | description 101 | instructions 102 | createdDate 103 | likes 104 | username 105 | } 106 | ``` 107 | 108 | #### signupUser 109 | ``` 110 | mutation ($username: String!, $email: String!, $password: String!) { 111 | signupUser(username: $username, email: $email, password: $password) { 112 | token 113 | } 114 | } 115 | ``` 116 | 117 | #### signinUser 118 | ``` 119 | mutation ($username: String!, $password: String!) { 120 | signinUser(username: $username, password: $password) { 121 | token 122 | } 123 | } 124 | ``` 125 | 126 | #### getCurrentUser (require authorization header) 127 | ``` 128 | { 129 | getCurrentUser { 130 | username 131 | joinDate 132 | email 133 | favorites { 134 | _id 135 | name 136 | } 137 | } 138 | } 139 | ``` 140 | 141 | #### addRecipe (require authorization header) 142 | _username not used, obtained by Token Authorization._ 143 | ``` 144 | mutation ($name: String!, $imageUrl: String!, $category: String!, $description: String!, $instructions: String!, $username: String) { 145 | addRecipe(name: $name, imageUrl: $imageUrl, category: $category, description: $description, instructions: $instructions, username: $username) { 146 | ...MinimalRecipe 147 | } 148 | } 149 | 150 | fragment MinimalRecipe on Recipe { 151 | _id 152 | name 153 | imageUrl 154 | category 155 | } 156 | 157 | ``` 158 | 159 | #### updateUserRecipe (require authorization header) 160 | ``` 161 | mutation ($_id: ID!, $name: String!, $imageUrl: String!, $category: String!, $description: String!, $instructions: String!) { 162 | updateUserRecipe(_id: $_id, name: $name, imageUrl: $imageUrl, category: $category, description: $description, instructions: $instructions) { 163 | ...CompleteRecipe 164 | } 165 | } 166 | 167 | fragment CompleteRecipe on Recipe { 168 | _id 169 | name 170 | imageUrl 171 | category 172 | description 173 | instructions 174 | createdDate 175 | likes 176 | username 177 | } 178 | ``` 179 | 180 | #### getUserRecipe (require authorization header) 181 | ``` 182 | query ($username: String!) { 183 | getUserRecipes(username: $username) { 184 | ...CompleteRecipe 185 | } 186 | } 187 | 188 | fragment CompleteRecipe on Recipe { 189 | _id 190 | name 191 | imageUrl 192 | category 193 | description 194 | instructions 195 | createdDate 196 | likes 197 | username 198 | } 199 | ``` 200 | 201 | #### likeRecipe (require authorization header) 202 | _username not used, obtained by Token Authorization._ 203 | ``` 204 | mutation ($_id: ID!, $username: String!) { 205 | likeRecipe(_id: $_id, username: $username) { 206 | ...LikeRecipe 207 | } 208 | } 209 | 210 | fragment LikeRecipe on Recipe { 211 | _id 212 | likes 213 | } 214 | ``` 215 | 216 | #### unlikeRecipe (require authorization header) 217 | _username not used, obtained by Token Authorization._ 218 | ``` 219 | mutation ($_id: ID!, $username: String!) { 220 | unlikeRecipe(_id: $_id, username: $username) { 221 | ...LikeRecipe 222 | } 223 | } 224 | 225 | fragment LikeRecipe on Recipe { 226 | _id 227 | likes 228 | } 229 | ``` 230 | 231 | #### deleteUserRecipe (require authorization header) 232 | ``` 233 | mutation ($_id: ID!) { 234 | deleteUserRecipe(_id: $_id) { 235 | _id 236 | } 237 | } 238 | ``` 239 | 240 | License 241 | ---- 242 | 243 | MIT 244 | -------------------------------------------------------------------------------- /config.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | type configModel struct { 4 | mongoUri string 5 | mongoDb string 6 | tokenSecret string 7 | tokenExp string 8 | serveUri string 9 | } 10 | 11 | var config = configModel{ 12 | mongoUri: "mongodb://admin:123456@localhost:37812/react-recipes", // Mongo Uri example: mongodb://admin:123456@localhost:37812/react-recipes 13 | mongoDb: "react-recipes", // DB name 14 | tokenSecret: "secret", // Secret to use in Tokens 15 | tokenExp: "1h", // Expiration of Token 16 | serveUri: ":4444", // Serve 17 | } 18 | -------------------------------------------------------------------------------- /db_logic.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "time" 7 | 8 | "go.mongodb.org/mongo-driver/bson" 9 | "go.mongodb.org/mongo-driver/bson/primitive" 10 | "go.mongodb.org/mongo-driver/mongo/options" 11 | ) 12 | 13 | // Queries 14 | 15 | // getAllRecipes 16 | func (db mongoDB) getAllRecipes() (interface{}, error) { 17 | var results []RecipeModel 18 | var err error 19 | 20 | ctx, _ := context.WithTimeout(context.Background(), 30*time.Second) 21 | cur, err := db.recipes.Find(ctx, bson.D{}, options.Find()) 22 | if err != nil { 23 | return nil, err 24 | } 25 | for cur.Next(ctx) { 26 | var elem RecipeModel 27 | err = cur.Decode(&elem) 28 | if err != nil { 29 | return nil, err 30 | } 31 | results = append(results, elem) 32 | } 33 | if err = cur.Err(); err != nil { 34 | return nil, err 35 | } 36 | cur.Close(ctx) 37 | return results, nil 38 | } 39 | 40 | // getRecipe 41 | func (db mongoDB) getRecipe(_id string) (interface{}, error) { 42 | var results RecipeModel 43 | var err error 44 | 45 | id, err := primitive.ObjectIDFromHex(_id) 46 | if err != nil { 47 | return nil, err 48 | } 49 | q := bson.M{"_id": id} 50 | ctx, _ := context.WithTimeout(context.Background(), 30*time.Second) 51 | err = db.recipes.FindOne(ctx, q).Decode(&results) 52 | if err != nil { 53 | return nil, err 54 | } 55 | return results, nil 56 | } 57 | 58 | // searchRecipes 59 | func (db mongoDB) searchRecipes(searchTerm string) (interface{}, error) { 60 | var err error 61 | var results []RecipeModel 62 | 63 | q := bson.M{"$text": bson.M{"$search": searchTerm}} 64 | ctx, _ := context.WithTimeout(context.Background(), 30*time.Second) 65 | cur, err := db.recipes.Find(ctx, q, options.Find()) 66 | if err != nil { 67 | return nil, err 68 | } 69 | for cur.Next(ctx) { 70 | var elem RecipeModel 71 | err := cur.Decode(&elem) 72 | if err != nil { 73 | return nil, err 74 | } 75 | results = append(results, elem) 76 | } 77 | if err := cur.Err(); err != nil { 78 | return nil, err 79 | } 80 | cur.Close(ctx) 81 | return results, nil 82 | } 83 | 84 | // getCurrentUser 85 | func (db mongoDB) getCurrentUser(username string) (interface{}, error) { 86 | var err error 87 | var results UserModel 88 | 89 | q := bson.M{"username": username} 90 | ctx, _ := context.WithTimeout(context.Background(), 30*time.Second) 91 | err = db.users.FindOne(ctx, q).Decode(&results) 92 | if err != nil { 93 | return nil, err 94 | } 95 | var favorites []RecipeModel 96 | for e, _ := range results.Favorites { 97 | var recipe RecipeModel 98 | 99 | _id := results.Favorites[e].(primitive.ObjectID) 100 | q := bson.M{"_id": _id} 101 | if c, _ := db.recipes.CountDocuments(context.Background(), q); c > 0 { 102 | ctx, _ = context.WithTimeout(context.Background(), 30*time.Second) 103 | err := db.recipes.FindOne(ctx, q).Decode(&recipe) 104 | if err != nil { 105 | return nil, err 106 | } 107 | favorites = append(favorites, recipe) 108 | } 109 | } 110 | favi := make([]interface{}, len(favorites)) 111 | for i, fav := range favorites { 112 | favi[i] = fav 113 | } 114 | results.Favorites = favi 115 | return results, nil 116 | } 117 | 118 | // getUserRecipes 119 | func (db mongoDB) getUserRecipes(username string) (interface{}, error) { 120 | var err error 121 | var results []RecipeModel 122 | 123 | q := bson.M{"username": username} 124 | ctx, _ := context.WithTimeout(context.Background(), 30*time.Second) 125 | cur, err := db.recipes.Find(ctx, q, options.Find()) 126 | if err != nil { 127 | return nil, err 128 | } 129 | for cur.Next(ctx) { 130 | var elem RecipeModel 131 | err := cur.Decode(&elem) 132 | if err != nil { 133 | return nil, err 134 | } 135 | results = append(results, elem) 136 | } 137 | if err := cur.Err(); err != nil { 138 | return nil, err 139 | } 140 | cur.Close(ctx) 141 | return results, nil 142 | } 143 | 144 | // Mutations 145 | 146 | // addRecipe 147 | func (db mongoDB) addRecipe(username string, name string, imageUrl string, category string, description string, instructions string) (interface{}, error) { 148 | var err error 149 | var results RecipeModel 150 | 151 | results.ID = primitive.NewObjectID() 152 | results.Name = name 153 | results.ImageUrl = imageUrl 154 | results.Category = category 155 | results.Description = description 156 | results.Instructions = instructions 157 | results.CreatedDate = time.Now() 158 | results.Username = username 159 | ctx, _ := context.WithTimeout(context.Background(), 30*time.Second) 160 | _, err = db.recipes.InsertOne(ctx, results) 161 | if err != nil { 162 | return nil, err 163 | } 164 | return results, nil 165 | } 166 | 167 | // likeRecipe 168 | func (db mongoDB) likeRecipe(_id string, username string) (interface{}, error) { 169 | var err error 170 | var results RecipeModel 171 | 172 | id, err := primitive.ObjectIDFromHex(_id) 173 | if err != nil { 174 | return nil, err 175 | } 176 | q := bson.M{"_id": id} 177 | q2 := bson.M{"$inc": bson.M{"likes": 1}} 178 | ctx, _ := context.WithTimeout(context.Background(), 30*time.Second) 179 | err = db.recipes.FindOneAndUpdate(ctx, q, q2).Decode(&results) 180 | if err != nil { 181 | return nil, err 182 | } 183 | //results.Likes++ 184 | q = bson.M{"username": username} 185 | q2 = bson.M{"$addToSet": bson.M{"favorites": id}} 186 | ctx, _ = context.WithTimeout(context.Background(), 30*time.Second) 187 | err = db.users.FindOneAndUpdate(ctx, q, q2).Err() 188 | if err != nil { 189 | return nil, err 190 | } 191 | return results, nil 192 | } 193 | 194 | // unlikeRecipe 195 | func (db mongoDB) unlikeRecipe(_id string, username string) (interface{}, error) { 196 | var err error 197 | var results RecipeModel 198 | 199 | id, err := primitive.ObjectIDFromHex(_id) 200 | if err != nil { 201 | return nil, err 202 | } 203 | q := bson.M{"_id": id} 204 | q2 := bson.M{"$inc": bson.M{"likes": -1}} 205 | ctx, _ := context.WithTimeout(context.Background(), 30*time.Second) 206 | err = db.recipes.FindOneAndUpdate(ctx, q, q2).Decode(&results) 207 | if err != nil { 208 | return nil, err 209 | } 210 | //results.Likes-- 211 | q = bson.M{"username": username} 212 | q2 = bson.M{"$pull": bson.M{"favorites": id}} 213 | ctx, _ = context.WithTimeout(context.Background(), 30*time.Second) 214 | err = db.users.FindOneAndUpdate(ctx, q, q2).Err() 215 | if err != nil { 216 | return nil, err 217 | } 218 | return results, nil 219 | } 220 | 221 | // deleteUserRecipe 222 | func (db mongoDB) deleteUserRecipe(_id string, user string) (interface{}, error) { 223 | var err error 224 | var results RecipeModel 225 | 226 | id, err := primitive.ObjectIDFromHex(_id) 227 | if err != nil { 228 | return nil, err 229 | } 230 | q := bson.M{"_id": id, "username": user} 231 | ctx, _ := context.WithTimeout(context.Background(), 30*time.Second) 232 | err = db.recipes.FindOneAndDelete(ctx, q).Decode(&results) 233 | if err != nil { 234 | return nil, err 235 | } 236 | q = bson.M{"favorites": id} 237 | ctx, _ = context.WithTimeout(context.Background(), 30*time.Second) 238 | cur, err := db.users.Find(ctx, q, options.Find()) 239 | if err != nil { 240 | return nil, err 241 | } 242 | for cur.Next(ctx) { 243 | var elem UserModel 244 | err := cur.Decode(&elem) 245 | if err != nil { 246 | return nil, err 247 | } 248 | q = bson.M{"username": elem.Username} 249 | q2 := bson.M{"$pull": bson.M{"favorites": id}} 250 | ctx2, _ := context.WithTimeout(context.Background(), 30*time.Second) 251 | err = db.users.FindOneAndUpdate(ctx2, q, q2).Err() 252 | if err != nil { 253 | return nil, err 254 | } 255 | } 256 | if err := cur.Err(); err != nil { 257 | return nil, err 258 | } 259 | cur.Close(ctx) 260 | 261 | return results, nil 262 | } 263 | 264 | // updateUserRecipe 265 | func (db mongoDB) updateUserRecipe(_id string, user string, name string, imageUrl string, category string, description string, instructions string) (interface{}, error) { 266 | var err error 267 | var results RecipeModel 268 | 269 | id, err := primitive.ObjectIDFromHex(_id) 270 | if err != nil { 271 | return nil, err 272 | } 273 | q := bson.M{"_id": id, "username": user} 274 | q2 := bson.M{"$set": bson.M{"name": name, 275 | "imageUrl": imageUrl, 276 | "category": category, 277 | "description": description, 278 | "instructions": instructions, 279 | }} 280 | ctx, _ := context.WithTimeout(context.Background(), 30*time.Second) 281 | err = db.recipes.FindOneAndUpdate(ctx, q, q2).Decode(&results) 282 | if err != nil { 283 | return nil, err 284 | } 285 | results.Name = name 286 | results.ImageUrl = imageUrl 287 | results.Category = category 288 | results.Description = description 289 | results.Instructions = instructions 290 | return results, nil 291 | } 292 | 293 | // signinUser 294 | func (db mongoDB) signinUser(username string, password string) (interface{}, error) { 295 | var err error 296 | var results UserModel 297 | 298 | q := bson.M{"username": username} 299 | ctx, _ := context.WithTimeout(context.Background(), 30*time.Second) 300 | if err = db.users.FindOne(ctx, q).Decode(&results); err != nil { 301 | return nil, fmt.Errorf("User not found.") 302 | } 303 | if err = comparePassword(password, results.Password); err != nil { 304 | return nil, fmt.Errorf("Invalid password.") 305 | } 306 | results.Token, err = createToken(results.Username, results.Email) 307 | return results, nil 308 | } 309 | 310 | // signupUser 311 | func (db mongoDB) signupUser(username string, password string, email string) (interface{}, error) { 312 | var err error 313 | var results UserModel 314 | 315 | q := bson.M{"username": username} 316 | ctx, _ := context.WithTimeout(context.Background(), 30*time.Second) 317 | if err := db.users.FindOne(ctx, q).Decode(&results); err == nil { 318 | return nil, fmt.Errorf("User already exists.") 319 | } 320 | q = bson.M{"email": email} 321 | ctx, _ = context.WithTimeout(context.Background(), 30*time.Second) 322 | if err := db.users.FindOne(ctx, q).Decode(&results); err == nil { 323 | return nil, fmt.Errorf("Email already exists.") 324 | } 325 | pass, err := generatePassword(password) 326 | if err != nil { 327 | return nil, err 328 | } 329 | results.ID = primitive.NewObjectID() 330 | results.Username = username 331 | results.Password = pass 332 | results.Email = email 333 | results.JoinDate = time.Now() 334 | results.Favorites = make([]interface{}, 0) 335 | ctx, _ = context.WithTimeout(context.Background(), 30*time.Second) 336 | _, err = db.users.InsertOne(ctx, results) 337 | if err != nil { 338 | return nil, err 339 | } 340 | results.Token, err = createToken(results.Username, results.Email) 341 | return results, nil 342 | } 343 | -------------------------------------------------------------------------------- /db_main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "log" 6 | 7 | "go.mongodb.org/mongo-driver/mongo" 8 | "go.mongodb.org/mongo-driver/mongo/options" 9 | ) 10 | 11 | type mongoDB struct { 12 | session *mongo.Client 13 | users *mongo.Collection 14 | recipes *mongo.Collection 15 | } 16 | 17 | // Connect to MongoDB 18 | func connectDB() mongoDB { 19 | client, err := mongo.Connect(context.Background(), options.Client().ApplyURI(config.mongoUri)) 20 | if err != nil { 21 | log.Fatal(err) 22 | } 23 | err = client.Ping(context.Background(), nil) 24 | if err != nil { 25 | log.Fatal(err) 26 | } 27 | return mongoDB{ 28 | session: client, 29 | recipes: client.Database(config.mongoDb).Collection("recipes"), 30 | users: client.Database(config.mongoDb).Collection("users"), 31 | } 32 | } 33 | 34 | // Disconnect to MongoDB 35 | func (db mongoDB) closeDB() { 36 | err := db.session.Disconnect(context.Background()) 37 | if err != nil { 38 | log.Fatal(err) 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /db_struct.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "time" 5 | 6 | "go.mongodb.org/mongo-driver/bson/primitive" 7 | ) 8 | 9 | // RecipeModel struct 10 | type RecipeModel struct { 11 | ID primitive.ObjectID `bson:"_id,omitempty" json:"_id,omitempty"` 12 | Name string `bson:"name" json:"name,omitempty"` 13 | ImageUrl string `bson:"imageUrl" json:"imageUrl,omitempty"` 14 | Category string `bson:"category" json:"category,omitempty"` 15 | Description string `bson:"description" json:"description,omitempty"` 16 | Instructions string `bson:"instructions" json:"instructions,omitempty"` 17 | CreatedDate time.Time `bson:"createdDate,omitempty" json:"createdDate,omitempty"` 18 | Likes int `bson:"likes,omitempty" json:"likes,omitempty"` 19 | Username string `bson:"username,omitempty" json:"username,omitempty"` 20 | } 21 | 22 | // UserModel struct 23 | type UserModel struct { 24 | ID primitive.ObjectID `bson:"_id" json:"_id,omitempty"` 25 | Username string `bson:"username" json:"username,omitempty"` 26 | Password string `bson:"password" json:"password,omitempty"` 27 | Email string `bson:"email" json:"email,omitempty"` 28 | JoinDate time.Time `bson:"joinDate" json:"joinDate,omitempty"` 29 | Favorites []interface{} `bson:"favorites" json:"favorites,omitempty" model:"RecipeModel"` 30 | Token string `json:"token,omitempty"` // graphql only 31 | } 32 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module MGG 2 | 3 | go 1.12 4 | 5 | require ( 6 | github.com/dgrijalva/jwt-go v3.2.0+incompatible 7 | github.com/go-stack/stack v1.8.0 // indirect 8 | github.com/golang/snappy v0.0.1 // indirect 9 | github.com/google/go-cmp v0.2.0 // indirect 10 | github.com/graphql-go/graphql v0.7.8 11 | github.com/graphql-go/handler v0.2.3 12 | github.com/stretchr/testify v1.3.0 // indirect 13 | github.com/tidwall/pretty v0.0.0-20190325153808-1166b9ac2b65 // indirect 14 | github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c // indirect 15 | github.com/xdg/stringprep v1.0.0 // indirect 16 | go.mongodb.org/mongo-driver v1.0.0 17 | golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c 18 | golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6 // indirect 19 | golang.org/x/text v0.3.0 // indirect 20 | ) 21 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= 2 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 3 | github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= 4 | github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= 5 | github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= 6 | github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= 7 | github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4= 8 | github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= 9 | github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ= 10 | github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= 11 | github.com/graphql-go/graphql v0.7.8 h1:769CR/2JNAhLG9+aa8pfLkKdR0H+r5lsQqling5WwpU= 12 | github.com/graphql-go/graphql v0.7.8/go.mod h1:k6yrAYQaSP59DC5UVxbgxESlmVyojThKdORUqGDGmrI= 13 | github.com/graphql-go/handler v0.2.3 h1:CANh8WPnl5M9uA25c2GBhPqJhE53Fg0Iue/fRNla71E= 14 | github.com/graphql-go/handler v0.2.3/go.mod h1:leLF6RpV5uZMN1CdImAxuiayrYYhOk33bZciaUGaXeU= 15 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 16 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 17 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 18 | github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= 19 | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= 20 | github.com/tidwall/pretty v0.0.0-20190325153808-1166b9ac2b65 h1:rQ229MBgvW68s1/g6f1/63TgYwYxfF4E+bi/KC19P8g= 21 | github.com/tidwall/pretty v0.0.0-20190325153808-1166b9ac2b65/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= 22 | github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c h1:u40Z8hqBAAQyv+vATcGgV0YCnDjqSL7/q/JyPhhJSPk= 23 | github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I= 24 | github.com/xdg/stringprep v1.0.0 h1:d9X0esnoa3dFsV0FG35rAT0RIhYFlPq7MiP+DW89La0= 25 | github.com/xdg/stringprep v1.0.0/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y= 26 | go.mongodb.org/mongo-driver v1.0.0 h1:KxPRDyfB2xXnDE2My8acoOWBQkfv3tz0SaWTRZjJR0c= 27 | go.mongodb.org/mongo-driver v1.0.0/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= 28 | golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c h1:Vj5n4GlwjmQteupaxJ9+0FNOmBrHfq7vN4btdGoDZgI= 29 | golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 30 | golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6 h1:bjcUS9ztw9kFmmIxJInhon/0Is3p+EHBKNgquIzo1OI= 31 | golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 32 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 33 | golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= 34 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 35 | -------------------------------------------------------------------------------- /gql_logic.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/graphql-go/graphql" 5 | ) 6 | 7 | // Queries 8 | 9 | // getAllRecipes 10 | func getAllRecipes(_ graphql.ResolveParams) (interface{}, error) { 11 | var err error 12 | var results interface{} 13 | 14 | results, err = db.getAllRecipes() 15 | if err != nil { 16 | return nil, err 17 | } 18 | return results, nil 19 | } 20 | 21 | // getRecipe 22 | func getRecipe(p graphql.ResolveParams) (interface{}, error) { 23 | var err error 24 | var results interface{} 25 | 26 | id := p.Args["_id"].(string) 27 | if err := isRequired(map[string]string{ 28 | "_id": id}); err != nil { 29 | return nil, err 30 | } 31 | results, err = db.getRecipe(id) 32 | if err != nil { 33 | return nil, err 34 | } 35 | return results, nil 36 | } 37 | 38 | // searchRecipes 39 | func searchRecipes(p graphql.ResolveParams) (interface{}, error) { 40 | var err error 41 | var results interface{} 42 | 43 | searchTerm := p.Args["searchTerm"].(string) 44 | results, err = db.searchRecipes(searchTerm) 45 | if err != nil { 46 | return nil, err 47 | } 48 | return results, nil 49 | } 50 | 51 | // getCurrentUser 52 | func getCurrentUser(p graphql.ResolveParams) (interface{}, error) { 53 | var err error 54 | var results interface{} 55 | 56 | user := p.Context.Value("username").(string) 57 | if len(user) == 0 { 58 | return nil, nil 59 | } 60 | results, err = db.getCurrentUser(user) 61 | if err != nil { 62 | return results, err 63 | } 64 | return results, nil 65 | } 66 | 67 | // getUserRecipes 68 | func getUserRecipes(p graphql.ResolveParams) (interface{}, error) { 69 | var err error 70 | var results interface{} 71 | 72 | user := p.Args["username"].(string) 73 | if err := isRequired(map[string]string{ 74 | "username": user}); err != nil { 75 | return nil, err 76 | } 77 | results, err = db.getUserRecipes(user) 78 | if err != nil { 79 | return nil, err 80 | } 81 | return results, nil 82 | } 83 | 84 | // Mutations 85 | 86 | // addRecipe 87 | func addRecipe(p graphql.ResolveParams) (interface{}, error) { 88 | var err error 89 | var results interface{} 90 | 91 | user := p.Context.Value("username").(string) // Obtained by Token Authorization 92 | name := p.Args["name"].(string) 93 | imageUrl := p.Args["imageUrl"].(string) 94 | category := p.Args["category"].(string) 95 | description := p.Args["description"].(string) 96 | instructions := p.Args["instructions"].(string) 97 | if err := isRequired(map[string]string{ 98 | "session": user, 99 | "name": name, 100 | "imageUrl": imageUrl, 101 | "category": category, 102 | "description": description, 103 | "instructions": instructions}); err != nil { 104 | return nil, err 105 | } 106 | results, err = db.addRecipe(user, name, imageUrl, category, description, instructions) 107 | if err != nil { 108 | return nil, err 109 | } 110 | return results, nil 111 | } 112 | 113 | // likeRecipe 114 | func likeRecipe(p graphql.ResolveParams) (interface{}, error) { 115 | var err error 116 | var results interface{} 117 | 118 | user := p.Context.Value("username").(string) // Obtained by Token Authorization 119 | id := p.Args["_id"].(string) 120 | if err := isRequired(map[string]string{ 121 | "session": user, 122 | "ID": id}); err != nil { 123 | return nil, err 124 | } 125 | results, err = db.likeRecipe(id, user) 126 | if err != nil { 127 | return nil, err 128 | } 129 | return results, nil 130 | } 131 | 132 | // unlikeRecipe 133 | func unlikeRecipe(p graphql.ResolveParams) (interface{}, error) { 134 | var err error 135 | var results interface{} 136 | 137 | user := p.Context.Value("username").(string) // Obtained by Token Authorization 138 | id := p.Args["_id"].(string) 139 | if err := isRequired(map[string]string{ 140 | "session": user, 141 | "ID": id}); err != nil { 142 | return nil, err 143 | } 144 | results, err = db.unlikeRecipe(id, user) 145 | if err != nil { 146 | return nil, err 147 | } 148 | return results, nil 149 | } 150 | 151 | // deleteUserRecipe 152 | func deleteUserRecipe(p graphql.ResolveParams) (interface{}, error) { 153 | var err error 154 | var results interface{} 155 | 156 | user := p.Context.Value("username").(string) // Obtained by Token Authorization 157 | id := p.Args["_id"].(string) 158 | if err := isRequired(map[string]string{ 159 | "session": user, 160 | "ID": id}); err != nil { 161 | return nil, err 162 | } 163 | results, err = db.deleteUserRecipe(id, user) 164 | if err != nil { 165 | return nil, err 166 | } 167 | return results, nil 168 | } 169 | 170 | // updateUserRecipe 171 | func updateUserRecipe(p graphql.ResolveParams) (interface{}, error) { 172 | var err error 173 | var results interface{} 174 | 175 | user := p.Context.Value("username").(string) // Obtained by Token Authorization 176 | id := p.Args["_id"].(string) 177 | name := p.Args["name"].(string) 178 | imageUrl := p.Args["imageUrl"].(string) 179 | category := p.Args["category"].(string) 180 | description := p.Args["description"].(string) 181 | instructions := p.Args["instructions"].(string) 182 | if err := isRequired(map[string]string{ 183 | "session": user, 184 | "ID": id, 185 | "name": name, 186 | "imageUrl": imageUrl, 187 | "category": category, 188 | "description": description, 189 | "instructions": instructions}); err != nil { 190 | return nil, err 191 | } 192 | results, err = db.updateUserRecipe(id, user, name, imageUrl, category, description, instructions) 193 | if err != nil { 194 | return nil, err 195 | } 196 | return results, nil 197 | } 198 | 199 | // signinUser 200 | func signinUser(p graphql.ResolveParams) (interface{}, error) { 201 | var err error 202 | var results interface{} 203 | 204 | user := p.Args["username"].(string) 205 | pass := p.Args["password"].(string) 206 | if err := isRequired(map[string]string{ 207 | "username": user, 208 | "password": pass}); err != nil { 209 | return nil, err 210 | } 211 | results, err = db.signinUser(user, pass) 212 | if err != nil { 213 | return nil, err 214 | } 215 | return results, nil 216 | } 217 | 218 | // signupUser 219 | func signupUser(p graphql.ResolveParams) (interface{}, error) { 220 | var err error 221 | var results interface{} 222 | 223 | user := p.Args["username"].(string) 224 | pass := p.Args["password"].(string) 225 | email := p.Args["email"].(string) 226 | if err := isRequired(map[string]string{ 227 | "username": user, 228 | "password": pass, 229 | "email": email, 230 | }); err != nil { 231 | return nil, err 232 | } 233 | results, err = db.signupUser(user, pass, email) 234 | if err != nil { 235 | return nil, err 236 | } 237 | return results, nil 238 | } 239 | -------------------------------------------------------------------------------- /gql_schema.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "log" 5 | 6 | "github.com/graphql-go/graphql" 7 | ) 8 | 9 | // Init the schema of GraphQL 10 | func initSchema() graphql.Schema { 11 | graphqlSchema, err := graphql.NewSchema(graphql.SchemaConfig{ 12 | Query: graphql.NewObject(graphql.ObjectConfig{ 13 | Name: "Query", 14 | Fields: graphql.Fields{ 15 | "getAllRecipes": &graphql.Field{ 16 | Type: graphql.NewList(RecipeType), 17 | Args: graphql.FieldConfigArgument{}, 18 | Resolve: getAllRecipes, 19 | }, 20 | "getRecipe": &graphql.Field{ 21 | Type: RecipeType, 22 | Args: graphql.FieldConfigArgument{ 23 | "_id": &graphql.ArgumentConfig{ 24 | Type: graphql.NewNonNull(ID), 25 | }}, 26 | Resolve: getRecipe, 27 | }, 28 | "searchRecipes": &graphql.Field{ 29 | Type: graphql.NewList(RecipeType), 30 | Args: graphql.FieldConfigArgument{ 31 | "searchTerm": &graphql.ArgumentConfig{ 32 | Type: graphql.String, 33 | }}, 34 | Resolve: searchRecipes, 35 | }, 36 | "getCurrentUser": &graphql.Field{ 37 | Type: UserType, 38 | Args: graphql.FieldConfigArgument{}, 39 | Resolve: getCurrentUser, 40 | }, 41 | "getUserRecipes": &graphql.Field{ 42 | Type: graphql.NewList(RecipeType), 43 | Args: graphql.FieldConfigArgument{ 44 | "username": &graphql.ArgumentConfig{ 45 | Type: graphql.NewNonNull(graphql.String), 46 | }}, 47 | Resolve: getUserRecipes, 48 | }, 49 | }, 50 | }), 51 | Mutation: graphql.NewObject(graphql.ObjectConfig{ 52 | Name: "Mutation", 53 | Fields: graphql.Fields{ 54 | "addRecipe": &graphql.Field{ 55 | Type: RecipeType, 56 | Args: graphql.FieldConfigArgument{ 57 | "name": &graphql.ArgumentConfig{ 58 | Type: graphql.NewNonNull(graphql.String), 59 | }, 60 | "imageUrl": &graphql.ArgumentConfig{ 61 | Type: graphql.NewNonNull(graphql.String), 62 | }, 63 | "category": &graphql.ArgumentConfig{ 64 | Type: graphql.NewNonNull(graphql.String), 65 | }, 66 | "description": &graphql.ArgumentConfig{ 67 | Type: graphql.NewNonNull(graphql.String), 68 | }, 69 | "instructions": &graphql.ArgumentConfig{ 70 | Type: graphql.NewNonNull(graphql.String), 71 | }, 72 | "username": &graphql.ArgumentConfig{ 73 | Type: graphql.String, 74 | }}, 75 | Resolve: addRecipe, 76 | }, 77 | "likeRecipe": &graphql.Field{ 78 | Type: RecipeType, 79 | Args: graphql.FieldConfigArgument{ 80 | "_id": &graphql.ArgumentConfig{ 81 | Type: graphql.NewNonNull(ID), 82 | }, 83 | "username": &graphql.ArgumentConfig{ 84 | Type: graphql.NewNonNull(graphql.String), 85 | }}, 86 | Resolve: likeRecipe, 87 | }, 88 | "unlikeRecipe": &graphql.Field{ 89 | Type: RecipeType, 90 | Args: graphql.FieldConfigArgument{ 91 | "_id": &graphql.ArgumentConfig{ 92 | Type: graphql.NewNonNull(ID), 93 | }, 94 | "username": &graphql.ArgumentConfig{ 95 | Type: graphql.NewNonNull(graphql.String), 96 | }}, 97 | Resolve: unlikeRecipe, 98 | }, 99 | "deleteUserRecipe": &graphql.Field{ 100 | Type: RecipeType, 101 | Args: graphql.FieldConfigArgument{ 102 | "_id": &graphql.ArgumentConfig{ 103 | Type: graphql.NewNonNull(ID), 104 | }}, 105 | Resolve: deleteUserRecipe, 106 | }, 107 | "updateUserRecipe": &graphql.Field{ 108 | Type: RecipeType, 109 | Args: graphql.FieldConfigArgument{ 110 | "_id": &graphql.ArgumentConfig{ 111 | Type: graphql.NewNonNull(ID), 112 | }, 113 | "name": &graphql.ArgumentConfig{ 114 | Type: graphql.NewNonNull(graphql.String), 115 | }, 116 | "imageUrl": &graphql.ArgumentConfig{ 117 | Type: graphql.NewNonNull(graphql.String), 118 | }, 119 | "category": &graphql.ArgumentConfig{ 120 | Type: graphql.NewNonNull(graphql.String), 121 | }, 122 | "description": &graphql.ArgumentConfig{ 123 | Type: graphql.NewNonNull(graphql.String), 124 | }, 125 | "instructions": &graphql.ArgumentConfig{ 126 | Type: graphql.NewNonNull(graphql.String), 127 | }}, 128 | Resolve: updateUserRecipe, 129 | }, 130 | "signinUser": &graphql.Field{ 131 | Type: UserType, 132 | Args: graphql.FieldConfigArgument{ 133 | "username": &graphql.ArgumentConfig{ 134 | Type: graphql.NewNonNull(graphql.String), 135 | }, 136 | "password": &graphql.ArgumentConfig{ 137 | Type: graphql.NewNonNull(graphql.String), 138 | }}, 139 | Resolve: signinUser, 140 | }, 141 | "signupUser": &graphql.Field{ 142 | Type: UserType, 143 | Args: graphql.FieldConfigArgument{ 144 | "username": &graphql.ArgumentConfig{ 145 | Type: graphql.NewNonNull(graphql.String), 146 | }, 147 | "password": &graphql.ArgumentConfig{ 148 | Type: graphql.NewNonNull(graphql.String), 149 | }, 150 | "email": &graphql.ArgumentConfig{ 151 | Type: graphql.NewNonNull(graphql.String), 152 | }}, 153 | Resolve: signupUser, 154 | }, 155 | }, 156 | }), 157 | Types: []graphql.Type{ID}, 158 | }) 159 | if err != nil { 160 | log.Fatal(err) 161 | } 162 | return graphqlSchema 163 | 164 | } 165 | -------------------------------------------------------------------------------- /gql_struct.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "errors" 5 | "log" 6 | 7 | "github.com/graphql-go/graphql" 8 | "github.com/graphql-go/graphql/language/ast" 9 | "github.com/graphql-go/graphql/language/kinds" 10 | ) 11 | 12 | // _validate for ID support 13 | func _validate(value string) error { 14 | if len(value) < 3 { 15 | return errors.New("The minimum length required is 3") 16 | } 17 | return nil 18 | } 19 | 20 | // ID support 21 | var ID = graphql.NewScalar(graphql.ScalarConfig{ 22 | Name: "ID", 23 | Description: "The `id` scalar type represents a ID Object.", 24 | Serialize: func(value interface{}) interface{} { 25 | return value 26 | }, 27 | ParseValue: func(value interface{}) interface{} { 28 | var err error 29 | switch value.(type) { 30 | case string: 31 | err = _validate(value.(string)) 32 | default: 33 | err = errors.New("Must be of type string.") 34 | } 35 | if err != nil { 36 | log.Fatal(err) 37 | } 38 | return value 39 | }, 40 | ParseLiteral: func(valueAst ast.Value) interface{} { 41 | if valueAst.GetKind() == kinds.StringValue { 42 | err := _validate(valueAst.GetValue().(string)) 43 | if err != nil { 44 | log.Fatal(err) 45 | } 46 | return valueAst 47 | } else { 48 | log.Fatal("Must be of type string.") 49 | return nil 50 | } 51 | }, 52 | }) 53 | 54 | // RecipeType 55 | var RecipeType = graphql.NewObject(graphql.ObjectConfig{ 56 | Name: "Recipe", 57 | Fields: graphql.Fields{ 58 | "_id": &graphql.Field{ 59 | Type: ID, 60 | }, 61 | "name": &graphql.Field{ 62 | Type: graphql.String, 63 | }, 64 | "imageUrl": &graphql.Field{ 65 | Type: graphql.String, 66 | }, 67 | "category": &graphql.Field{ 68 | Type: graphql.String, 69 | }, 70 | "description": &graphql.Field{ 71 | Type: graphql.String, 72 | }, 73 | "instructions": &graphql.Field{ 74 | Type: graphql.String, 75 | }, 76 | "createdDate": &graphql.Field{ 77 | Type: graphql.String, 78 | }, 79 | "likes": &graphql.Field{ 80 | Type: graphql.Int, 81 | }, 82 | "username": &graphql.Field{ 83 | Type: graphql.String, 84 | }, 85 | }, 86 | }) 87 | 88 | // UserType 89 | var UserType = graphql.NewObject(graphql.ObjectConfig{ 90 | Name: "User", 91 | Fields: graphql.Fields{ 92 | "_id": &graphql.Field{ 93 | Type: ID, 94 | }, 95 | "username": &graphql.Field{ 96 | Type: graphql.String, 97 | }, 98 | "password": &graphql.Field{ 99 | Type: graphql.String, 100 | }, 101 | "email": &graphql.Field{ 102 | Type: graphql.String, 103 | }, 104 | "joinDate": &graphql.Field{ 105 | Type: graphql.String, 106 | }, 107 | "favorites": &graphql.Field{ 108 | Type: graphql.NewList(RecipeType), 109 | }, 110 | "token": &graphql.Field{ // graphql only 111 | Type: graphql.String, 112 | }, 113 | }, 114 | }) 115 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "net/http" 7 | 8 | "github.com/graphql-go/handler" 9 | ) 10 | 11 | var db mongoDB 12 | 13 | func main() { 14 | fmt.Println("Golang+GraphQL+MongoDB Server v1.0.0") 15 | 16 | // MongoDB 17 | db = connectDB() 18 | defer db.closeDB() 19 | 20 | // GraphQL 21 | schema := initSchema() 22 | h := handler.New(&handler.Config{ 23 | Schema: &schema, 24 | Pretty: true, 25 | GraphiQL: true, // GraphiQL interface 26 | }) 27 | 28 | // Serve 29 | http.Handle("/", http.FileServer(http.Dir("./public"))) // Serve the frontend in /public 30 | http.Handle("/graphql", disableCors(headerAuthorization(h))) 31 | err := http.ListenAndServe(config.serveUri, nil) 32 | if err != nil { 33 | log.Fatal("ListenAndServe: ", err) 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /public/asset-manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "main.css": "/static/css/main.e344f020.chunk.css", 3 | "main.js": "/static/js/main.ef6f36c7.chunk.js", 4 | "main.js.map": "/static/js/main.ef6f36c7.chunk.js.map", 5 | "runtime~main.js": "/static/js/runtime~main.a8a9905a.js", 6 | "runtime~main.js.map": "/static/js/runtime~main.a8a9905a.js.map", 7 | "static/js/2.3cd3ed05.chunk.js": "/static/js/2.3cd3ed05.chunk.js", 8 | "static/js/2.3cd3ed05.chunk.js.map": "/static/js/2.3cd3ed05.chunk.js.map", 9 | "index.html": "/index.html", 10 | "precache-manifest.322cc1a0981814470fa95698ad009295.js": "/precache-manifest.322cc1a0981814470fa95698ad009295.js", 11 | "service-worker.js": "/service-worker.js", 12 | "static/css/main.e344f020.chunk.css.map": "/static/css/main.e344f020.chunk.css.map" 13 | } -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonathanhecl/golang-graphql-mongodb/881bce86d92e9a69b4018512f0e6aecd4e55944c/public/favicon.ico -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | React App
Jonathan Hecl was here!
-------------------------------------------------------------------------------- /public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | } 10 | ], 11 | "start_url": ".", 12 | "display": "standalone", 13 | "theme_color": "#000000", 14 | "background_color": "#ffffff" 15 | } 16 | -------------------------------------------------------------------------------- /public/precache-manifest.322cc1a0981814470fa95698ad009295.js: -------------------------------------------------------------------------------- 1 | self.__precacheManifest = [ 2 | { 3 | "revision": "42ac5946195a7306e2a5", 4 | "url": "/static/js/runtime~main.a8a9905a.js" 5 | }, 6 | { 7 | "revision": "2b45352816a04acb534c", 8 | "url": "/static/js/main.ef6f36c7.chunk.js" 9 | }, 10 | { 11 | "revision": "c9934e8f8ddb7edec47a", 12 | "url": "/static/js/2.3cd3ed05.chunk.js" 13 | }, 14 | { 15 | "revision": "2b45352816a04acb534c", 16 | "url": "/static/css/main.e344f020.chunk.css" 17 | }, 18 | { 19 | "revision": "06c8a5df0b6f57b6c1768c28411f9e89", 20 | "url": "/index.html" 21 | } 22 | ]; -------------------------------------------------------------------------------- /public/service-worker.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Welcome to your Workbox-powered service worker! 3 | * 4 | * You'll need to register this file in your web app and you should 5 | * disable HTTP caching for this file too. 6 | * See https://goo.gl/nhQhGp 7 | * 8 | * The rest of the code is auto-generated. Please don't update this file 9 | * directly; instead, make changes to your Workbox build configuration 10 | * and re-run your build process. 11 | * See https://goo.gl/2aRDsh 12 | */ 13 | 14 | importScripts("https://storage.googleapis.com/workbox-cdn/releases/3.6.3/workbox-sw.js"); 15 | 16 | importScripts( 17 | "/precache-manifest.322cc1a0981814470fa95698ad009295.js" 18 | ); 19 | 20 | workbox.clientsClaim(); 21 | 22 | /** 23 | * The workboxSW.precacheAndRoute() method efficiently caches and responds to 24 | * requests for URLs in the manifest. 25 | * See https://goo.gl/S9QRab 26 | */ 27 | self.__precacheManifest = [].concat(self.__precacheManifest || []); 28 | workbox.precaching.suppressWarnings(); 29 | workbox.precaching.precacheAndRoute(self.__precacheManifest, {}); 30 | 31 | workbox.routing.registerNavigationRoute("/index.html", { 32 | 33 | blacklist: [/^\/_/,/\/[^\/]+\.[^\/]+$/], 34 | }); 35 | -------------------------------------------------------------------------------- /public/static/css/main.e344f020.chunk.css: -------------------------------------------------------------------------------- 1 | body{margin:0;padding:0;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}code{font-family:source-code-pro,Menlo,Monaco,Consolas,Courier New,monospace}.App,nav{text-align:center}nav{padding-bottom:.2em;padding-top:2em;background-color:#efefef;box-shadow:-3px 3px 10px 0 hsla(0,0%,65.9%,.7)}nav ul{display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;-webkit-justify-content:space-evenly;justify-content:space-evenly;-webkit-flex-wrap:wrap;flex-wrap:wrap}li,p{font-size:2rem}ul{list-style:none}input,select,textarea{padding:.4em .2em;font-size:2rem}nav a,nav a:link{text-decoration:none;font-size:2.5rem;font-weight:100}.active{font-weight:700}.form{display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center;-webkit-flex-direction:column;flex-direction:column}.delete-button{color:red;cursor:pointer}.main-title{padding:.5em;color:#1eaedb;margin:0;-webkit-text-decoration-line:underline;text-decoration-line:underline;-webkit-text-decoration-style:dotted;text-decoration-style:dotted}.cards{display:grid;margin:1.5em 3em;grid-template-columns:repeat(auto-fit,minmax(250px,1fr));grid-auto-rows:150px;grid-auto-flow:row dense;grid-gap:2em;grid-auto-rows:300px}.card{position:relative;display:-webkit-flex;display:flex;-webkit-flex-direction:column;flex-direction:column;-webkit-justify-content:flex-end;justify-content:flex-end;box-shadow:-3px 3px 10px 0 hsla(0,0%,65.9%,.4);text-align:center;background:#ddd;transition:all .3s}.card:hover{-webkit-transform:scale(1.05);transform:scale(1.05)}.card:after{content:"";position:absolute;width:100%;height:100%;background-color:#000;opacity:.25;transition:opacity .3s ease-in-out}.card:hover:after{opacity:0}.card-text{position:relative;z-index:1;color:#272525;background:#f5f5f5;letter-spacing:1px}.card-text a{text-decoration:none}.card-text h4{margin:0;padding:.2em}.Lunch{background:#24c6dc;background:linear-gradient(90deg,#514a9d,#24c6dc)}.Lunch,.Snack{width:20%;margin:20px;z-index:1;padding:7px;border-radius:5px;color:#fff}.Snack{background:#50c9c3;background:linear-gradient(90deg,#50928f,#026964)}.Breakfast{width:100px;background:#9d50bb}.Breakfast,.Dinner{margin:20px;z-index:1;color:#fff;padding:7px;border-radius:50px 120px 120px}.Dinner{width:20%;background:linear-gradient(90deg,#b24592,#f15f79)}.recipe-image,.recipe-image:after{height:60vh;width:100%}.recipe-image:after{content:"";position:absolute;opacity:.25;transition:opacity .3s ease-in-out}.recipe{text-align:center;background:#f5f5f5;padding:1em}.recipe h1{font-size:2.5rem;text-align:center}.recipe-header{overflow:hidden;background-image:url(https://bit.ly/2JqRbuI)}.recipe-header>p{margin:0}.recipe-description{font-size:2rem;color:#2f4f4f;padding:1em;font-weight:200;background:#fff;box-shadow:2px 2px 2px 2px rgba(0,0,0,.2);font-style:italic}.recipe-name{color:#1eaedb;text-decoration:underline;-webkit-text-decoration-style:wavy;text-decoration-style:wavy}.recipe-instructions{text-align:left;padding:0 2em}.recipe-instructions *{padding-bottom:.5em}.recipe-instructions__title{font-weight:200;letter-spacing:2px;color:#1eaedb;text-decoration:underline}.like-button{position:fixed;right:1em;bottom:1em;font-size:2rem;background-color:#f15f79;color:#fff!important}.search{font-size:3rem;transition:width .2s ease-in;margin:2em;width:10em}.search:focus{width:12em}.spinner{text-align:center;padding:5em}.modal{position:fixed;left:0;top:0;right:0;bottom:0;background-color:rgba(0,0,0,.65);visibility:hidden;-webkit-backface-visibility:hidden;backface-visibility:hidden;opacity:0;transition:opacity .15s ease-in-out}.modal.modal-open{visibility:visible;-webkit-backface-visibility:visible;backface-visibility:visible;opacity:1;z-index:1}.modal-inner{position:relative;height:100%;display:-webkit-flex;display:flex;-webkit-flex-direction:column;flex-direction:column;-webkit-justify-content:center;justify-content:center;-webkit-align-items:center;align-items:center}.modal-content{background-color:#fff;max-width:35em;padding:1em 1.5em;position:relative;margin:2em;box-shadow:0 0 10px 0 rgba(0,0,0,.35)}.modal-content-inner{padding-top:1em;margin-bottom:0}.modal-content-inner input{width:500px}.modal-buttons{display:-webkit-flex;display:flex;-webkit-flex-direction:row;flex-direction:row;-webkit-justify-content:flex-end;justify-content:flex-end;-webkit-align-items:center;align-items:center}.modal-buttons button{margin-left:1em}.modal-buttons button:first-child{margin-left:0} 2 | /*# sourceMappingURL=main.e344f020.chunk.css.map */ -------------------------------------------------------------------------------- /public/static/css/main.e344f020.chunk.css.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":["E:/Clouds/GitLab/LOCALTEST/react-recipes-master/client/src/E:/Clouds/GitLab/LOCALTEST/react-recipes-master/client/src/index.css","main.e344f020.chunk.css","E:/Clouds/GitLab/LOCALTEST/react-recipes-master/client/src/components/E:/Clouds/GitLab/LOCALTEST/react-recipes-master/client/src/components/App.css"],"names":[],"mappings":"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","file":"main.e344f020.chunk.css","sourcesContent":["body {\n margin: 0;\n padding: 0;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", \"Roboto\", \"Oxygen\",\n \"Ubuntu\", \"Cantarell\", \"Fira Sans\", \"Droid Sans\", \"Helvetica Neue\",\n sans-serif;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n}\n\ncode {\n font-family: source-code-pro, Menlo, Monaco, Consolas, \"Courier New\",\n monospace;\n}\n","body {\n margin: 0;\n padding: 0;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", \"Roboto\", \"Oxygen\",\n \"Ubuntu\", \"Cantarell\", \"Fira Sans\", \"Droid Sans\", \"Helvetica Neue\",\n sans-serif;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n}\n\ncode {\n font-family: source-code-pro, Menlo, Monaco, Consolas, \"Courier New\",\n monospace;\n}\n\n/*\n.App {\n text-align: center;\n}\n\n.center {\n text-align: center;\n}\n\nform.form {\n display: inline-grid;\n}\n\n.active {\n font-weight: bold;\n}\n\nnav {\n text-align: center;\n}\n\nnav > ul {\n display: inline-flex;\n list-style: none;\n}\n\nnav > ul > li {\n margin-right: 1em;\n}\n\n.App ul {\n list-style: none;\n} \n*/\n\n/********************************************/\n\n.App {\n text-align: center;\n}\n\nnav {\n text-align: center;\n padding-bottom: 0.2em;\n padding-top: 2em;\n background-color: #efefef;\n box-shadow: -3px 3px 10px 0px rgba(168, 168, 168, 0.7);\n}\n\nnav ul {\n display: -webkit-flex;\n display: flex;\n -webkit-align-items: center;\n align-items: center;\n -webkit-justify-content: space-evenly;\n justify-content: space-evenly;\n -webkit-flex-wrap: wrap;\n flex-wrap: wrap;\n}\n\np,\nli {\n font-size: 2rem;\n}\n\nul {\n list-style: none;\n}\n\ninput,\nselect,\ntextarea {\n padding: 0.4em 0.2em;\n font-size: 2rem;\n}\n\nnav a,\nnav a:link {\n text-decoration: none;\n font-size: 2.5rem;\n font-weight: 100;\n}\n\n.active {\n font-weight: bold;\n}\n\n.form {\n display: -webkit-flex;\n display: flex;\n -webkit-align-items: center;\n align-items: center;\n -webkit-justify-content: center;\n justify-content: center;\n -webkit-flex-direction: column;\n flex-direction: column;\n}\n\n.delete-button {\n color: red;\n cursor: pointer;\n}\n\n/* App */\n\n.main-title {\n padding: 0.5em;\n color: #1eaedb;\n margin: 0;\n -webkit-text-decoration-line: underline;\n text-decoration-line: underline;\n -webkit-text-decoration-style: dotted;\n text-decoration-style: dotted;\n}\n\n.cards {\n display: grid;\n margin: 1.5em 3em;\n grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));\n grid-auto-rows: 150px;\n grid-auto-flow: row dense;\n grid-gap: 2em;\n grid-auto-rows: 300px;\n}\n\n.card {\n position: relative;\n display: -webkit-flex;\n display: flex;\n -webkit-flex-direction: column;\n flex-direction: column;\n -webkit-justify-content: flex-end;\n justify-content: flex-end;\n box-shadow: -3px 3px 10px 0px rgba(168, 168, 168, 0.4);\n text-align: center;\n background: #ddd;\n transition: all 0.3s;\n}\n\n.card:hover {\n -webkit-transform: scale(1.05);\n transform: scale(1.05);\n}\n\n.card:after {\n content: \"\";\n position: absolute;\n width: 100%;\n height: 100%;\n background-color: black;\n opacity: 0.25;\n transition: opacity 0.3s ease-in-out;\n}\n\n.card:hover:after {\n opacity: 0;\n}\n\n.card-text {\n position: relative;\n z-index: 1;\n color: rgb(39, 37, 37);\n background: whitesmoke;\n letter-spacing: 1px;\n}\n\n.card-text a {\n text-decoration: none;\n}\n\n.card-text h4 {\n margin: 0;\n padding: 0.2em;\n}\n\n.Lunch {\n width: 20%;\n margin: 20px;\n z-index: 1;\n padding: 7px;\n border-radius: 5px;\n color: white;\n background: #24c6dc;\n background: linear-gradient(to right, #514a9d, #24c6dc);\n}\n\n.Snack {\n width: 20%;\n margin: 20px;\n z-index: 1;\n padding: 7px;\n border-radius: 5px;\n color: white;\n background: #50c9c3;\n background: linear-gradient(to right, rgb(80, 146, 143), rgb(2, 105, 100));\n}\n\n.Breakfast {\n width: 100px;\n margin: 20px;\n z-index: 1;\n color: white;\n padding: 7px;\n background: #9d50bb;\n border-radius: 50px 120px 120px;\n}\n\n.Dinner {\n width: 20%;\n margin: 20px;\n z-index: 1;\n padding: 7px;\n color: white;\n background: linear-gradient(to right, #b24592, #f15f79);\n border-radius: 50px 120px 120px;\n}\n\n/* Recipe Page */\n\n.recipe-image {\n height: 60vh;\n width: 100%;\n}\n\n.recipe-image:after {\n content: \"\";\n position: absolute;\n width: 100%;\n height: 60vh;\n opacity: 0.25;\n transition: opacity 0.3s ease-in-out;\n}\n\n.recipe {\n text-align: center;\n background: whitesmoke;\n padding: 1em;\n}\n\n.recipe h1 {\n font-size: 2.5rem;\n text-align: center;\n}\n\n.recipe-header {\n overflow: hidden;\n background-image: url(https://bit.ly/2JqRbuI);\n}\n\n.recipe-header > p {\n margin: 0;\n}\n\n.recipe-description {\n font-size: 2rem;\n color: darkslategray;\n padding: 1em;\n font-weight: 200;\n background: white;\n box-shadow: 2px 2px 2px 2px rgba(0, 0, 0, 0.2);\n font-style: italic;\n}\n\n.recipe-name {\n color: #1eaedb;\n text-decoration: underline;\n -webkit-text-decoration-style: wavy;\n text-decoration-style: wavy;\n}\n\n.recipe-instructions {\n text-align: left;\n padding: 0 2em;\n}\n\n.recipe-instructions * {\n padding-bottom: 0.5em;\n}\n\n.recipe-instructions__title {\n font-weight: 200;\n letter-spacing: 2px;\n color: #1eaedb;\n text-decoration: underline;\n}\n\n.like-button {\n position: fixed;\n right: 1em;\n bottom: 1em;\n font-size: 2rem;\n background-color: #f15f79;\n color: white !important;\n}\n\n/* Search */\n\n.search {\n font-size: 3rem;\n transition: width 0.2s ease-in;\n margin: 2em;\n width: 10em;\n}\n\n.search:focus {\n width: 12em;\n}\n\n.spinner {\n text-align: center;\n padding: 5em;\n}\n\n/* User Recipes */\n\n.modal {\n position: fixed;\n left: 0;\n top: 0;\n right: 0;\n bottom: 0;\n background-color: rgba(0, 0, 0, 0.65);\n visibility: hidden;\n -webkit-backface-visibility: hidden;\n backface-visibility: hidden;\n opacity: 0;\n transition: opacity 0.15s ease-in-out;\n}\n\n.modal.modal-open {\n visibility: visible;\n -webkit-backface-visibility: visible;\n backface-visibility: visible;\n opacity: 1;\n z-index: 1;\n}\n\n.modal-inner {\n position: relative;\n height: 100%;\n display: -webkit-flex;\n display: flex;\n -webkit-flex-direction: column;\n flex-direction: column;\n -webkit-justify-content: center;\n justify-content: center;\n -webkit-align-items: center;\n align-items: center;\n}\n\n.modal-content {\n background-color: white;\n max-width: 35em;\n padding: 1em 1.5em;\n position: relative;\n margin: 2em;\n box-shadow: 0px 0px 10px 0px rgba(0, 0, 0, 0.35);\n}\n\n.modal-content-inner {\n padding-top: 1em;\n margin-bottom: 0;\n}\n\n.modal-content-inner input {\n width: 500px;\n}\n\n.modal-buttons {\n display: -webkit-flex;\n display: flex;\n -webkit-flex-direction: row;\n flex-direction: row;\n -webkit-justify-content: flex-end;\n justify-content: flex-end;\n -webkit-align-items: center;\n align-items: center;\n}\n\n.modal-buttons button {\n margin-left: 1em;\n}\n\n.modal-buttons button:first-child {\n margin-left: 0;\n}\n\n","/*\n.App {\n text-align: center;\n}\n\n.center {\n text-align: center;\n}\n\nform.form {\n display: inline-grid;\n}\n\n.active {\n font-weight: bold;\n}\n\nnav {\n text-align: center;\n}\n\nnav > ul {\n display: inline-flex;\n list-style: none;\n}\n\nnav > ul > li {\n margin-right: 1em;\n}\n\n.App ul {\n list-style: none;\n} \n*/\n\n/********************************************/\n\n.App {\n text-align: center;\n}\n\nnav {\n text-align: center;\n padding-bottom: 0.2em;\n padding-top: 2em;\n background-color: #efefef;\n box-shadow: -3px 3px 10px 0px rgba(168, 168, 168, 0.7);\n}\n\nnav ul {\n display: flex;\n align-items: center;\n justify-content: space-evenly;\n flex-wrap: wrap;\n}\n\np,\nli {\n font-size: 2rem;\n}\n\nul {\n list-style: none;\n}\n\ninput,\nselect,\ntextarea {\n padding: 0.4em 0.2em;\n font-size: 2rem;\n}\n\nnav a,\nnav a:link {\n text-decoration: none;\n font-size: 2.5rem;\n font-weight: 100;\n}\n\n.active {\n font-weight: bold;\n}\n\n.form {\n display: flex;\n align-items: center;\n justify-content: center;\n flex-direction: column;\n}\n\n.delete-button {\n color: red;\n cursor: pointer;\n}\n\n/* App */\n\n.main-title {\n padding: 0.5em;\n color: #1eaedb;\n margin: 0;\n text-decoration-line: underline;\n text-decoration-style: dotted;\n}\n\n.cards {\n display: grid;\n margin: 1.5em 3em;\n grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));\n grid-auto-rows: 150px;\n grid-auto-flow: row dense;\n grid-gap: 2em;\n grid-auto-rows: 300px;\n}\n\n.card {\n position: relative;\n display: flex;\n flex-direction: column;\n justify-content: flex-end;\n box-shadow: -3px 3px 10px 0px rgba(168, 168, 168, 0.4);\n text-align: center;\n background: #ddd;\n transition: all 0.3s;\n}\n\n.card:hover {\n transform: scale(1.05);\n}\n\n.card:after {\n content: \"\";\n position: absolute;\n width: 100%;\n height: 100%;\n background-color: black;\n opacity: 0.25;\n transition: opacity 0.3s ease-in-out;\n}\n\n.card:hover:after {\n opacity: 0;\n}\n\n.card-text {\n position: relative;\n z-index: 1;\n color: rgb(39, 37, 37);\n background: whitesmoke;\n letter-spacing: 1px;\n}\n\n.card-text a {\n text-decoration: none;\n}\n\n.card-text h4 {\n margin: 0;\n padding: 0.2em;\n}\n\n.Lunch {\n width: 20%;\n margin: 20px;\n z-index: 1;\n padding: 7px;\n border-radius: 5px;\n color: white;\n background: #24c6dc;\n background: linear-gradient(to right, #514a9d, #24c6dc);\n}\n\n.Snack {\n width: 20%;\n margin: 20px;\n z-index: 1;\n padding: 7px;\n border-radius: 5px;\n color: white;\n background: #50c9c3;\n background: linear-gradient(to right, rgb(80, 146, 143), rgb(2, 105, 100));\n}\n\n.Breakfast {\n width: 100px;\n margin: 20px;\n z-index: 1;\n color: white;\n padding: 7px;\n background: #9d50bb;\n border-radius: 50px 120px 120px;\n}\n\n.Dinner {\n width: 20%;\n margin: 20px;\n z-index: 1;\n padding: 7px;\n color: white;\n background: linear-gradient(to right, #b24592, #f15f79);\n border-radius: 50px 120px 120px;\n}\n\n/* Recipe Page */\n\n.recipe-image {\n height: 60vh;\n width: 100%;\n}\n\n.recipe-image:after {\n content: \"\";\n position: absolute;\n width: 100%;\n height: 60vh;\n opacity: 0.25;\n transition: opacity 0.3s ease-in-out;\n}\n\n.recipe {\n text-align: center;\n background: whitesmoke;\n padding: 1em;\n}\n\n.recipe h1 {\n font-size: 2.5rem;\n text-align: center;\n}\n\n.recipe-header {\n overflow: hidden;\n background-image: url(https://bit.ly/2JqRbuI);\n}\n\n.recipe-header > p {\n margin: 0;\n}\n\n.recipe-description {\n font-size: 2rem;\n color: darkslategray;\n padding: 1em;\n font-weight: 200;\n background: white;\n box-shadow: 2px 2px 2px 2px rgba(0, 0, 0, 0.2);\n font-style: italic;\n}\n\n.recipe-name {\n color: #1eaedb;\n text-decoration: underline;\n text-decoration-style: wavy;\n}\n\n.recipe-instructions {\n text-align: left;\n padding: 0 2em;\n}\n\n.recipe-instructions * {\n padding-bottom: 0.5em;\n}\n\n.recipe-instructions__title {\n font-weight: 200;\n letter-spacing: 2px;\n color: #1eaedb;\n text-decoration: underline;\n}\n\n.like-button {\n position: fixed;\n right: 1em;\n bottom: 1em;\n font-size: 2rem;\n background-color: #f15f79;\n color: white !important;\n}\n\n/* Search */\n\n.search {\n font-size: 3rem;\n transition: width 0.2s ease-in;\n margin: 2em;\n width: 10em;\n}\n\n.search:focus {\n width: 12em;\n}\n\n.spinner {\n text-align: center;\n padding: 5em;\n}\n\n/* User Recipes */\n\n.modal {\n position: fixed;\n left: 0;\n top: 0;\n right: 0;\n bottom: 0;\n background-color: rgba(0, 0, 0, 0.65);\n visibility: hidden;\n backface-visibility: hidden;\n opacity: 0;\n transition: opacity 0.15s ease-in-out;\n}\n\n.modal.modal-open {\n visibility: visible;\n backface-visibility: visible;\n opacity: 1;\n z-index: 1;\n}\n\n.modal-inner {\n position: relative;\n height: 100%;\n display: flex;\n flex-direction: column;\n justify-content: center;\n align-items: center;\n}\n\n.modal-content {\n background-color: white;\n max-width: 35em;\n padding: 1em 1.5em;\n position: relative;\n margin: 2em;\n box-shadow: 0px 0px 10px 0px rgba(0, 0, 0, 0.35);\n}\n\n.modal-content-inner {\n padding-top: 1em;\n margin-bottom: 0;\n}\n\n.modal-content-inner input {\n width: 500px;\n}\n\n.modal-buttons {\n display: flex;\n flex-direction: row;\n justify-content: flex-end;\n align-items: center;\n}\n\n.modal-buttons button {\n margin-left: 1em;\n}\n\n.modal-buttons button:first-child {\n margin-left: 0;\n}\n"]} -------------------------------------------------------------------------------- /public/static/js/main.ef6f36c7.chunk.js: -------------------------------------------------------------------------------- 1 | (window.webpackJsonp=window.webpackJsonp||[]).push([[0],{106:function(e,t,n){"use strict";n.r(t);var a=n(0),r=n.n(a),c=n(40),i=n.n(c),l=n(110),u=n(111),o=n(54),s=n(109),m=(n(61),n(15)),p=n(16),d=n(18),h=n(17),f=n(19),g=n(37),E=(n(62),n(5)),v=n(11),b=n(9);function y(){var e=Object(v.a)(["\n fragment LikeRecipe on Recipe {\n _id\n likes\n }\n "]);return y=function(){return e},e}function j(){var e=Object(v.a)(["\n fragment MinimalRecipe on Recipe {\n _id\n name\n imageUrl\n category\n }\n "]);return j=function(){return e},e}function O(){var e=Object(v.a)(["\n fragment CompleteRecipe on Recipe {\n _id\n name\n imageUrl\n category\n description\n instructions\n createdDate\n likes\n username\n }\n "]);return O=function(){return e},e}var k={recipe:Object(b.b)(O()),minRecipe:Object(b.b)(j()),like:Object(b.b)(y())};function C(){var e=Object(v.a)(["\n mutation($username: String!, $email: String!, $password: String!) {\n signupUser(username: $username, email: $email, password: $password) {\n token\n }\n }\n"]);return C=function(){return e},e}function S(){var e=Object(v.a)(["\n mutation($username: String!, $password: String!) {\n signinUser(username: $username, password: $password) {\n token\n }\n }\n"]);return S=function(){return e},e}function R(){var e=Object(v.a)(["\n query($username: String!) {\n getUserRecipes(username: $username) {\n ...CompleteRecipe\n }\n }\n ","\n"]);return R=function(){return e},e}function w(){var e=Object(v.a)(["\n query {\n getCurrentUser {\n username\n joinDate\n email\n favorites {\n _id\n name\n }\n }\n }\n"]);return w=function(){return e},e}function U(){var e=Object(v.a)(["\n mutation(\n $_id: ID!\n $name: String!\n $imageUrl: String!\n $category: String!\n $description: String!\n $instructions: String!\n ) {\n updateUserRecipe(\n _id: $_id\n name: $name\n imageUrl: $imageUrl\n category: $category\n description: $description\n instructions: $instructions\n ) {\n ...CompleteRecipe\n }\n }\n ","\n"]);return U=function(){return e},e}function _(){var e=Object(v.a)(["\n mutation($_id: ID!) {\n deleteUserRecipe(_id: $_id) {\n _id\n }\n }\n"]);return _=function(){return e},e}function $(){var e=Object(v.a)(["\n mutation($_id: ID!, $username: String!) {\n unlikeRecipe(_id: $_id, username: $username) {\n ...LikeRecipe\n }\n }\n ","\n"]);return $=function(){return e},e}function N(){var e=Object(v.a)(["\n mutation($_id: ID!, $username: String!) {\n likeRecipe(_id: $_id, username: $username) {\n ...LikeRecipe\n }\n }\n ","\n"]);return N=function(){return e},e}function A(){var e=Object(v.a)(["\n mutation(\n $name: String!\n $imageUrl: String!\n $category: String!\n $description: String!\n $instructions: String!\n $username: String\n ) {\n addRecipe(\n name: $name\n imageUrl: $imageUrl\n category: $category\n description: $description\n instructions: $instructions\n username: $username\n ) {\n ...MinimalRecipe\n }\n }\n ","\n"]);return A=function(){return e},e}function D(){var e=Object(v.a)(["\n query($searchTerm: String) {\n searchRecipes(searchTerm: $searchTerm) {\n _id\n name\n likes\n }\n }\n"]);return D=function(){return e},e}function x(){var e=Object(v.a)(["\n query($_id: ID!) {\n getRecipe(_id: $_id) {\n ...CompleteRecipe\n }\n }\n ","\n"]);return x=function(){return e},e}function q(){var e=Object(v.a)(["\n query {\n getAllRecipes {\n ...MinimalRecipe\n }\n }\n ","\n"]);return q=function(){return e},e}var I=Object(b.b)(q(),k.minRecipe),L=Object(b.b)(x(),k.recipe),F=Object(b.b)(D()),M=Object(b.b)(A(),k.minRecipe),Q=Object(b.b)(N(),k.like),B=Object(b.b)($(),k.like),T=Object(b.b)(_()),P=Object(b.b)(U(),k.recipe),Y=Object(b.b)(w()),H=Object(b.b)(R(),k.recipe),J=Object(b.b)(S()),z=Object(b.b)(C()),G=n(41),W=g.a.li({shown:{opacity:1},hidden:{opacity:0}}),K=function(e){var t=e._id,n=e.name,a=e.imageUrl,c=e.category;return r.a.createElement(W,{style:{background:"url(".concat(a,") center center / cover no-repeat")},className:"card"},r.a.createElement("span",{className:c},c),r.a.createElement("div",{className:"card-text"},r.a.createElement(G.a,{to:"/recipes/".concat(t)},r.a.createElement("h4",null,n))))},V=n(52),X=function(){return r.a.createElement("div",{className:"spinner"},r.a.createElement(V.PulseLoader,{color:"#1eaedb",size:30,margin:"3px"}))},Z=g.a.ul({shown:{x:"0%",staggerChildren:100},hidden:{x:"-100%"}}),ee=function(e){function t(){var e,n;Object(m.a)(this,t);for(var a=arguments.length,r=new Array(a),c=0;c-1;n.setState({liked:c,username:t})}},n.handleClick=function(e,t){n.setState(function(e){return{liked:!e.liked}},function(){return n.handleLike(e,t)})},n.handleLike=function(e,t){n.state.liked?e().then(function(){var e=Object(ae.a)(ne.a.mark(function e(t){return ne.a.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:return t.data,e.next=3,n.props.refetch();case 3:case"end":return e.stop()}},e)}));return function(t){return e.apply(this,arguments)}}()):t().then(function(){var e=Object(ae.a)(ne.a.mark(function e(t){return ne.a.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:return t.data,e.next=3,n.props.refetch();case 3:case"end":return e.stop()}},e)}));return function(t){return e.apply(this,arguments)}}())},n.updateLike=function(e,t){var a=t.data.likeRecipe,r=n.props._id,c=e.readQuery({query:L,variables:{_id:r}}).getRecipe;e.writeQuery({query:L,variables:{_id:r},data:{getRecipe:Object(ce.a)({},c,{likes:a.likes+1})}})},n.updateUnlike=function(e,t){var a=t.data.unlikeRecipe,r=n.props._id,c=e.readQuery({query:L,variables:{_id:r}}).getRecipe;e.writeQuery({query:L,variables:{_id:r},data:{getRecipe:Object(ce.a)({},c,{likes:a.likes-1})}})},n}return Object(f.a)(t,e),Object(p.a)(t,[{key:"render",value:function(){var e=this,t=this.state,n=t.username,a=t.liked,c=this.props._id;return r.a.createElement(E.c,{mutation:B,variables:{_id:c,username:n},update:this.updateUnlike},function(t){return r.a.createElement(E.c,{mutation:Q,variables:{_id:c,username:n},update:e.updateLike},function(c){return n&&r.a.createElement("button",{className:"like-button",onClick:function(){return e.handleClick(c,t)}},a?"Unlike":"Like")})})}}]),t}(r.a.Component)),Se=Object(ie.a)(function(e){var t=e.match.params._id;return r.a.createElement(E.d,{query:L,variables:{_id:t}},function(e){var n=e.data,a=e.loading,c=e.error;return a?r.a.createElement(X,null):c?r.a.createElement("div",{className:"App"},"Error"):r.a.createElement("div",{className:"App"},r.a.createElement("div",{style:{background:"url(".concat(n.getRecipe.imageUrl,") center center / cover no-repeat")},className:"recipe-image"}),r.a.createElement("div",{className:"recipe"},r.a.createElement("div",{className:"recipe-header"},r.a.createElement("h2",{className:"recipe-name"},r.a.createElement("strong",null,n.getRecipe.name)),r.a.createElement("h5",null,r.a.createElement("strong",null,n.getRecipe.category)),r.a.createElement("p",null,"Created by ",r.a.createElement("strong",null,n.getRecipe.username)),r.a.createElement("p",null,"Created date ",r.a.createElement("strong",null,n.getRecipe.createdDate)),r.a.createElement("p",null,n.getRecipe.likes," ",r.a.createElement("span",{role:"img","aria-label":"heart"},"\u2665"))),r.a.createElement("blockquote",{className:"recipe-description"},n.getRecipe.description),r.a.createElement("h3",{className:"recipe-instructions__title"},"Instructions"),r.a.createElement("div",{className:"recipe-instructions",dangerouslySetInnerHTML:{__html:n.getRecipe.instructions}}),r.a.createElement(Ce,{_id:t})))})}),Re=function(e){var t=e.session;return r.a.createElement("div",{className:"App"},r.a.createElement("h3",null,"User Info"),r.a.createElement("p",null,"Username: ",t.getCurrentUser.username),r.a.createElement("p",null,"E-mail: ",t.getCurrentUser.email),r.a.createElement("p",null,"Join Date: ",function(e){var t=new Date(e).toLocaleDateString("en-US"),n=new Date(e).toLocaleTimeString("en-US");return"".concat(t," at ").concat(n)}(t.getCurrentUser.joinDate)),r.a.createElement("ul",null,r.a.createElement("h3",null,t.getCurrentUser.username,"'s Favorites"),t.getCurrentUser.favorites.map(function(e){return r.a.createElement("li",{key:e._id},r.a.createElement(G.a,{to:"/recipes/".concat(e._id)},r.a.createElement("p",null,e.name))," ")}),!t.getCurrentUser.favorites.length&&r.a.createElement("p",null,r.a.createElement("strong",null,"You have no favorites currently. Go add some!"))))},we=function(e){function t(){var e,n;Object(m.a)(this,t);for(var a=arguments.length,r=new Array(a),c=0;c1&&void 0!==arguments[1]?arguments[1]:{};return r.a.createElement(r.a.Fragment,null,r.a.createElement("button",{className:"button-primary",onClick:function(){return e.loadRecipe(n)}},"Update"),r.a.createElement("button",{className:"delete-button",onClick:function(){return e.handleDelete(t)}},a.loading?"Deleting...":"Delete"))}))}))})}}]),t}(r.a.Component),Ue=function(e){var t=e.handleSubmit,n=e.recipe,a=e.handleChange,c=e.handleEditChange,i=e.closeModal;return r.a.createElement(E.c,{mutation:P,variables:{_id:n._id,name:n.name,imageUrl:n.imageUrl,category:n.category,description:n.description,instructions:n.instructions}},function(e){return r.a.createElement("div",{className:"modal modal-open"},r.a.createElement("div",{className:"modal-inner"},r.a.createElement("div",{className:"modal-content"},r.a.createElement("form",{onSubmit:function(n){return t(n,e)},className:"modal-content-inner"},r.a.createElement("h4",null,"Edit Recipe"),r.a.createElement("input",{type:"text",name:"name",placeholder:"Recipe Name",onChange:a,value:n.name}),r.a.createElement("input",{type:"text",name:"imageUrl",placeholder:"Recipe Image",onChange:a,value:n.imageUrl}),r.a.createElement("select",{name:"category",onChange:a,value:n.category},r.a.createElement("option",{value:"Breakfast"},"Breakfast"),r.a.createElement("option",{value:"Lunch"},"Lunch"),r.a.createElement("option",{value:"Dinner"},"Dinner"),r.a.createElement("option",{value:"Snack"},"Snack")),r.a.createElement("input",{type:"text",name:"description",placeholder:"Add description",onChange:a,value:n.description}),r.a.createElement(be.a,{name:"instructions",content:n.instructions,events:{change:c}}),r.a.createElement("hr",null),r.a.createElement("div",{className:"modal-buttons"},r.a.createElement("button",{type:"submit",className:"button-primary"},"Update"),r.a.createElement("button",{onClick:i},"Cencel"))))))})},_e=we,$e=ye(function(e){return e&&e.data.getCurrentUser})(function(e){var t=e.session;return r.a.createElement("div",{className:"App"},r.a.createElement(Re,{session:t}),r.a.createElement(_e,{username:t.getCurrentUser.username}))}),Ne=n(108),Ae=Object(ie.a)(function(e){var t=e.history;return r.a.createElement(E.a,null,function(e){return r.a.createElement("button",{onClick:function(){return function(e,t){localStorage.removeItem("token"),e.resetStore(),t.push("/")}(e,t)}},"Signout")})}),De=function(e){var t=e.session;return r.a.createElement(a.Fragment,null,r.a.createElement("ul",null,r.a.createElement("li",null,r.a.createElement(Ne.a,{to:"/",exact:!0},"Home")),r.a.createElement("li",null,r.a.createElement(Ne.a,{to:"/search"},"Search")),r.a.createElement("li",null,r.a.createElement(Ne.a,{to:"/recipe/add"},"Add Recipe")),r.a.createElement("li",null,r.a.createElement(Ne.a,{to:"/profile"},"Profile")),r.a.createElement("li",null,r.a.createElement(Ae,null))),r.a.createElement("h4",null,"Welcome, ",r.a.createElement("strong",null,t.getCurrentUser.username)))},xe=function(){return r.a.createElement("ul",null,r.a.createElement("li",null,r.a.createElement(Ne.a,{to:"/",exact:!0},"Home")),r.a.createElement("li",null,r.a.createElement(Ne.a,{to:"/search"},"Search")),r.a.createElement("li",null,r.a.createElement(Ne.a,{to:"/signin"},"Signin")),r.a.createElement("li",null,r.a.createElement(Ne.a,{to:"/signup"},"Signup")))},qe=function(e){var t=e.session;return r.a.createElement("nav",null,t&&t.getCurrentUser?r.a.createElement(De,{session:t}):r.a.createElement(xe,null))},Ie=new b.a({uri:"http://localhost:4444/graphql",fetchOptions:{credentials:"include"},request:function(e){var t=localStorage.getItem("token");e.setContext({headers:{authorization:t}})},onError:function(e){e.networkError&&localStorage.setItem("token","")}}),Le=he(function(e){var t=e.refetch,n=e.session;return r.a.createElement(l.a,null,r.a.createElement(a.Fragment,null,r.a.createElement(qe,{session:n}),r.a.createElement(u.a,null,r.a.createElement(o.a,{path:"/",exact:!0,component:ee}),r.a.createElement(o.a,{path:"/search",component:ge}),r.a.createElement(o.a,{path:"/profile",render:function(){return r.a.createElement($e,{session:n})}}),r.a.createElement(o.a,{path:"/recipe/add",render:function(){return r.a.createElement(ke,{session:n})}}),r.a.createElement(o.a,{path:"/recipes/:_id",component:Se}),r.a.createElement(o.a,{path:"/signin",render:function(){return r.a.createElement(se,{refetch:t})}}),r.a.createElement(o.a,{path:"/signup",render:function(){return r.a.createElement(de,{refetch:t})}}),r.a.createElement(s.a,{to:"/"}))))});i.a.render(r.a.createElement(E.b,{client:Ie},r.a.createElement(Le,null)),document.getElementById("root"))},56:function(e,t,n){e.exports=n(106)},61:function(e,t,n){},62:function(e,t,n){}},[[56,1,2]]]); 2 | //# sourceMappingURL=main.ef6f36c7.chunk.js.map -------------------------------------------------------------------------------- /public/static/js/main.ef6f36c7.chunk.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":["queries/fragments.js","queries/index.js","components/Recipe/RecipeItem.js","components/Spinner.js","components/App.js","components/Error.js","components/Auth/Signin.js","components/Auth/Signup.js","components/withSession.js","components/Recipe/SearchItem.js","components/Recipe/Search.js","components/withAuth.js","components/Recipe/AddRecipe.js","components/Recipe/LikeRecipe.js","components/Recipe/RecipePage.js","components/Profile/UserInfo.js","components/Profile/UserRecipes.js","components/Profile/Profile.js","components/Auth/Signout.js","components/Navbar.js","index.js"],"names":["recipeFragments","recipe","gql","_templateObject","minRecipe","_templateObject2","like","_templateObject3","GET_ALL_RECIPES","queries_templateObject","GET_RECIPE","queries_templateObject2","SEARCH_RECIPES","queries_templateObject3","ADD_RECIPE","_templateObject4","LIKE_RECIPE","_templateObject5","UNLIKE_RECIPE","_templateObject6","DELETE_USER_RECIPE","_templateObject7","UPDATE_USER_RECIPE","_templateObject8","GET_CURRENT_USER","_templateObject9","GET_USER_RECIPES","_templateObject10","SIGNIN_USER","_templateObject11","SIGNUP_USER","_templateObject12","RecipeItem","posed","li","shown","opacity","hidden","Recipe_RecipeItem","_ref","_id","name","imageUrl","category","react_default","a","createElement","style","background","concat","className","Link","to","Spinner","react_spinners","color","size","margin","RecipeList","ul","x","staggerChildren","App","state","on","slideIn","_this","setState","setTimeout","this","_this2","react_apollo_esm","query","data","loading","error","components_Spinner","pose","getAllRecipes","map","Object","assign","key","React","Component","Error","message","initialState","username","password","Signin","clearState","objectSpread","handleChange","event","_event$target","target","value","defineProperty","handleSubmit","signinUser","preventDefault","then","_ref2","asyncToGenerator","regenerator_default","mark","_callee","wrap","_context","prev","next","localStorage","setItem","token","props","refetch","history","push","stop","_x","apply","arguments","validateForm","_this$state","_this$state2","mutation","variables","_ref3","onSubmit","type","placeholder","onChange","disabled","components_Error","withRouter","email","passwordConfirmation","Signup","signupUser","withSession","session","SearchItem","likes","Search","searchRecipes","client","persist","searchTerm","sent","Recipe_SearchItem","withAuth","conditionFunc","Redirect","description","instructions","AddRecipe","handleEditChange","newContent","editor","getData","addRecipe","updateCache","cache","readQuery","writeQuery","toConsumableArray","getCurrentUser","refetchQueries","update","htmlFor","lib_default","content","events","change","liked","componentDidMount","console","log","_this$props$session$g","favorites","prevLiked","findIndex","favorite","handleClick","likeRecipe","unlikeRecipe","prevState","handleLike","_ref4","_callee2","_context2","_x2","updateLike","_ref5","getRecipe","updateUnlike","_ref6","onClick","match","params","createdDate","role","aria-label","dangerouslySetInnerHTML","__html","Recipe_LikeRecipe","UserInfo","date","newDate","Date","toLocaleDateString","newTime","toLocaleTimeString","formatDate","joinDate","length","UserRecipes","modal","handleDelete","deleteUserRecipe","window","confirm","updateUserRecipe","closeModal","loadRecipe","UserRecipes_EditRecipeModal","getUserRecipes","border","marginBottom","filter","attrs","undefined","Fragment","EditRecipeModal","Profile_UserInfo","Profile_UserRecipes","removeItem","resetStore","handleSignout","NavbarAuth","react","NavLink","exact","Auth_Signout","NavbarUnAuth","Navbar","Navbar_NavbarAuth","Navbar_NavbarUnAuth","ApolloClient","uri","fetchOptions","credentials","request","operation","getItem","setContext","headers","authorization","onError","networkError","RootWithSession","BrowserRouter","components_Navbar","Switch","Route","path","component","render","components_Profile_Profile","Recipe_AddRecipe","RecipePage","Auth_Signin","Auth_Signup","ReactDOM","document","getElementById"],"mappings":"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","file":"static/js/main.ef6f36c7.chunk.js","sourcesContent":["import { gql } from \"apollo-boost\";\r\n\r\nexport const recipeFragments = {\r\n recipe: gql`\r\n fragment CompleteRecipe on Recipe {\r\n _id\r\n name\r\n imageUrl\r\n category\r\n description\r\n instructions\r\n createdDate\r\n likes\r\n username\r\n }\r\n `,\r\n minRecipe: gql`\r\n fragment MinimalRecipe on Recipe {\r\n _id\r\n name\r\n imageUrl\r\n category\r\n }\r\n `,\r\n like: gql`\r\n fragment LikeRecipe on Recipe {\r\n _id\r\n likes\r\n }\r\n `\r\n};\r\n","import { gql } from \"apollo-boost\";\r\nimport { recipeFragments } from \"./fragments\";\r\n\r\n// Recipes Queries\r\nexport const GET_ALL_RECIPES = gql`\r\n query {\r\n getAllRecipes {\r\n ...MinimalRecipe\r\n }\r\n }\r\n ${recipeFragments.minRecipe}\r\n`;\r\nexport const GET_RECIPE = gql`\r\n query($_id: ID!) {\r\n getRecipe(_id: $_id) {\r\n ...CompleteRecipe\r\n }\r\n }\r\n ${recipeFragments.recipe}\r\n`;\r\nexport const SEARCH_RECIPES = gql`\r\n query($searchTerm: String) {\r\n searchRecipes(searchTerm: $searchTerm) {\r\n _id\r\n name\r\n likes\r\n }\r\n }\r\n`;\r\n\r\n// Recipes Mutations\r\nexport const ADD_RECIPE = gql`\r\n mutation(\r\n $name: String!\r\n $imageUrl: String!\r\n $category: String!\r\n $description: String!\r\n $instructions: String!\r\n $username: String\r\n ) {\r\n addRecipe(\r\n name: $name\r\n imageUrl: $imageUrl\r\n category: $category\r\n description: $description\r\n instructions: $instructions\r\n username: $username\r\n ) {\r\n ...MinimalRecipe\r\n }\r\n }\r\n ${recipeFragments.minRecipe}\r\n`;\r\nexport const LIKE_RECIPE = gql`\r\n mutation($_id: ID!, $username: String!) {\r\n likeRecipe(_id: $_id, username: $username) {\r\n ...LikeRecipe\r\n }\r\n }\r\n ${recipeFragments.like}\r\n`;\r\nexport const UNLIKE_RECIPE = gql`\r\n mutation($_id: ID!, $username: String!) {\r\n unlikeRecipe(_id: $_id, username: $username) {\r\n ...LikeRecipe\r\n }\r\n }\r\n ${recipeFragments.like}\r\n`;\r\nexport const DELETE_USER_RECIPE = gql`\r\n mutation($_id: ID!) {\r\n deleteUserRecipe(_id: $_id) {\r\n _id\r\n }\r\n }\r\n`;\r\nexport const UPDATE_USER_RECIPE = gql`\r\n mutation(\r\n $_id: ID!\r\n $name: String!\r\n $imageUrl: String!\r\n $category: String!\r\n $description: String!\r\n $instructions: String!\r\n ) {\r\n updateUserRecipe(\r\n _id: $_id\r\n name: $name\r\n imageUrl: $imageUrl\r\n category: $category\r\n description: $description\r\n instructions: $instructions\r\n ) {\r\n ...CompleteRecipe\r\n }\r\n }\r\n ${recipeFragments.recipe}\r\n`;\r\n\r\n// User Queries\r\nexport const GET_CURRENT_USER = gql`\r\n query {\r\n getCurrentUser {\r\n username\r\n joinDate\r\n email\r\n favorites {\r\n _id\r\n name\r\n }\r\n }\r\n }\r\n`;\r\nexport const GET_USER_RECIPES = gql`\r\n query($username: String!) {\r\n getUserRecipes(username: $username) {\r\n ...CompleteRecipe\r\n }\r\n }\r\n ${recipeFragments.recipe}\r\n`;\r\n\r\n// User Mutations\r\nexport const SIGNIN_USER = gql`\r\n mutation($username: String!, $password: String!) {\r\n signinUser(username: $username, password: $password) {\r\n token\r\n }\r\n }\r\n`;\r\n\r\nexport const SIGNUP_USER = gql`\r\n mutation($username: String!, $email: String!, $password: String!) {\r\n signupUser(username: $username, email: $email, password: $password) {\r\n token\r\n }\r\n }\r\n`;\r\n","import React from \"react\";\r\nimport posed from \"react-pose\";\r\nimport { Link } from \"react-router-dom\";\r\n\r\nconst RecipeItem = posed.li({\r\n shown: { opacity: 1 },\r\n hidden: { opacity: 0 }\r\n});\r\n\r\nexport default ({ _id, name, imageUrl, category }) => (\r\n \r\n {category}\r\n
\r\n \r\n

{name}

\r\n \r\n
\r\n \r\n);\r\n","import React from \"react\";\r\nimport { PulseLoader } from \"react-spinners\";\r\n\r\nconst Spinner = () => (\r\n
\r\n \r\n
\r\n);\r\n\r\nexport default Spinner;\r\n","import React from \"react\";\nimport posed from \"react-pose\";\nimport \"./App.css\";\n\nimport { Query } from \"react-apollo\";\nimport { GET_ALL_RECIPES } from \"../queries\";\nimport RecipeItem from \"./Recipe/RecipeItem\";\nimport Spinner from \"./Spinner\";\n\nconst RecipeList = posed.ul({\n shown: {\n x: \"0%\",\n staggerChildren: 100\n },\n hidden: {\n x: \"-100%\"\n }\n});\n\nclass App extends React.Component {\n state = {\n on: false\n };\n\n componentDidMount() {\n setTimeout(this.slideIn, 200);\n }\n\n slideIn = () => {\n this.setState({ on: !this.state.on });\n };\n\n render() {\n return (\n
\n

\n Find Recipes You Love\n

\n \n {({ data, loading, error }) => {\n if (loading) return ;\n if (error) return
Error
;\n const { on } = this.state;\n return (\n \n {data.getAllRecipes.map(recipe => (\n \n ))}\n \n );\n }}\n
\n
\n );\n }\n}\n\nexport default App;\n","import React from \"react\";\r\n\r\nconst Error = ({ error }) =>

{error.message}

;\r\n\r\nexport default Error;\r\n","import React from \"react\";\r\nimport { withRouter } from \"react-router-dom\";\r\n\r\nimport { Mutation } from \"react-apollo\";\r\nimport { SIGNIN_USER } from \"../../queries\";\r\nimport Error from \"../Error\";\r\n\r\nconst initialState = {\r\n username: \"\",\r\n password: \"\"\r\n};\r\n\r\nclass Signin extends React.Component {\r\n state = { ...initialState };\r\n\r\n clearState = () => {\r\n this.setState({ ...initialState });\r\n };\r\n\r\n handleChange = event => {\r\n const { name, value } = event.target;\r\n this.setState({\r\n [name]: value\r\n });\r\n };\r\n\r\n handleSubmit = (event, signinUser) => {\r\n event.preventDefault();\r\n signinUser().then(async ({ data }) => {\r\n localStorage.setItem(\"token\", data.signinUser.token);\r\n await this.props.refetch();\r\n this.clearState();\r\n this.props.history.push(\"/\");\r\n });\r\n };\r\n\r\n validateForm = () => {\r\n const { username, password } = this.state;\r\n const isInvalid = !username || !password;\r\n return isInvalid;\r\n };\r\n\r\n render() {\r\n const { username, password } = this.state;\r\n\r\n return (\r\n
\r\n

Signin

\r\n \r\n {(signinUser, { data, loading, error }) => {\r\n return (\r\n this.handleSubmit(event, signinUser)}\r\n >\r\n \r\n \r\n \r\n Signin\r\n \r\n {error && }\r\n \r\n );\r\n }}\r\n \r\n
\r\n );\r\n }\r\n}\r\n\r\nexport default withRouter(Signin);\r\n","import React from \"react\";\r\nimport { withRouter } from \"react-router-dom\";\r\n\r\nimport { Mutation } from \"react-apollo\";\r\nimport { SIGNUP_USER } from \"../../queries\";\r\nimport Error from \"../Error\";\r\n\r\nconst initialState = {\r\n username: \"\",\r\n email: \"\",\r\n password: \"\",\r\n passwordConfirmation: \"\"\r\n};\r\n\r\nclass Signup extends React.Component {\r\n state = { ...initialState };\r\n\r\n clearState = () => {\r\n this.setState({ ...initialState });\r\n };\r\n\r\n handleChange = event => {\r\n const { name, value } = event.target;\r\n this.setState({\r\n [name]: value\r\n });\r\n };\r\n\r\n handleSubmit = (event, signupUser) => {\r\n event.preventDefault();\r\n signupUser().then(async ({ data }) => {\r\n localStorage.setItem(\"token\", data.signupUser.token);\r\n await this.props.refetch();\r\n this.clearState();\r\n this.props.history.push(\"/\");\r\n });\r\n };\r\n\r\n validateForm = () => {\r\n const { username, email, password, passwordConfirmation } = this.state;\r\n const isInvalid =\r\n !username || !email || !password || password !== passwordConfirmation;\r\n return isInvalid;\r\n };\r\n\r\n render() {\r\n const { username, email, password, passwordConfirmation } = this.state;\r\n\r\n return (\r\n
\r\n

Signup

\r\n \r\n {(signupUser, { data, loading, error }) => {\r\n return (\r\n this.handleSubmit(event, signupUser)}\r\n >\r\n \r\n \r\n \r\n \r\n \r\n Submit\r\n \r\n {error && }\r\n \r\n );\r\n }}\r\n \r\n
\r\n );\r\n }\r\n}\r\n\r\nexport default withRouter(Signup);\r\n","import React from \"react\";\r\nimport { Query } from \"react-apollo\";\r\nimport { GET_CURRENT_USER } from \"../queries\";\r\n\r\nconst withSession = Component => props => (\r\n \r\n {({ data, loading, refetch }) => {\r\n if (loading) return null;\r\n return ;\r\n }}\r\n \r\n);\r\n\r\nexport default withSession;\r\n","import React from \"react\";\r\nimport { Link } from \"react-router-dom\";\r\n\r\nconst SearchItem = ({ _id, name, likes }) => (\r\n
  • \r\n \r\n

    {name}

    \r\n \r\n

    Likes: {likes}

    \r\n
  • \r\n);\r\n\r\nexport default SearchItem;\r\n","import React from \"react\";\r\nimport { ApolloConsumer } from \"react-apollo\";\r\nimport { SEARCH_RECIPES } from \"../../queries\";\r\nimport SearchItem from \"./SearchItem\";\r\n\r\nclass Search extends React.Component {\r\n state = {\r\n searchRecipes: []\r\n };\r\n\r\n handleChange = ({ searchRecipes }) => {\r\n this.setState({\r\n searchRecipes\r\n });\r\n };\r\n\r\n render() {\r\n const { searchRecipes } = this.state;\r\n return (\r\n \r\n {client => (\r\n
    \r\n

    Search

    \r\n {\r\n event.persist();\r\n const { data } = await client.query({\r\n query: SEARCH_RECIPES,\r\n variables: { searchTerm: event.target.value }\r\n });\r\n this.handleChange(data);\r\n }}\r\n />\r\n
      \r\n {searchRecipes.map(recipe => (\r\n \r\n ))}\r\n
    \r\n
    \r\n )}\r\n
    \r\n );\r\n }\r\n}\r\n\r\nexport default Search;\r\n","import React from \"react\";\r\nimport { Query } from \"react-apollo\";\r\nimport { Redirect } from \"react-router-dom\";\r\nimport { GET_CURRENT_USER } from \"../queries\";\r\n\r\nconst withAuth = conditionFunc => Component => props => (\r\n \r\n {(data, loading, error) => {\r\n if (loading) return null;\r\n return conditionFunc(data) ? (\r\n \r\n ) : (\r\n \r\n );\r\n }}\r\n \r\n);\r\n\r\nexport default withAuth;\r\n","import React from \"react\";\r\nimport CKEditor from \"react-ckeditor-component\";\r\nimport { withRouter } from \"react-router-dom\";\r\n\r\nimport { Mutation } from \"react-apollo\";\r\nimport {\r\n ADD_RECIPE,\r\n GET_ALL_RECIPES,\r\n GET_USER_RECIPES,\r\n GET_CURRENT_USER\r\n} from \"../../queries\";\r\nimport Error from \"../Error\";\r\nimport withAuth from \"../withAuth\";\r\nimport Spinner from \"../Spinner\";\r\n\r\nconst initialState = {\r\n name: \"\",\r\n imageUrl: \"\",\r\n category: \"Breakfast\",\r\n description: \"\",\r\n instructions: \"\",\r\n username: \"\"\r\n};\r\n\r\nclass AddRecipe extends React.Component {\r\n state = { ...initialState };\r\n\r\n clearState = () => {\r\n this.setState({ ...initialState });\r\n };\r\n\r\n validateForm = () => {\r\n const {\r\n name,\r\n imageUrl,\r\n category,\r\n description,\r\n instructions,\r\n username\r\n } = this.state;\r\n const isInvalid =\r\n !name ||\r\n !imageUrl ||\r\n !category ||\r\n !description ||\r\n !instructions ||\r\n !username;\r\n return isInvalid;\r\n };\r\n\r\n handleChange = event => {\r\n const { name, value } = event.target;\r\n this.setState({\r\n [name]: value\r\n });\r\n };\r\n\r\n handleEditChange = event => {\r\n const newContent = event.editor.getData();\r\n this.setState({ instructions: newContent });\r\n };\r\n\r\n handleSubmit = (event, addRecipe) => {\r\n event.preventDefault();\r\n addRecipe().then(({ data }) => {\r\n this.clearState();\r\n this.props.history.push(\"/\");\r\n });\r\n };\r\n\r\n updateCache = (cache, { data: { addRecipe } }) => {\r\n const { getAllRecipes } = cache.readQuery({ query: GET_ALL_RECIPES });\r\n cache.writeQuery({\r\n query: GET_ALL_RECIPES,\r\n data: {\r\n getAllRecipes: [addRecipe, ...getAllRecipes]\r\n }\r\n });\r\n };\r\n\r\n componentDidMount() {\r\n this.setState({\r\n username: this.props.session.getCurrentUser.username\r\n });\r\n }\r\n\r\n render() {\r\n const {\r\n name,\r\n imageUrl,\r\n category,\r\n description,\r\n instructions,\r\n username\r\n } = this.state;\r\n\r\n return (\r\n [\r\n { query: GET_USER_RECIPES, variables: { username } },\r\n { query: GET_CURRENT_USER }\r\n ]}\r\n update={this.updateCache}\r\n >\r\n {(addRecipe, { data, loading, error }) => {\r\n if (loading) return ;\r\n return (\r\n
    \r\n

    Add Recipe

    \r\n this.handleSubmit(event, addRecipe)}\r\n >\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n {/* */}\r\n \r\n Submit\r\n \r\n {error && }\r\n \r\n
    \r\n );\r\n }}\r\n \r\n );\r\n }\r\n}\r\n\r\nexport default withAuth(session => session && session.data.getCurrentUser)(\r\n withRouter(AddRecipe)\r\n);\r\n","import React from \"react\";\r\nimport { Mutation } from \"react-apollo\";\r\nimport { UNLIKE_RECIPE, LIKE_RECIPE, GET_RECIPE } from \"../../queries\";\r\nimport withSession from \"../withSession\";\r\n\r\nclass LikeRecipe extends React.Component {\r\n state = {\r\n liked: false,\r\n username: \"\"\r\n };\r\n\r\n componentDidMount = () => {\r\n console.log(this.props);\r\n if (this.props.session.getCurrentUser) {\r\n const { username, favorites } = this.props.session.getCurrentUser;\r\n const { _id } = this.props;\r\n const prevLiked =\r\n favorites.findIndex(favorite => favorite._id === _id) > -1;\r\n this.setState({ liked: prevLiked, username });\r\n }\r\n };\r\n\r\n handleClick = (likeRecipe, unlikeRecipe) => {\r\n this.setState(\r\n prevState => ({\r\n liked: !prevState.liked\r\n }),\r\n () => this.handleLike(likeRecipe, unlikeRecipe)\r\n );\r\n };\r\n\r\n handleLike = (likeRecipe, unlikeRecipe) => {\r\n if (this.state.liked) {\r\n likeRecipe().then(async ({ data }) => {\r\n await this.props.refetch();\r\n });\r\n } else {\r\n unlikeRecipe().then(async ({ data }) => {\r\n await this.props.refetch();\r\n });\r\n }\r\n };\r\n\r\n updateLike = (cache, { data: { likeRecipe } }) => {\r\n const { _id } = this.props;\r\n const { getRecipe } = cache.readQuery({\r\n query: GET_RECIPE,\r\n variables: { _id }\r\n });\r\n cache.writeQuery({\r\n query: GET_RECIPE,\r\n variables: { _id },\r\n data: {\r\n getRecipe: { ...getRecipe, likes: likeRecipe.likes + 1 }\r\n }\r\n });\r\n };\r\n\r\n updateUnlike = (cache, { data: { unlikeRecipe } }) => {\r\n const { _id } = this.props;\r\n const { getRecipe } = cache.readQuery({\r\n query: GET_RECIPE,\r\n variables: { _id }\r\n });\r\n cache.writeQuery({\r\n query: GET_RECIPE,\r\n variables: { _id },\r\n data: {\r\n getRecipe: { ...getRecipe, likes: unlikeRecipe.likes - 1 }\r\n }\r\n });\r\n };\r\n\r\n render() {\r\n const { username, liked } = this.state;\r\n const { _id } = this.props;\r\n\r\n return (\r\n \r\n {unlikeRecipe => (\r\n \r\n {likeRecipe =>\r\n username && (\r\n this.handleClick(likeRecipe, unlikeRecipe)}\r\n >\r\n {liked ? \"Unlike\" : \"Like\"}\r\n \r\n )\r\n }\r\n \r\n )}\r\n \r\n );\r\n }\r\n}\r\n\r\nexport default withSession(LikeRecipe);\r\n","import React from \"react\";\r\nimport { withRouter } from \"react-router-dom\";\r\nimport { Query } from \"react-apollo\";\r\nimport { GET_RECIPE } from \"../../queries\";\r\nimport LikeRecipe from \"./LikeRecipe\";\r\nimport Spinner from \"../Spinner\";\r\n\r\nconst RecipePage = ({ match }) => {\r\n const { _id } = match.params;\r\n return (\r\n \r\n {({ data, loading, error }) => {\r\n if (loading) return ;\r\n if (error) return
    Error
    ;\r\n return (\r\n
    \r\n \r\n
    \r\n
    \r\n

    \r\n {data.getRecipe.name}\r\n

    \r\n
    \r\n {data.getRecipe.category}\r\n
    \r\n

    \r\n Created by {data.getRecipe.username}\r\n

    \r\n

    \r\n Created date {data.getRecipe.createdDate}\r\n

    \r\n

    \r\n {data.getRecipe.likes}{\" \"}\r\n \r\n ♥\r\n \r\n

    \r\n
    \r\n
    \r\n {data.getRecipe.description}\r\n
    \r\n

    Instructions

    \r\n \r\n \r\n
    \r\n
    \r\n );\r\n }}\r\n
    \r\n );\r\n};\r\n\r\nexport default withRouter(RecipePage);\r\n","import React from \"react\";\r\nimport { Link } from \"react-router-dom\";\r\n\r\nconst formatDate = date => {\r\n const newDate = new Date(date).toLocaleDateString(\"en-US\");\r\n const newTime = new Date(date).toLocaleTimeString(\"en-US\");\r\n return `${newDate} at ${newTime}`;\r\n};\r\n\r\nconst UserInfo = ({ session }) => (\r\n
    \r\n

    User Info

    \r\n

    Username: {session.getCurrentUser.username}

    \r\n

    E-mail: {session.getCurrentUser.email}

    \r\n

    Join Date: {formatDate(session.getCurrentUser.joinDate)}

    \r\n
      \r\n

      {session.getCurrentUser.username}'s Favorites

      \r\n {session.getCurrentUser.favorites.map(favorite => (\r\n
    • \r\n \r\n

      {favorite.name}

      \r\n {\" \"}\r\n
    • \r\n ))}\r\n {!session.getCurrentUser.favorites.length && (\r\n

      \r\n You have no favorites currently. Go add some!\r\n

      \r\n )}\r\n
    \r\n
    \r\n);\r\n\r\nexport default UserInfo;\r\n","import React from \"react\";\r\nimport { Query, Mutation } from \"react-apollo\";\r\nimport { Link } from \"react-router-dom\";\r\nimport CKEditor from \"react-ckeditor-component\";\r\nimport {\r\n GET_USER_RECIPES,\r\n UPDATE_USER_RECIPE,\r\n DELETE_USER_RECIPE,\r\n GET_ALL_RECIPES,\r\n GET_CURRENT_USER\r\n} from \"../../queries\";\r\nimport Spinner from \"../Spinner\";\r\n\r\nclass UserRecipes extends React.Component {\r\n state = {\r\n _id: \"\",\r\n name: \"\",\r\n imageUrl: \"\",\r\n category: \"Breakfast\",\r\n description: \"\",\r\n instructions: \"\",\r\n modal: false\r\n };\r\n\r\n handleChange = event => {\r\n const { name, value } = event.target;\r\n this.setState({\r\n [name]: value\r\n });\r\n };\r\n\r\n handleEditChange = event => {\r\n const newContent = event.editor.getData();\r\n this.setState({ instructions: newContent });\r\n };\r\n\r\n handleDelete = deleteUserRecipe => {\r\n const confirmDelete = window.confirm(\r\n \"Are you sure you want to delete this recipe?\"\r\n );\r\n if (confirmDelete) {\r\n deleteUserRecipe().then(({ data }) => {\r\n //\r\n });\r\n }\r\n };\r\n\r\n handleSubmit = (event, updateUserRecipe) => {\r\n event.preventDefault();\r\n updateUserRecipe().then(({ data }) => {\r\n console.log(data);\r\n this.closeModal();\r\n });\r\n };\r\n\r\n loadRecipe = recipe => {\r\n this.setState({ ...recipe, modal: true });\r\n };\r\n\r\n closeModal = () => {\r\n this.setState({ modal: false });\r\n };\r\n\r\n render() {\r\n const { username } = this.props;\r\n const { modal } = this.state;\r\n return (\r\n \r\n {({ data, loading, error }) => {\r\n if (loading) return ;\r\n if (error) return
    Error
    ;\r\n return (\r\n
      \r\n {modal && (\r\n \r\n )}\r\n

      Your Recipes

      \r\n {!data.getUserRecipes.length && (\r\n

      \r\n You have not added any recipes yet.\r\n

      \r\n )}\r\n {data.getUserRecipes.map(recipe => (\r\n
    • \r\n \r\n

      {recipe.name}

      \r\n \r\n

      Likes: {recipe.likes}

      \r\n [\r\n { query: GET_ALL_RECIPES },\r\n { query: GET_CURRENT_USER }\r\n ]}\r\n update={(cache, { data: { deleteUserRecipe } }) => {\r\n const { getUserRecipes } = cache.readQuery({\r\n query: GET_USER_RECIPES,\r\n variables: { username }\r\n });\r\n cache.writeQuery({\r\n query: GET_USER_RECIPES,\r\n variables: { username },\r\n data: {\r\n getUserRecipes: getUserRecipes.filter(\r\n recipe => recipe._id !== deleteUserRecipe._id\r\n )\r\n }\r\n });\r\n }}\r\n >\r\n {(deleteUserRecipe, attrs = {}) => (\r\n \r\n this.loadRecipe(recipe)}\r\n >\r\n Update\r\n \r\n this.handleDelete(deleteUserRecipe)}\r\n >\r\n {attrs.loading ? \"Deleting...\" : \"Delete\"}\r\n \r\n \r\n )}\r\n \r\n
    • \r\n ))}\r\n
    \r\n );\r\n }}\r\n
    \r\n );\r\n }\r\n}\r\n\r\nconst EditRecipeModal = ({\r\n handleSubmit,\r\n recipe,\r\n handleChange,\r\n handleEditChange,\r\n closeModal\r\n}) => (\r\n \r\n {updateUserRecipe => (\r\n
    \r\n
    \r\n
    \r\n handleSubmit(event, updateUserRecipe)}\r\n className=\"modal-content-inner\"\r\n >\r\n

    Edit Recipe

    \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n
    \r\n
    \r\n \r\n \r\n
    \r\n \r\n
    \r\n
    \r\n
    \r\n )}\r\n \r\n);\r\n\r\nexport default UserRecipes;\r\n","import React from \"react\";\r\nimport UserInfo from \"./UserInfo\";\r\nimport UserRecipes from \"./UserRecipes\";\r\nimport withAuth from \"../withAuth\";\r\n\r\nconst Profile = ({ session }) => (\r\n
    \r\n \r\n \r\n
    \r\n);\r\n\r\nexport default withAuth(session => session && session.data.getCurrentUser)(\r\n Profile\r\n);\r\n","import React from \"react\";\r\nimport { withRouter } from \"react-router-dom\";\r\nimport { ApolloConsumer } from \"react-apollo\";\r\n\r\nconst handleSignout = (client, history) => {\r\n localStorage.removeItem(\"token\");\r\n client.resetStore();\r\n history.push(\"/\");\r\n};\r\n\r\nconst Signout = ({ history }) => (\r\n \r\n {client => {\r\n return (\r\n \r\n );\r\n }}\r\n \r\n);\r\n\r\nexport default withRouter(Signout);\r\n","import React, { Fragment } from \"react\";\r\nimport { NavLink } from \"react-router-dom\";\r\nimport Signout from \"../components/Auth/Signout\";\r\n\r\nconst Navbar = ({ session }) => (\r\n \r\n);\r\n\r\nconst NavbarAuth = ({ session }) => (\r\n \r\n
      \r\n
    • \r\n \r\n Home\r\n \r\n
    • \r\n
    • \r\n Search\r\n
    • \r\n
    • \r\n Add Recipe\r\n
    • \r\n
    • \r\n Profile\r\n
    • \r\n
    • \r\n \r\n
    • \r\n
    \r\n

    \r\n Welcome, {session.getCurrentUser.username}\r\n

    \r\n
    \r\n);\r\n\r\nconst NavbarUnAuth = () => (\r\n
      \r\n
    • \r\n \r\n Home\r\n \r\n
    • \r\n
    • \r\n Search\r\n
    • \r\n
    • \r\n Signin\r\n
    • \r\n
    • \r\n Signup\r\n
    • \r\n
    \r\n);\r\n\r\nexport default Navbar;\r\n","import React, { Fragment } from \"react\";\nimport ReactDOM from \"react-dom\";\nimport {\n BrowserRouter as Router,\n Route,\n Switch,\n Redirect\n} from \"react-router-dom\";\n\nimport \"./index.css\";\nimport App from \"./components/App\";\nimport Signin from \"./components/Auth/Signin\";\nimport Signup from \"./components/Auth/Signup\";\nimport withSession from \"./components/withSession\";\nimport Search from \"./components/Recipe/Search\";\nimport AddRecipe from \"./components/Recipe/AddRecipe\";\nimport RecipePage from \"./components/Recipe/RecipePage\";\nimport Profile from \"./components/Profile/Profile\";\nimport Navbar from \"./components/Navbar\";\n\nimport ApolloClient from \"apollo-boost\";\nimport { ApolloProvider } from \"react-apollo\";\n\nconst client = new ApolloClient({\n uri: \"http://localhost:4444/graphql\",\n //uri: \"https://react-apollo-recipes-hide.herokuapp.com/graphql\",\n fetchOptions: {\n credentials: \"include\"\n },\n request: operation => {\n const token = localStorage.getItem(\"token\");\n operation.setContext({\n headers: {\n authorization: token\n }\n });\n },\n onError: ({ networkError }) => {\n if (networkError) {\n localStorage.setItem(\"token\", \"\");\n }\n }\n});\n\nconst Root = ({ refetch, session }) => (\n \n \n \n \n \n \n } />\n }\n />\n \n } />\n } />\n \n \n \n \n);\n\nconst RootWithSession = withSession(Root);\n\nReactDOM.render(\n \n \n ,\n document.getElementById(\"root\")\n);\n"],"sourceRoot":""} -------------------------------------------------------------------------------- /public/static/js/runtime~main.a8a9905a.js: -------------------------------------------------------------------------------- 1 | !function(e){function r(r){for(var n,f,i=r[0],l=r[1],a=r[2],c=0,s=[];c