-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathapp.rb
More file actions
172 lines (142 loc) · 4.64 KB
/
app.rb
File metadata and controls
172 lines (142 loc) · 4.64 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
require "bundler/setup"
# Load the appropriate gem groups depending on environment.
# - In production (or on Render), we load only :default and :production gems.
# - In development, we load :default and :development gems.
if ENV['RACK_ENV'] == 'production' || ENV['RENDER']
Bundler.require(:default, :production)
else
Bundler.require(:default, :development)
end
require "sinatra"
require "graphql"
require "json"
# Enable Sinatra auto-reloading only in development.
# This lets the server restart automatically when files change.
configure :development do
require "sinatra/reloader"
end
# In-memory sample user data.
# This acts as a small mock database for demo purposes.
USERS = [
{ id: 1, name: "Alice", email: "alice@example.com" },
{ id: 2, name: "Bob", email: "bob@example.com" },
{ id: 3, name: "Carol", email: "carol@example.com" }
]
# -------------------------------
# GraphQL Type Definitions
# These types define the structure of returned data.
# -------------------------------
class UserType < GraphQL::Schema::Object
# A user has 3 fields: id, name, email.
field :id, ID, null: false
field :name, String, null: false
field :email, String, null: false
end
class MessageType < GraphQL::Schema::Object
# Returned by the sendMessage mutation.
field :message, String, null: false
field :timestamp, String, null: false
end
# -------------------------------
# GraphQL Query Root
# This defines all available read-only operations.
# -------------------------------
class QueryType < GraphQL::Schema::Object
# A simple "hello" field for testing.
field :hello, String, null: false
# Returns an array of all users.
field :users, [UserType], null: false
# Returns a single user by ID.
field :user, UserType, null: true do
argument :id, ID, required: true
end
# Resolver for hello
def hello
"Hello from GraphQL!"
end
# Resolver for users list
def users
USERS
end
# Resolver for a single user by ID
def user(id:)
USERS.find { |u| u[:id].to_s == id.to_s }
end
end
# -------------------------------
# GraphQL Mutation Root
# This defines write/update operations.
# -------------------------------
class MutationType < GraphQL::Schema::Object
# A mutation that accepts a message and returns it with a timestamp.
field :send_message, MessageType, null: false do
argument :message, String, required: true
end
# Mutation resolver
def send_message(message:)
{ message: message, timestamp: Time.now.to_s }
end
end
# -------------------------------
# GraphQL Schema Configuration
# Connects Query and Mutation to the schema object.
# -------------------------------
class MySchema < GraphQL::Schema
query(QueryType)
mutation(MutationType)
end
# -------------------------------
# GraphQL HTTP Endpoint (POST)
# All GraphQL requests are sent to /graphql.
# -------------------------------
post "/graphql" do
# Parse JSON request body.
payload = JSON.parse(request.body.read)
# Execute the GraphQL query with optional variables.
result = MySchema.execute(payload["query"], variables: payload["variables"])
# Return JSON response.
content_type :json
result.to_json
end
# -------------------------------
# GraphiQL Web UI
# Available at the root path `/`.
# This is an in-browser IDE for GraphQL queries and mutations.
# -------------------------------
get "/" do
content_type :html
<<-HTML
<!DOCTYPE html>
<html>
<head>
<title>Ruby GraphQL Server</title>
<!-- Load GraphiQL CSS -->
<link href="https://unpkg.com/graphiql@2.2.0/graphiql.min.css" rel="stylesheet" />
</head>
<body style="margin:0; height:100vh;">
<!-- GraphiQL UI container -->
<div id="graphiql" style="height:100vh;"></div>
<!-- Load React (required by GraphiQL) -->
<script src="https://unpkg.com/react@18.2.0/umd/react.production.min.js"></script>
<!-- Load ReactDOM (required by GraphiQL) -->
<script src="https://unpkg.com/react-dom@18.2.0/umd/react-dom.production.min.js"></script>
<!-- Load GraphiQL library -->
<script src="https://unpkg.com/graphiql@2.2.0/graphiql.min.js"></script>
<script>
// GraphQL fetcher function used by the GraphiQL UI.
const graphQLFetcher = graphQLParams =>
fetch('/graphql', {
method: 'post',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(graphQLParams),
}).then(response => response.json());
// Render GraphiQL into the page.
ReactDOM.render(
React.createElement(GraphiQL, { fetcher: graphQLFetcher }),
document.getElementById('graphiql')
);
</script>
</body>
</html>
HTML
end