1use std::collections::HashMap;
7use std::sync::Arc;
8
9use axum::extract::{Path, Query, State};
10use axum::Json;
11
12use crate::error::PipelineError;
13use crate::pipeline::{QueryInput, QueryPipeline};
14
15use super::builder;
16use super::types::*;
17
18pub async fn handle_entity_insert(
22 State(pipeline): State<Arc<QueryPipeline>>,
23 Path(type_name): Path<String>,
24 Json(req): Json<EntityInsertRequest>,
25) -> Result<Json<CrudResponse>, PipelineError> {
26 let schema = pipeline
27 .schema()
28 .ok_or_else(|| PipelineError::Schema("No schema loaded".to_string()))?;
29
30 let clauses = builder::build_entity_insert(&type_name, &req.attributes, schema)?;
31
32 let typeql = type_bridge_core_lib::compiler::QueryCompiler::new().compile(&clauses);
33
34 let output = pipeline
35 .execute_query(QueryInput {
36 database: req.database,
37 transaction_type: "write".to_string(),
38 clauses,
39 metadata: HashMap::new(),
40 })
41 .await?;
42
43 Ok(Json(CrudResponse {
44 status: "ok".to_string(),
45 results: output.results,
46 metadata: CrudMetadata {
47 request_id: output.request_id,
48 execution_time_ms: output.execution_time_ms,
49 typeql,
50 },
51 }))
52}
53
54pub async fn handle_entity_fetch(
58 State(pipeline): State<Arc<QueryPipeline>>,
59 Path(type_name): Path<String>,
60 Query(req): Query<EntityFetchQuery>,
61) -> Result<Json<CrudResponse>, PipelineError> {
62 let schema = pipeline
63 .schema()
64 .ok_or_else(|| PipelineError::Schema("No schema loaded".to_string()))?;
65
66 let clauses = builder::build_entity_fetch(
67 &type_name,
68 &[],
69 &[],
70 req.limit,
71 req.offset,
72 schema,
73 )?;
74
75 let typeql = type_bridge_core_lib::compiler::QueryCompiler::new().compile(&clauses);
76
77 let output = pipeline
78 .execute_query(QueryInput {
79 database: req.database,
80 transaction_type: "read".to_string(),
81 clauses,
82 metadata: HashMap::new(),
83 })
84 .await?;
85
86 Ok(Json(CrudResponse {
87 status: "ok".to_string(),
88 results: output.results,
89 metadata: CrudMetadata {
90 request_id: output.request_id,
91 execution_time_ms: output.execution_time_ms,
92 typeql,
93 },
94 }))
95}
96
97#[derive(Debug, serde::Deserialize)]
99pub struct EntityFetchQuery {
100 pub database: Option<String>,
101 pub limit: Option<u64>,
102 pub offset: Option<u64>,
103}
104
105pub async fn handle_entity_get_by_iid(
109 State(pipeline): State<Arc<QueryPipeline>>,
110 Path((type_name, iid)): Path<(String, String)>,
111 Query(params): Query<DatabaseParam>,
112) -> Result<Json<CrudResponse>, PipelineError> {
113 let schema = pipeline
114 .schema()
115 .ok_or_else(|| PipelineError::Schema("No schema loaded".to_string()))?;
116
117 let clauses = builder::build_entity_fetch_by_iid(&type_name, &iid, schema)?;
118
119 let typeql = type_bridge_core_lib::compiler::QueryCompiler::new().compile(&clauses);
120
121 let output = pipeline
122 .execute_query(QueryInput {
123 database: params.database,
124 transaction_type: "read".to_string(),
125 clauses,
126 metadata: HashMap::new(),
127 })
128 .await?;
129
130 Ok(Json(CrudResponse {
131 status: "ok".to_string(),
132 results: output.results,
133 metadata: CrudMetadata {
134 request_id: output.request_id,
135 execution_time_ms: output.execution_time_ms,
136 typeql,
137 },
138 }))
139}
140
141pub async fn handle_entity_update(
145 State(pipeline): State<Arc<QueryPipeline>>,
146 Path((type_name, iid)): Path<(String, String)>,
147 Json(req): Json<EntityUpdateRequest>,
148) -> Result<Json<CrudResponse>, PipelineError> {
149 let schema = pipeline
150 .schema()
151 .ok_or_else(|| PipelineError::Schema("No schema loaded".to_string()))?;
152
153 let clauses =
154 builder::build_entity_update_by_iid(&type_name, &iid, &req.attributes, schema)?;
155
156 let typeql = type_bridge_core_lib::compiler::QueryCompiler::new().compile(&clauses);
157
158 let output = pipeline
159 .execute_query(QueryInput {
160 database: req.database,
161 transaction_type: "write".to_string(),
162 clauses,
163 metadata: HashMap::new(),
164 })
165 .await?;
166
167 Ok(Json(CrudResponse {
168 status: "ok".to_string(),
169 results: output.results,
170 metadata: CrudMetadata {
171 request_id: output.request_id,
172 execution_time_ms: output.execution_time_ms,
173 typeql,
174 },
175 }))
176}
177
178pub async fn handle_entity_delete(
182 State(pipeline): State<Arc<QueryPipeline>>,
183 Path((type_name, iid)): Path<(String, String)>,
184 Query(params): Query<DatabaseParam>,
185) -> Result<Json<CrudResponse>, PipelineError> {
186 let schema = pipeline
187 .schema()
188 .ok_or_else(|| PipelineError::Schema("No schema loaded".to_string()))?;
189
190 let clauses = builder::build_entity_delete_by_iid(&type_name, &iid, schema)?;
191
192 let typeql = type_bridge_core_lib::compiler::QueryCompiler::new().compile(&clauses);
193
194 let output = pipeline
195 .execute_query(QueryInput {
196 database: params.database,
197 transaction_type: "write".to_string(),
198 clauses,
199 metadata: HashMap::new(),
200 })
201 .await?;
202
203 Ok(Json(CrudResponse {
204 status: "ok".to_string(),
205 results: output.results,
206 metadata: CrudMetadata {
207 request_id: output.request_id,
208 execution_time_ms: output.execution_time_ms,
209 typeql,
210 },
211 }))
212}
213
214pub async fn handle_relation_insert(
218 State(pipeline): State<Arc<QueryPipeline>>,
219 Path(type_name): Path<String>,
220 Json(req): Json<RelationInsertRequest>,
221) -> Result<Json<CrudResponse>, PipelineError> {
222 let schema = pipeline
223 .schema()
224 .ok_or_else(|| PipelineError::Schema("No schema loaded".to_string()))?;
225
226 let clauses = builder::build_relation_insert(
227 &type_name,
228 &req.role_players,
229 &req.attributes,
230 schema,
231 )?;
232
233 let typeql = type_bridge_core_lib::compiler::QueryCompiler::new().compile(&clauses);
234
235 let output = pipeline
236 .execute_query(QueryInput {
237 database: req.database,
238 transaction_type: "write".to_string(),
239 clauses,
240 metadata: HashMap::new(),
241 })
242 .await?;
243
244 Ok(Json(CrudResponse {
245 status: "ok".to_string(),
246 results: output.results,
247 metadata: CrudMetadata {
248 request_id: output.request_id,
249 execution_time_ms: output.execution_time_ms,
250 typeql,
251 },
252 }))
253}
254
255pub async fn handle_relation_fetch(
259 State(pipeline): State<Arc<QueryPipeline>>,
260 Path(type_name): Path<String>,
261 Query(req): Query<EntityFetchQuery>,
262) -> Result<Json<CrudResponse>, PipelineError> {
263 let schema = pipeline
264 .schema()
265 .ok_or_else(|| PipelineError::Schema("No schema loaded".to_string()))?;
266
267 let clauses = builder::build_relation_fetch(
268 &type_name,
269 &[],
270 &[],
271 req.limit,
272 req.offset,
273 schema,
274 )?;
275
276 let typeql = type_bridge_core_lib::compiler::QueryCompiler::new().compile(&clauses);
277
278 let output = pipeline
279 .execute_query(QueryInput {
280 database: req.database,
281 transaction_type: "read".to_string(),
282 clauses,
283 metadata: HashMap::new(),
284 })
285 .await?;
286
287 Ok(Json(CrudResponse {
288 status: "ok".to_string(),
289 results: output.results,
290 metadata: CrudMetadata {
291 request_id: output.request_id,
292 execution_time_ms: output.execution_time_ms,
293 typeql,
294 },
295 }))
296}
297
298pub async fn handle_relation_delete(
302 State(pipeline): State<Arc<QueryPipeline>>,
303 Path((type_name, iid)): Path<(String, String)>,
304 Query(params): Query<DatabaseParam>,
305) -> Result<Json<CrudResponse>, PipelineError> {
306 let schema = pipeline
307 .schema()
308 .ok_or_else(|| PipelineError::Schema("No schema loaded".to_string()))?;
309
310 let clauses = builder::build_relation_delete_by_iid(&type_name, &iid, schema)?;
311
312 let typeql = type_bridge_core_lib::compiler::QueryCompiler::new().compile(&clauses);
313
314 let output = pipeline
315 .execute_query(QueryInput {
316 database: params.database,
317 transaction_type: "write".to_string(),
318 clauses,
319 metadata: HashMap::new(),
320 })
321 .await?;
322
323 Ok(Json(CrudResponse {
324 status: "ok".to_string(),
325 results: output.results,
326 metadata: CrudMetadata {
327 request_id: output.request_id,
328 execution_time_ms: output.execution_time_ms,
329 typeql,
330 },
331 }))
332}
333
334#[derive(Debug, serde::Deserialize)]
336pub struct DatabaseParam {
337 pub database: Option<String>,
338}