Skip to main content

product_os_service_handler/
lib.rs

1//! Product OS Service Handler
2//!
3//! A FeathersJS-compatible service handler that provides CRUD operations for database tables
4//! through a REST API interface compatible with FeathersJS clients.
5//!
6//! # Overview
7//!
8//! This crate implements the [FeathersJS](https://feathersjs.com/) service pattern, allowing
9//! seamless integration between Rust backends and FeathersJS clients. It provides:
10//!
11//! - **find**: Query multiple records with pagination, filtering, and sorting
12//! - **get**: Retrieve a single record by ID
13//! - **create**: Insert new records into the database
14//! - **patch**: Partially update existing records  
15//! - **remove**: Delete records from the database
16//! - **update**: Full record replacement (not yet implemented)
17//!
18//! # FeathersJS Compatibility
19//!
20//! The service handler implements the standard FeathersJS query syntax including:
21//! - Query operators: `$limit`, `$skip`, `$sort`, `$select`
22//! - Comparison operators: `$lt`, `$lte`, `$gt`, `$gte`, `$ne`, `$in`, `$nin`
23//! - Logical operators: `$or`
24//! - Wildcard search with `*`
25//!
26//! # Example
27//!
28//! ```rust,no_run
29//! use std::sync::Arc;
30//! use parking_lot::Mutex;
31//! use product_os_service_handler::ProductOSServiceHandler;
32//! # use product_os_command_control::ProductOSController;
33//! # use product_os_router::ProductOSRouter;
34//!
35//! # async fn example(controller: Arc<Mutex<ProductOSController>>) -> Result<(), Box<dyn std::error::Error>> {
36//! // Create a service for the "users" table
37//! let service = ProductOSServiceHandler::new(
38//!     "users".to_string(),
39//!     "/api/users".to_string(),
40//!     "users".to_string(),
41//!     "id".to_string(),
42//!     controller
43//! );
44//!
45//! // Load the service into a router
46//! let mut router = ProductOSRouter::new();
47//! service.load_service(&mut router).await;
48//! # Ok(())
49//! # }
50//! ```
51//!
52//! # Features
53//!
54//! - `postgres_store` - Enable PostgreSQL database support
55//! - `sqlite_store` - Enable SQLite database support
56//!
57//! # Architecture
58//!
59//! The handler follows a layered architecture:
60//! 1. **HTTP Layer**: Route handlers process HTTP requests
61//! 2. **Conversion Layer**: Transform between JSON and database formats
62//! 3. **Database Layer**: Execute queries via `ProductOSRelationalStore`
63
64use std::collections::HashMap;
65use std::sync::Arc;
66use parking_lot::Mutex;
67use product_os_capabilities::{Feature, RegistryFeature, What};
68use product_os_command_control::ProductOSController;
69use product_os_router::{Body, State, ProductOSRouterError, Json, MethodRouter, Path, Query, Response, StatusCode};
70use product_os_store::{ProductOSRelationalStore, RelationalRow, Expression, RelationalError};
71
72use lazy_static::lazy_static;
73use regex::Regex;
74use std::str::FromStr;
75
76pub use async_trait::async_trait;
77use serde_json::Value;
78
79lazy_static! {
80    /// Regex pattern for parsing array and object notation in query parameters.
81    ///
82    /// Matches patterns like `[key]` or `[]` in query strings to support nested
83    /// object and array access in FeathersJS style queries.
84    ///
85    /// Examples:
86    /// - `user[name]` - Object property access
87    /// - `tags[]` - Array element
88    /// - `filters[age][$gt]` - Nested object access
89    static ref OBJECT_ARRAY_ELEMENT_REGEX: Regex = Regex::new(r"\[([%$a-zA-Z0-9_-]*)\]").unwrap();
90}
91
92/// Product OS Service Handler
93///
94/// A FeathersJS-compatible service handler that manages CRUD operations for a specific
95/// database table. Each handler instance is bound to a single table and provides
96/// RESTful endpoints following the FeathersJS service pattern.
97///
98/// # Fields
99///
100/// - `name`: Service identifier (e.g., "users")
101/// - `path`: URL path for the service (e.g., "/api/users")
102/// - `table_name`: Database table name
103/// - `identifier_name`: Primary key column name (e.g., "id")
104/// - `controller`: Reference to the ProductOS controller
105/// - `store`: Database connection and query interface
106/// - `default_limit`: Default pagination limit
107/// - `default_offset`: Default pagination offset
108///
109/// # Thread Safety
110///
111/// This struct is thread-safe and can be safely shared across threads using `Arc`.
112/// The internal `ProductOSRelationalStore` uses connection pooling for concurrent access.
113///
114/// # Example
115///
116/// ```rust,no_run
117/// # use std::sync::Arc;
118/// # use parking_lot::Mutex;
119/// # use product_os_service_handler::ProductOSServiceHandler;
120/// # use product_os_command_control::ProductOSController;
121/// # async fn example(controller: Arc<Mutex<ProductOSController>>) {
122/// let service = ProductOSServiceHandler::new(
123///     "products".to_string(),
124///     "/api/products".to_string(),
125///     "products".to_string(),
126///     "product_id".to_string(),
127///     controller
128/// );
129/// # }
130/// ```
131pub struct ProductOSServiceHandler {
132    name: String,
133    path: String,
134
135    table_name: String,
136    identifier_name: String,
137
138    controller: Option<Arc<Mutex<ProductOSController>>>,
139    store: Arc<ProductOSRelationalStore>,
140
141    default_limit: Option<u32>,
142    default_offset: Option<u32>
143}
144
145impl ProductOSServiceHandler {
146    /// Creates a new service handler instance
147    ///
148    /// This method initializes a service handler bound to a specific database table.
149    /// It extracts configuration from the controller including default pagination
150    /// settings and database connection information.
151    ///
152    /// # Arguments
153    ///
154    /// * `name` - The service identifier (e.g., "users", "products")
155    /// * `path` - The URL path where this service will be mounted (e.g., "/api/users")
156    /// * `table_name` - The name of the database table this service manages
157    /// * `identifier_name` - The primary key column name (e.g., "id", "user_id")
158    /// * `controller` - Shared reference to the ProductOS controller
159    ///
160    /// # Returns
161    ///
162    /// A new `ProductOSServiceHandler` instance configured with the specified parameters.
163    ///
164    /// # Example
165    ///
166    /// ```rust,no_run
167    /// # use std::sync::Arc;
168    /// # use parking_lot::Mutex;
169    /// # use product_os_service_handler::ProductOSServiceHandler;
170    /// # use product_os_command_control::ProductOSController;
171    /// # async fn example(controller: Arc<Mutex<ProductOSController>>) {
172    /// let service = ProductOSServiceHandler::new(
173    ///     "users".to_string(),
174    ///     "/api/users".to_string(),
175    ///     "users".to_string(),
176    ///     "id".to_string(),
177    ///     controller
178    /// );
179    /// # }
180    /// ```
181    pub fn new(name: String, path: String, table_name: String, identifier_name: String, controller: Arc<Mutex<ProductOSController>>) -> Self {
182        let controller_unlocked = controller.clone();
183        let mut controller_locked = controller_unlocked.lock();
184
185        let store = controller_locked.get_relational_store();
186
187        let default_limit = Some(controller_locked.get_configuration().get_store_relational_default_limit());
188        let default_offset = Some(controller_locked.get_configuration().get_store_relational_default_offset());
189
190        Self {
191            name,
192            path,
193
194            table_name,
195            identifier_name,
196
197            controller: Some(controller),
198            store,
199
200            default_limit,
201            default_offset
202        }
203    }
204
205    /// Registers this service with a router
206    ///
207    /// This method registers the service with the ProductOS controller and adds
208    /// all necessary routes to the provided router. It sets up both collection
209    /// routes (for find/create) and individual resource routes (for get/update/patch/remove).
210    ///
211    /// # Arguments
212    ///
213    /// * `router` - Mutable reference to the ProductOS router where routes will be registered
214    ///
215    /// # Routes Created
216    ///
217    /// - `GET {path}` - Find multiple records
218    /// - `POST {path}` - Create a new record
219    /// - `GET {path}/:id` - Get a single record
220    /// - `PUT {path}/:id` - Update a record (not implemented)
221    /// - `PATCH {path}/:id` - Patch a record
222    /// - `DELETE {path}/:id` - Remove a record
223    ///
224    /// # Example
225    ///
226    /// ```rust,no_run
227    /// # use std::sync::Arc;
228    /// # use parking_lot::Mutex;
229    /// # use product_os_service_handler::ProductOSServiceHandler;
230    /// # use product_os_command_control::ProductOSController;
231    /// # use product_os_router::ProductOSRouter;
232    /// # async fn example(controller: Arc<Mutex<ProductOSController>>) {
233    /// let service = ProductOSServiceHandler::new(
234    ///     "users".to_string(),
235    ///     "/api/users".to_string(),
236    ///     "users".to_string(),
237    ///     "id".to_string(),
238    ///     controller
239    /// );
240    ///
241    /// let mut router = ProductOSRouter::new();
242    /// service.load_service(&mut router).await;
243    /// # }
244    /// ```
245    #[allow(clippy::await_holding_lock)] // Controller method requires the lock across the await
246    pub async fn load_service(self, router: &mut product_os_router::ProductOSRouter) {
247        if let Some(ctr) = self.controller.clone() {
248            let path = self.get_path().to_string();
249            let name = self.get_identifier_name().to_string();
250            let service_arc = Arc::new(self);
251
252            let controller_unlocked = Arc::clone(&ctr);
253            let mut controller = controller_unlocked.lock();
254            controller.add_feature(service_arc.clone(), path, router).await;
255
256            tracing::info!("Service {} successfully added to server", name);
257        }
258    }
259
260    /// Returns a reference to the relational store
261    ///
262    /// Provides access to the underlying database connection for executing queries.
263    pub fn get_store(&self) -> Arc<ProductOSRelationalStore> {
264        self.store.clone()
265    }
266
267    /// Returns the database table name
268    ///
269    /// This is the name of the table in the database that this service manages.
270    pub fn get_table_name(&self) -> String {
271        self.table_name.to_owned()
272    }
273
274    /// Returns the identifier column name
275    ///
276    /// This is the name of the primary key column used for identifying records.
277    pub fn get_identifier_name(&self) -> String {
278        self.identifier_name.to_owned()
279    }
280
281    /// Returns the service path
282    ///
283    /// This is the URL path where the service is mounted (e.g., "/api/users").
284    pub fn get_path(&self) -> String {
285        self.path.to_owned()
286    }
287
288    /// Returns the default query limit
289    ///
290    /// This limit is used when no explicit `$limit` is provided in queries.
291    pub fn get_default_limit(&self) -> Option<u32> {
292        self.default_limit
293    }
294
295    /// Returns the default query offset
296    ///
297    /// This offset is used when no explicit `$skip` is provided in queries.
298    pub fn get_default_offset(&self) -> Option<u32> {
299        self.default_offset
300    }
301
302    /// Internal: Registers HTTP routes with the router
303    ///
304    /// This private method handles the actual route registration, setting up
305    /// both collection and individual resource endpoints.
306    fn service_handler(path: String, router: &mut product_os_router::ProductOSRouter, service_handler: Arc<ProductOSServiceHandler>) {
307        let service_state = service_handler.clone();
308        
309        router.add_route(path.as_str(), MethodRouter::new()
310            .get(ProductOSServiceHandler::find)
311            .post(ProductOSServiceHandler::create)
312            .with_state(service_state.clone()));
313
314        let mut specific_path = path.to_string();
315        specific_path.push_str("/:id");
316
317        router.add_route(specific_path.as_str(), MethodRouter::new()
318            .get(ProductOSServiceHandler::get)
319            .put(ProductOSServiceHandler::update)
320            .patch(ProductOSServiceHandler::patch)
321            .delete(ProductOSServiceHandler::remove)
322            .with_state(service_state));
323    }
324
325    /*
326
327    const myService = {
328      async find(params) {
329        return [];
330      },
331      async get(id, params) {},
332      async create(data, params) {},
333      async update(id, data, params) {},
334      async patch(id, data, params) {},
335      async remove(id, params) {},
336      setup(app, path) {}
337    }
338
339    params contain additional information for the service method call. Some properties in params can be set by Feathers already. Commonly used are:
340
341    params.query - the query parameters from the client, either passed as URL query parameters (see the REST chapter) or through websockets (see Socket.io or Primus).
342    params.provider - The transport (rest, socketio or primus) used for this service call. Will be undefined for internal calls from the server (unless passed explicitly).
343    params.authentication - The authentication information to use for the authentication service
344    params.user - The authenticated user, either set by Feathers authentication or passed explicitly.
345    params.connection - If the service call has been made by a real-time transport (e.g. through websockets), params.connection is the connection object that can be used with channels.
346    params.headers - The HTTP headers connected to this service call if available. This is either the headers of the REST call or the headers passed when initializing a websocket connection.
347
348    */
349    async fn find(State(service): State<Arc<ProductOSServiceHandler>>,
350                  Query(query_params): Query<HashMap<String, Value>>) -> Response<Body> {
351        tracing::info!("FIND request received:\n{:?}", query_params);
352
353        let store: Arc<ProductOSRelationalStore> = service.get_store();
354        let table_name: String = service.get_table_name();
355        let identifier_name: String = service.get_identifier_name();
356
357        tracing::info!("Query params: {:?}", query_params);
358
359        let mut params: Vec<(String, String)> = vec!();
360        for (k, val) in query_params.clone() {
361            match val {
362                Value::String(str) => { params.push((k.to_string(), str)); }
363                Value::Array(arr) => {
364                    for v in arr {
365                        match v {
366                            Value::String(str) => { params.push((k.to_string(), str)); }
367                            _ => return ProductOSRouterError::error_response(ProductOSRouterError::Process("Query type error".to_string()), &StatusCode::INTERNAL_SERVER_ERROR)
368                        }
369                    }
370                }
371                _ => return ProductOSRouterError::error_response(ProductOSRouterError::Process("Query type error".to_string()), &StatusCode::INTERNAL_SERVER_ERROR)
372            }
373        }
374
375        // Find
376        /*
377        {
378          "total": "<total number of records>",
379          "limit": "<max number of items per page>",
380          "skip": "<number of skipped items (offset)>",
381          "data": [/* data */]
382        }
383        */
384        let query_object = query_to_object(params);
385        match query_object_to_query_expression(table_name.clone(), query_object, service.get_default_offset(), service.get_default_limit()) {
386            Ok(query_expression) => {
387                if let product_os_store::Query::QueryComplete(
388                    _, _, _, _, _, _, _, _,
389                    Some(product_os_store::Fetch::CountWithOffset(offset, limit)),
390                    _) = query_expression {
391                    let result = store.get_all_specific(&query_expression.clone()).await;
392
393                    match result {
394                        Ok(rows) => {
395                            let mut values_vec = vec!();
396
397                            for row in rows {
398                                match row_to_object(row) {
399                                    Ok(row_object) => {
400                                        let mut object = row_object.clone();
401                                        if let serde_json::Value::Object(mut obj) = row_object {
402                                            match obj.get(identifier_name.as_str()) {
403                                                None => {}
404                                                Some(id) => {
405                                                    obj.insert("_id".to_string(), id.clone());
406                                                    object = serde_json::Value::Object(obj);
407                                                }
408                                            }
409
410                                            values_vec.push(object);
411                                        }
412                                        else {
413                                            ProductOSRouterError::error_response(ProductOSRouterError::Process("Error making request - problem with object".to_string()), &StatusCode::INTERNAL_SERVER_ERROR);
414                                        }
415                                    }
416                                    Err(e) => return ProductOSRouterError::error_response(e, &StatusCode::INTERNAL_SERVER_ERROR)
417                                }
418                            }
419
420                            let rows_object = serde_json::Value::Array(values_vec);
421
422                            let total_count = match store.count(&query_expression, identifier_name.as_str()).await {
423                                Ok(value) => serde_json::Number::from(value),
424                                Err(e) => return ProductOSRouterError::error_response(ProductOSRouterError::Process(format!("Count error: {:?}", e)), &StatusCode::INTERNAL_SERVER_ERROR)
425                            };
426
427                            let mut response_object = serde_json::Map::new();
428
429                            response_object.insert(String::from("data"), rows_object);
430                            response_object.insert(String::from("total"), serde_json::Value::Number(total_count));
431                            response_object.insert(String::from("limit"), serde_json::Value::Number(serde_json::Number::from(limit)));
432                            response_object.insert(String::from("offset"), serde_json::Value::Number(serde_json::Number::from(offset)));
433
434                            let response = serde_json::Value::Object(response_object);
435
436                            Response::builder()
437                                .status(StatusCode::OK)
438                                .header("content-type", "application/json")
439                                .body(Body::from(response.to_string()))
440                                .unwrap()
441                        }
442                        Err(e) => ProductOSRouterError::error_response(ProductOSRouterError::Process(format!("Unable to fetch records: {:?}", e)), &StatusCode::INTERNAL_SERVER_ERROR)
443                    }
444                }
445                else {
446                    ProductOSRouterError::error_response(ProductOSRouterError::Process("Query type error".to_string()), &StatusCode::INTERNAL_SERVER_ERROR)
447                }
448            }
449            Err(e) => ProductOSRouterError::error_response(ProductOSRouterError::Process(format!("Problem with query: {:?}", e)), &StatusCode::BAD_REQUEST)
450        }
451    }
452
453    async fn get(State(service): State<Arc<ProductOSServiceHandler>>,
454                 Path(identifier): Path<String>,
455                 Query(query_params): Query<HashMap<String, Value>>) -> Response<Body> {
456        tracing::info!("GET request received:\n{:?}\n{:?}", identifier, query_params);
457
458        let store: Arc<ProductOSRelationalStore> = service.get_store();
459        let table_name: String = service.get_table_name();
460        let identifier_name: String = service.get_identifier_name();
461
462        let mut select_fields = product_os_store::Fields::All;
463        let mut sort_by = vec!((identifier_name.clone(), product_os_store::SortOrder::DESC));
464
465        tracing::info!("Query params: {:?}", query_params);
466
467        let mut params: Vec<(String, String)> = vec!();
468        for (k, val) in query_params.clone() {
469            match val {
470                Value::String(str) => { params.push((k.to_string(), str)); }
471                Value::Array(arr) => {
472                    for v in arr {
473                        match v {
474                            Value::String(str) => { params.push((k.to_string(), str)); }
475                            _ => return ProductOSRouterError::error_response(ProductOSRouterError::Process("Query type error".to_string()), &StatusCode::INTERNAL_SERVER_ERROR)
476                        }
477                    }
478                }
479                _ => return ProductOSRouterError::error_response(ProductOSRouterError::Process("Query type error".to_string()), &StatusCode::INTERNAL_SERVER_ERROR)
480            }
481        }
482
483        let query_object = query_to_object(params);
484        if let Ok(product_os_store::Query::QueryComplete(
485            _, _,
486            fields,
487            _, _, _, _,
488            sort,
489            _, _)) = query_object_to_query_expression(table_name.clone(), query_object, service.get_default_offset(), service.get_default_limit()) {
490            if let Some(f) = fields {
491                select_fields = f;
492            }
493
494            if let Some(s) = sort {
495                sort_by = s;
496            }
497        }
498
499        // Get
500        let result = store.get_one_specific(&product_os_store::Query::QueryComplete(
501            product_os_store::Table::Table(table_name),
502            None,
503            Some(select_fields),
504            None,
505            Some(product_os_store::Expression::EqualTo(identifier_name.clone(), identifier)),
506            None,
507            None,
508            Some(sort_by),
509            None,
510            None)).await;
511
512        match result {
513            Ok(res) => {
514                match res {
515                    None => ProductOSRouterError::error_response(ProductOSRouterError::Process(format!("Not found: {:?}", service.get_identifier_name())), &StatusCode::NOT_FOUND),
516                    Some(row) => {
517                        match row_to_object(row) {
518                            Ok(row_object) => {
519                                let mut object = row_object.clone();
520                                if let serde_json::Value::Object(mut obj) = row_object {
521                                    match obj.get(identifier_name.as_str()) {
522                                        None => {}
523                                        Some(id) => {
524                                            obj.insert("_id".to_string(), id.clone());
525                                            object = serde_json::Value::Object(obj);
526                                        }
527                                    }
528
529                                    Response::builder()
530                                        .status(StatusCode::OK)
531                                        .header("content-type", "application/json")
532                                        .body(Body::from(object.to_string()))
533                                        .unwrap()
534                                }
535                                else {
536                                    ProductOSRouterError::error_response(ProductOSRouterError::Process("Error making request - problem with object".to_string()), &StatusCode::INTERNAL_SERVER_ERROR)
537                                }
538                            },
539                            Err(e) => {
540                                tracing::error!("Error encountered: {:?}", e);
541                                ProductOSRouterError::error_response(ProductOSRouterError::Process(format!("Error making request: {:?}", e)), &StatusCode::INTERNAL_SERVER_ERROR)
542                            }
543                        }
544                    }
545                }
546            }
547            Err(e) => {
548                tracing::error!("Error encountered: {:?}", e);
549                ProductOSRouterError::error_response(ProductOSRouterError::Process(format!("Error making request: {:?}", e)), &StatusCode::INTERNAL_SERVER_ERROR)
550            }
551        }
552    }
553
554    async fn create(State(service): State<Arc<ProductOSServiceHandler>>,
555                    Query(query_params): Query<HashMap<String, Value>>,
556                    Json(payload): Json<serde_json::Value>) -> Response<Body> {
557        tracing::info!("CREATE request received:\n{:?}\n{:?}", payload, query_params);
558
559        let store: Arc<ProductOSRelationalStore> = service.get_store();
560        let table_name: String = service.get_table_name();
561        // let identifier_name: String = service.get_identifier_name();
562
563        let mut params: Vec<(String, String)> = vec!();
564        for (k, val) in query_params.clone() {
565            match val {
566                Value::String(str) => { params.push((k.to_string(), str)); }
567                Value::Array(arr) => {
568                    for v in arr {
569                        match v {
570                            Value::String(str) => { params.push((k.to_string(), str)); }
571                            _ => return ProductOSRouterError::error_response(ProductOSRouterError::Process("Query type error".to_string()), &StatusCode::INTERNAL_SERVER_ERROR)
572                        }
573                    }
574                }
575                _ => return ProductOSRouterError::error_response(ProductOSRouterError::Process("Query type error".to_string()), &StatusCode::INTERNAL_SERVER_ERROR)
576            }
577        }
578
579        let mut fields = vec!();
580        let mut values = vec!();
581        for (name, value) in payload.as_object().unwrap().iter() {
582            fields.push(name.to_string());
583            match value {
584                serde_json::Value::Null => { values.push(product_os_store::Value::Null); }
585                serde_json::Value::Bool(b) => { values.push(product_os_store::Value::Boolean(b.to_owned())) }
586                serde_json::Value::Number(n) => {
587                    values.push(product_os_store::Value::BigNumber(i128::from(n.as_i64().unwrap())));
588                },
589                serde_json::Value::String(s) => { values.push(product_os_store::Value::String(s.to_string())); }
590                serde_json::Value::Array(arr) => {
591                    let mut a = vec!();
592                    for e in arr {
593                        match e {
594                            serde_json::Value::Bool(b) => { a.push(product_os_store::Value::Boolean(b.to_owned())) },
595                            serde_json::Value::Number(n) => {
596                                a.push(product_os_store::Value::BigNumber(i128::from(n.as_i64().unwrap())));
597                            }
598                            serde_json::Value::String(s) => { a.push(product_os_store::Value::String(s.to_string())) }
599                            _ => return ProductOSRouterError::error_response(ProductOSRouterError::Process("Error processing request data".to_string()), &StatusCode::INTERNAL_SERVER_ERROR)
600                        }
601                    };
602                    values.push(product_os_store::Value::Array(a.to_owned()));
603                },
604                serde_json::Value::Object(o) => { values.push(product_os_store::Value::Json(serde_json::Value::Object(o.to_owned()))); }
605            }
606        }
607
608        let insert_instruction = product_os_store::Instruction::InstructionComplete(
609            product_os_store::InstructionType::Insert,
610            table_name,
611            Some(product_os_store::Fields::SpecificString(fields)),
612            Some(vec!(values)),
613            None,
614            None,
615            None,
616            None,
617            None,
618            None,
619            None
620        );
621
622        match store.execute(&insert_instruction).await {
623            Ok(_) => {
624                Response::builder()
625                    .status(StatusCode::OK)
626                    .header("content-type", "application/json")
627                    .body(Body::from(payload.to_string()))
628                    .unwrap()
629            }
630            Err(e) => ProductOSRouterError::error_response(ProductOSRouterError::Process(format!("Error making request: {:?}", e)), &StatusCode::INTERNAL_SERVER_ERROR)
631        }
632    }
633
634    async fn update(State(_service): State<Arc<ProductOSServiceHandler>>,
635                    Path(identifier): Path<String>,
636                    Query(query_params): Query<HashMap<String, Value>>,
637                    Json(payload): Json<serde_json::Value>) -> Response<Body> {
638        tracing::info!("UPDATE request received:\n{:?}\n{:?}\n{:?}", identifier, payload, query_params);
639
640        Response::builder()
641            .status(StatusCode::NOT_IMPLEMENTED)
642            .header("content-type", "application/json")
643            .body(Body::from("{}"))
644            .unwrap()
645    }
646
647    async fn patch(State(service): State<Arc<ProductOSServiceHandler>>,
648                   Path(identifier): Path<String>,
649                   Query(query_params): Query<HashMap<String, Value>>,
650                   Json(payload): Json<serde_json::Value>) -> Response<Body> {
651        tracing::info!("PATCH request received:\n{:?}\n{:?}\n{:?}", identifier, payload, query_params);
652
653        let store: Arc<ProductOSRelationalStore> = service.get_store();
654        let table_name: String = service.get_table_name();
655        let identifier_name: String = service.get_identifier_name();
656
657        let mut params: Vec<(String, String)> = vec!();
658        for (k, val) in query_params.clone() {
659            match val {
660                Value::String(str) => { params.push((k.to_string(), str)); }
661                Value::Array(arr) => {
662                    for v in arr {
663                        match v {
664                            Value::String(str) => { params.push((k.to_string(), str)); }
665                            _ => return ProductOSRouterError::error_response(ProductOSRouterError::Process("Query type error".to_string()), &StatusCode::INTERNAL_SERVER_ERROR)
666                        }
667                    }
668                }
669                _ => return ProductOSRouterError::error_response(ProductOSRouterError::Process("Query type error".to_string()), &StatusCode::INTERNAL_SERVER_ERROR)
670            }
671        }
672
673        match update_object_to_fields_values(payload.clone()) {
674            Ok((fields, values)) => {
675                let update_instruction = product_os_store::Instruction::InstructionComplete(
676                    product_os_store::InstructionType::Update,
677                    table_name,
678                    Some(product_os_store::Fields::SpecificString(fields)),
679                    Some(vec!(values)),
680                    None,
681                    Some(product_os_store::Expression::EqualTo(identifier_name, identifier)),
682                    None,
683                    None,
684                    None,
685                    None,
686                    None
687                );
688
689                match store.execute(&update_instruction).await {
690                    Ok(_) => {
691                        Response::builder()
692                            .status(StatusCode::OK)
693                            .header("content-type", "application/json")
694                            .body(Body::from(payload.to_string()))
695                            .unwrap()
696                    }
697                    Err(e) => ProductOSRouterError::error_response(ProductOSRouterError::Process(format!("Error making request: {:?}", e)), &StatusCode::INTERNAL_SERVER_ERROR)
698                }
699            }
700            Err(e) => ProductOSRouterError::error_response(e, &StatusCode::BAD_REQUEST)
701        }
702    }
703
704    async fn remove(State(service): State<Arc<ProductOSServiceHandler>>,
705                    Path(identifier): Path<String>,
706                    Query(query_params): Query<HashMap<String, Value>>) -> Response<Body> {
707        tracing::info!("REMOVE request received:\n{:?}\n{:?}", identifier, query_params);
708
709        let store: Arc<ProductOSRelationalStore> = service.get_store();
710        let table_name: String = service.get_table_name();
711        let identifier_name: String = service.get_identifier_name();
712
713        let mut params: Vec<(String, String)> = vec!();
714        for (k, val) in query_params.clone() {
715            match val {
716                Value::String(str) => { params.push((k.to_string(), str)); }
717                Value::Array(arr) => {
718                    for v in arr {
719                        match v {
720                            Value::String(str) => { params.push((k.to_string(), str)); }
721                            _ => return ProductOSRouterError::error_response(ProductOSRouterError::Process("Query type error".to_string()), &StatusCode::INTERNAL_SERVER_ERROR)
722                        }
723                    }
724                }
725                _ => return ProductOSRouterError::error_response(ProductOSRouterError::Process("Query type error".to_string()), &StatusCode::INTERNAL_SERVER_ERROR)
726            }
727        }
728
729        let delete_instruction = product_os_store::Instruction::InstructionComplete(
730            product_os_store::InstructionType::Delete,
731            table_name,
732            None,
733            None,
734            None,
735            Some(product_os_store::Expression::EqualTo(identifier_name, identifier)),
736            None,
737            None,
738            None,
739            None,
740            None
741        );
742
743        match store.execute(&delete_instruction).await {
744            Ok(_) => {
745                Response::builder()
746                    .status(StatusCode::OK)
747                    .header("content-type", "application/json")
748                    .body(Body::from("{}"))
749                    .unwrap()
750            }
751            Err(e) => ProductOSRouterError::error_response(ProductOSRouterError::Process(format!("Error making request: {:?}", e)), &StatusCode::INTERNAL_SERVER_ERROR)
752        }
753    }
754}
755
756
757#[async_trait]
758impl Feature for ProductOSServiceHandler {
759    async fn register(&self, feature: Arc<dyn Feature>, base_path: String, router: &mut product_os_router::ProductOSRouter) -> RegistryFeature {
760        // Downcast the feature to ProductOSServiceHandler
761        // This is safe because we know the feature is a ProductOSServiceHandler when registering
762        let service_handler = Arc::new(ProductOSServiceHandler {
763            name: self.name.clone(),
764            path: self.path.clone(),
765            table_name: self.table_name.clone(),
766            identifier_name: self.identifier_name.clone(),
767            controller: self.controller.clone(),
768            store: self.store.clone(),
769            default_limit: self.default_limit,
770            default_offset: self.default_offset,
771        });
772        
773        ProductOSServiceHandler::service_handler(base_path.clone(), router, service_handler);
774
775        let mut identifier= self.name.to_owned();
776        identifier.push_str("Handler");
777
778        RegistryFeature {
779            identifier,
780            paths: vec!(base_path),
781            feature: Some(feature),
782            feature_mut: None
783        }
784    }
785
786    async fn register_mut(&self, _feature: Arc<Mutex<dyn Feature>>, _base_path: String, _router: &mut product_os_router::ProductOSRouter) -> RegistryFeature {
787        panic!("Mutable service handler not allowed to be registered")
788    }
789
790    fn identifier(&self) -> String {
791        "Content".to_string()
792    }
793
794    async fn request(&self, _action: &What, _input: &Option<serde_json::Value>, _semver: &str) -> Response<Body> {
795        Response::builder()
796            .status(StatusCode::NOT_IMPLEMENTED)
797            .header("content-type", "application/json")
798            .body(Body::from("{}"))
799            .unwrap()
800    }
801
802    async fn request_mut(&mut self, action: &What, input: &Option<serde_json::Value>, semver: &str) -> Response<Body> {
803        self.request(action, input, semver).await
804    }
805}
806
807
808
809
810fn row_to_object(row: RelationalRow) -> Result<serde_json::Value, ProductOSRouterError> {
811    let mut values = serde_json::Map::new();
812
813    let columns = row.columns();
814
815    for column in columns {
816        let name = column.name().to_string();
817        let position = column.ordinal();
818
819        let column_type = column.type_str();
820
821        // https://docs.rs/sqlx/latest/sqlx/postgres/types/index.html
822        match column_type.as_str() {
823            "BOOL" | "BOOL[]" => {
824                match row.try_get::<bool>(position) {
825                    Ok(value) => { values.insert(name, serde_json::Value::Bool(value)) }
826                    Err(e) => {
827                        match e {
828                            RelationalError::DecodeError => { values.insert(name, serde_json::Value::Null) }
829                            _ => return Err(ProductOSRouterError::Process(format!("Error translating value: {:?}", e)))
830                        }
831                    }
832                };
833            }
834            "\"CHAR\"" | "\"CHAR\"[]" => {
835                match row.try_get::<i8>(position) {
836                    Ok(value) => { values.insert(name, serde_json::Value::Number(serde_json::Number::from(value))) }
837                    Err(e) => {
838                        match e {
839                            RelationalError::DecodeError => { values.insert(name, serde_json::Value::Null) }
840                            _ => return Err(ProductOSRouterError::Process(format!("Error translating value: {:?}", e)))
841                        }
842                    }
843                };
844            }
845            "INT2" | "SMALLINT" | "SMALLSERIAL" => {
846                match row.try_get::<i16>(position) {
847                    Ok(value) => { values.insert(name, serde_json::Value::Number(serde_json::Number::from(value))) }
848                    Err(e) => {
849                        match e {
850                            RelationalError::DecodeError => { values.insert(name, serde_json::Value::Null) }
851                            _ => return Err(ProductOSRouterError::Process(format!("Error translating value: {:?}", e)))
852                        }
853                    }
854                };
855            }
856            "INT4" | "INT" | "SERIAL" => {
857                match row.try_get::<i32>(position) {
858                    Ok(value) => { values.insert(name, serde_json::Value::Number(serde_json::Number::from(value))) }
859                    Err(e) => {
860                        match e {
861                            RelationalError::DecodeError => { values.insert(name, serde_json::Value::Null) }
862                            _ => return Err(ProductOSRouterError::Process(format!("Error translating value: {:?}", e)))
863                        }
864                    }
865                };
866            }
867            "INT8" | "BIGINT" | "BIGSERIAL" => {
868                match row.try_get::<i64>(position) {
869                    Ok(value) => { values.insert(name, serde_json::Value::Number(serde_json::Number::from(value))) }
870                    Err(e) => {
871                        match e {
872                            RelationalError::DecodeError => { values.insert(name, serde_json::Value::Null) }
873                            _ => return Err(ProductOSRouterError::Process(format!("Error translating value: {:?}", e)))
874                        }
875                    }
876                };
877            }
878            "FLOAT4" | "REAL" => {
879                match row.try_get::<f32>(position) {
880                    Ok(value) => { values.insert(name, serde_json::Value::Number(serde_json::Number::from_f64(f64::from(value)).unwrap())) }
881                    Err(e) => {
882                        match e {
883                            RelationalError::DecodeError => { values.insert(name, serde_json::Value::Null) }
884                            _ => return Err(ProductOSRouterError::Process(format!("Error translating value: {:?}", e)))
885                        }
886                    }
887                };
888            }
889            "FLOAT8" | "DOUBLE PRECISION" => {
890                match row.try_get::<f64>(position) {
891                    Ok(value) => { values.insert(name, serde_json::Value::Number(serde_json::Number::from_f64(value).unwrap())) }
892                    Err(e) => {
893                        match e {
894                            RelationalError::DecodeError => { values.insert(name, serde_json::Value::Null) }
895                            _ => return Err(ProductOSRouterError::Process(format!("Error translating value: {:?}", e)))
896                        }
897                    }
898                };
899            }
900            "VARCHAR" | "CHAR" | "VARCHAR[]" | "CHAR[]" | "NAME" | "TEXT" => {
901                match row.try_get::<String>(position) {
902                    Ok(value) => { values.insert(name, serde_json::Value::String(value)) }
903                    Err(e) => {
904                        match e {
905                            RelationalError::DecodeError => { values.insert(name, serde_json::Value::Null) }
906                            _ => return Err(ProductOSRouterError::Process(format!("Error translating value: {:?}", e)))
907                        }
908                    }
909                };
910            }
911            "BYTEA" | "BYTEA[]" => {
912                match row.try_get::<Vec<u8>>(position) {
913                    Ok(value) => {
914                        let mut arr = vec!();
915                        for v in value {
916                            arr.push(serde_json::Value::Number(serde_json::Number::from(v)))
917                        }
918                        values.insert(name, serde_json::Value::Array(arr))
919                    }
920                    Err(e) => {
921                        match e {
922                            RelationalError::DecodeError => { values.insert(name, serde_json::Value::Null) }
923                            _ => return Err(ProductOSRouterError::Process(format!("Error translating value: {:?}", e)))
924                        }
925                    }
926                };
927            }
928            #[cfg(any(feature = "postgres_store", feature = "sqlite_store"))]
929            "TIMESTAMPTZ" | "TIMESTAMPTZ[]" => {
930                match row.try_get::<product_os_store::types::chrono::DateTime<product_os_store::types::chrono::Utc>>(position) {
931                    Ok(value) => { values.insert(name, serde_json::Value::String(value.to_rfc3339())) }
932                    Err(e) => {
933                        match e {
934                            RelationalError::DecodeError => { values.insert(name, serde_json::Value::Null) }
935                            _ => return Err(ProductOSRouterError::Process(format!("Error translating value: {:?}", e)))
936                        }
937                    }
938                };
939            }
940            #[cfg(any(feature = "postgres_store", feature = "sqlite_store"))]
941            "TIMESTAMP" | "TIMESTAMP[]" => {
942                match row.try_get::<product_os_store::types::chrono::NaiveDateTime>(position) {
943                    Ok(value) => { values.insert(name, serde_json::Value::String(value.to_string())) }
944                    Err(e) => {
945                        match e {
946                            RelationalError::DecodeError => { values.insert(name, serde_json::Value::Null) }
947                            _ => return Err(ProductOSRouterError::Process(format!("Error translating value: {:?}", e)))
948                        }
949                    }
950                };
951            }
952            #[cfg(any(feature = "postgres_store", feature = "sqlite_store"))]
953            "DATE" | "DATE[]" => {
954                match row.try_get::<product_os_store::types::chrono::NaiveDate>(position) {
955                    Ok(value) => { values.insert(name, serde_json::Value::String(value.to_string())) }
956                    Err(e) => {
957                        match e {
958                            RelationalError::DecodeError => { values.insert(name, serde_json::Value::Null) }
959                            _ => return Err(ProductOSRouterError::Process(format!("Error translating value: {:?}", e)))
960                        }
961                    }
962                };
963            }
964            #[cfg(any(feature = "postgres_store", feature = "sqlite_store"))]
965            "TIME" | "TIME[]" => {
966                match row.try_get::<product_os_store::types::chrono::NaiveTime>(position) {
967                    Ok(value) => { values.insert(name, serde_json::Value::String(value.to_string())) }
968                    Err(e) => {
969                        match e {
970                            RelationalError::DecodeError => { values.insert(name, serde_json::Value::Null) }
971                            _ => return Err(ProductOSRouterError::Process(format!("Error translating value: {:?}", e)))
972                        }
973                    }
974                };
975            }
976            #[cfg(any(feature = "postgres_store", feature = "sqlite_store"))]
977            "UUID" | "UUID[]" => {
978                match row.try_get::<product_os_store::types::uuid::Uuid>(position) {
979                    Ok(value) => { values.insert(name, serde_json::Value::String(value.to_string())) }
980                    Err(e) => {
981                        match e {
982                            RelationalError::DecodeError => { values.insert(name, serde_json::Value::Null) }
983                            _ => return Err(ProductOSRouterError::Process(format!("Error translating value: {:?}", e)))
984                        }
985                    }
986                };
987            }
988            #[cfg(any(feature = "postgres_store", feature = "sqlite_store"))]
989            "JSON" | "JSON[]" | "JSONB" | "JSONB[]" => {
990                match row.try_get::<product_os_store::types::Json<serde_json::value::Value>>(position) {
991                    Ok(value) => { values.insert(name, value.0) }
992                    Err(e) => {
993                        match e {
994                            RelationalError::DecodeError => { values.insert(name, serde_json::Value::Null) }
995                            _ => return Err(ProductOSRouterError::Process(format!("Error translating value: {:?}", e)))
996                        }
997                    }
998                };
999            }
1000            _ => {}
1001        };
1002    }
1003
1004    let response = serde_json::Value::Object(values);
1005    Ok(response)
1006}
1007
1008
1009
1010/// Converts a vector of query parameters to a JSON object
1011///
1012/// This function transforms URL query parameters into a nested JSON structure,
1013/// supporting FeathersJS query syntax including array and object notation.
1014///
1015/// # Arguments
1016///
1017/// * `query` - Vector of (key, value) tuples representing query parameters
1018///
1019/// # Query Syntax
1020///
1021/// The function supports FeathersJS query syntax:
1022/// - Simple keys: `name=value` becomes `{"name": "value"}`
1023/// - Array notation: `tags[]=a&tags[]=b` becomes `{"tags": ["a", "b"]}`
1024/// - Object notation: `user[name]=John` becomes `{"user": {"name": "John"}}`
1025/// - Nested objects: `filter[age][$gt]=21` becomes `{"filter": {"age": {"$gt": "21"}}}`
1026///
1027/// # Returns
1028///
1029/// A `serde_json::Value` representing the query as a JSON object.
1030///
1031/// # Example
1032///
1033/// ```rust
1034/// # use product_os_service_handler::query_to_object;
1035/// let query = vec![
1036///     ("name".to_string(), "John".to_string()),
1037///     ("age[$gt]".to_string(), "21".to_string()),
1038/// ];
1039/// let result = query_to_object(query);
1040/// // result: {"name": "John", "age": {"$gt": "21"}}
1041/// ```
1042pub fn query_to_object(query: Vec<(String, String)>) -> serde_json::Value {
1043    let mut object = serde_json::Value::Object(serde_json::Map::new());
1044
1045    for (full_key, value) in query {
1046        let key = full_key.split("[").collect::<Vec<&str>>().first().unwrap().to_owned();
1047
1048        let mut object_ref = &mut object;
1049        let mut object_key_name = None;
1050
1051        let mut is_object = false;
1052        let mut is_array = false;
1053
1054        for capture in OBJECT_ARRAY_ELEMENT_REGEX.captures_iter(full_key.as_str()) {
1055            tracing::info!("Capture {:?}", capture);
1056            if capture[1].is_empty() {
1057                if object_ref.as_object().unwrap().get(key).is_none() {
1058                    object_ref.as_object_mut().unwrap().insert(key.to_string(), serde_json::Value::Array(vec!()));
1059                }
1060
1061                object_ref = object_ref.as_object_mut().unwrap().get_mut(key).unwrap();
1062                object_key_name = None;
1063
1064                is_object = false;
1065                is_array = true;
1066            }
1067            else {
1068                if object_ref.as_object().unwrap().get(key).is_none() {
1069                    object_ref.as_object_mut().unwrap().insert(key.to_string(), serde_json::Value::Object(serde_json::Map::new()));
1070                }
1071
1072                object_ref = object_ref.as_object_mut().unwrap().get_mut(key).unwrap();
1073                object_key_name = Some(capture[1].to_string());
1074
1075                is_object = true;
1076                is_array = false;
1077            }
1078        }
1079
1080        if is_object {
1081            object_ref.as_object_mut().unwrap().insert(object_key_name.unwrap(), serde_json::Value::String(value.to_string()));
1082        }
1083        else if is_array {
1084            tracing::info!("Array: {:?}", object_ref);
1085            object_ref.as_array_mut().unwrap().push(serde_json::Value::String(value.to_string()));
1086        }
1087        else {
1088            object_ref.as_object_mut().unwrap().insert(key.to_string(), serde_json::Value::String(value.to_string()));
1089        }
1090    }
1091
1092    object
1093}
1094
1095
1096
1097/// Converts a query string to a JSON object
1098///
1099/// Parses a URL query string in the format `key1=value1&key2=value2` and converts
1100/// it to a nested JSON structure using the same logic as [`query_to_object`].
1101///
1102/// # Arguments
1103///
1104/// * `query_string` - A URL-encoded query string (e.g., "name=John&age[$gt]=21")
1105///
1106/// # Returns
1107///
1108/// A `serde_json::Value` representing the query as a JSON object.
1109///
1110/// # Example
1111///
1112/// ```rust
1113/// # use product_os_service_handler::query_string_to_object;
1114/// let query_str = "name=John&age[$gt]=21".to_string();
1115/// let result = query_string_to_object(query_str);
1116/// // result: {"name": "John", "age": {"$gt": "21"}}
1117/// ```
1118pub fn query_string_to_object(query_string: String) -> serde_json::Value {
1119    let query_string_elements = query_string.split("&").collect::<Vec<&str>>();
1120
1121    let mut query_array = Vec::new();
1122    for element in query_string_elements {
1123        let key_value = element.split("=").collect::<Vec<&str>>();
1124        if key_value.len() == 2 {
1125            let full_key = key_value.first().unwrap().to_string();
1126            let value = key_value.get(1).unwrap().to_string();
1127
1128            query_array.push((full_key, value));
1129        }
1130    }
1131
1132    query_to_object(query_array)
1133}
1134
1135
1136
1137/// Converts a JSON object back to a query string
1138///
1139/// This is the inverse operation of [`query_to_object`], converting a nested JSON
1140/// structure back into a URL query string format compatible with FeathersJS.
1141///
1142/// # Arguments
1143///
1144/// * `query_object` - A JSON value to convert to query string format
1145/// * `prefix` - A prefix for nested keys (use empty string for top-level)
1146///
1147/// # Returns
1148///
1149/// A URL query string representation of the JSON object.
1150///
1151/// # Example
1152///
1153/// ```rust
1154/// # use product_os_service_handler::object_to_query_string;
1155/// # use serde_json::json;
1156/// let obj = json!({"name": "John", "age": {"$gt": 21}});
1157/// let query_str = object_to_query_string(obj, String::new());
1158/// // result: "name=John&age[$gt]=21"
1159/// ```
1160pub fn object_to_query_string(query_object: serde_json::Value, prefix: String) -> String {
1161    let mut query_string = String::new();
1162
1163    match query_object {
1164        serde_json::Value::Object(object) => {
1165            for (mut key, value) in object {
1166                match value.clone() {
1167                    serde_json::Value::Array(array) => {
1168                        if !prefix.is_empty() {
1169                            key = format!("{prefix}[{key}]");
1170                        }
1171
1172                        for (counter, val) in array.iter().enumerate() {
1173                            match val {
1174                                serde_json::Value::Object(_) | serde_json::Value::Array(_) => {
1175                                    let array_prefix = if !prefix.is_empty() {
1176                                        format!("{prefix}[{counter}]")
1177                                    }
1178                                    else {
1179                                        format!("{key}[{counter}]")
1180                                    };
1181
1182                                    query_string.push_str(object_to_query_string(val.clone(), array_prefix).as_str());
1183                                    query_string.push('&');
1184                                }
1185                                serde_json::Value::Bool(boolean) => {
1186                                    let b = boolean.to_string();
1187                                    query_string.push_str(format!("{key}[]={b}&").as_str())
1188                                },
1189                                serde_json::Value::Number(number) => {
1190                                    let n = number.to_string();
1191                                    query_string.push_str(format!("{key}[]={n}&").as_str())
1192                                },
1193                                serde_json::Value::String(string) => {
1194                                    let s = string;
1195                                    query_string.push_str(format!("{key}[]={s}&").as_str())
1196                                }
1197                                serde_json::Value::Null => {}
1198                            }
1199                        }
1200                    }
1201                    serde_json::Value::Object(object) => {
1202                        if object.contains_key("_bsontype") {
1203                            #[allow(clippy::collapsible_match)] // Clearer as separate steps
1204                            match object.get("_bsontype") {
1205                                None => {}
1206                                Some(value) => {
1207                                    if let serde_json::Value::String(val) = value {
1208                                        if val.as_str() == "ObjectID" {
1209                                            match object.get("id") {
1210                                                None => {}
1211                                                Some(identifier) => {
1212                                                    if let serde_json::Value::Array(array) = identifier {
1213                                                        let mut hex_value = String::new();
1214                                                        for hex in array {
1215                                                            if let serde_json::Value::Number(number) = hex {
1216                                                                hex_value.push_str(format!("{:x}", number.as_i64().unwrap()).as_str());
1217                                                            }
1218                                                        }
1219
1220                                                        if !prefix.is_empty() {
1221                                                            key = format!("{prefix}[{key}]");
1222                                                        }
1223
1224                                                        query_string.push_str(format!("{key}={hex_value}&").as_str());
1225                                                    }
1226                                                }
1227                                            }
1228                                        }
1229                                    }
1230                                }
1231                            }
1232                        }
1233                        else {
1234                            let object_prefix = if !prefix.is_empty() {
1235                                format!("{prefix}[{key}]")
1236                            }
1237                            else {
1238                                key
1239                            };
1240
1241                            query_string.push_str(object_to_query_string(value.clone(), object_prefix).as_str());
1242                            query_string.push('&');
1243                        }
1244                    }
1245                    serde_json::Value::Bool(boolean) => {
1246                        if !prefix.is_empty() {
1247                            key = format!("{prefix}[{key}]");
1248                        }
1249
1250                        let b = boolean.to_string();
1251                        query_string.push_str(format!("{key}={b}&").as_str())
1252                    }
1253                    serde_json::Value::Number(number) => {
1254                        if !prefix.is_empty() {
1255                            key = format!("{prefix}[{key}]");
1256                        }
1257
1258                        let n = number.to_string();
1259                        query_string.push_str(format!("{key}={n}&").as_str())
1260                    }
1261                    serde_json::Value::String(string) => {
1262                        if !prefix.is_empty() {
1263                            key = format!("{prefix}[{key}]");
1264                        }
1265
1266                        let s = string;
1267                        query_string.push_str(format!("{key}={s}&").as_str())
1268                    }
1269                    serde_json::Value::Null => {
1270                        if !prefix.is_empty() {
1271                            key = format!("{prefix}[{key}]");
1272                        }
1273
1274                        query_string.push_str(format!("{key}=&").as_str())
1275                    }
1276                }
1277            }
1278
1279            query_string.trim_matches(&['&'] as &[_]).to_string()
1280        }
1281        _ => query_string
1282    }
1283}
1284
1285
1286fn query_object_to_query_expression(table_name: String, object: serde_json::Value, default_offset: Option<u32>, default_limit: Option<u32>) -> Result<product_os_store::Query, ProductOSRouterError> {
1287    let table = product_os_store::Table::Table(table_name);
1288    let join = None;
1289    let mut fields = Some(product_os_store::Fields::All);
1290    let distinct = None;
1291    // let mut expression = Some(product_os_store::Expression::Empty);
1292    let group_by = None;
1293    let having = None;
1294    let mut sort_by = None;
1295    let offset = default_offset.unwrap_or_default();
1296    let limit = default_limit.unwrap_or(100);
1297    let mut fetch = Some(product_os_store::Fetch::CountWithOffset(offset, limit));
1298    let table_creation = None;
1299
1300
1301    let mut filter_expression = vec!();
1302
1303    tracing::info!("Expression object {:?}", object);
1304    match object.as_object() {
1305        None => (),
1306        Some(query_object) => {
1307            for (key, value) in query_object {
1308                tracing::info!("Working through expression: {:?} {:?}", key, value);
1309                match key.as_str() {
1310                    "$limit" => {
1311                        if let Some(product_os_store::Fetch::CountWithOffset(offset, _)) = fetch {
1312                            fetch = Some(product_os_store::Fetch::CountWithOffset(offset, u32::from_str(value.as_str().unwrap()).unwrap()));
1313                        }
1314                    },
1315                    "$skip" => {
1316                        if let Some(product_os_store::Fetch::CountWithOffset(_, count)) = fetch {
1317                            fetch = Some(product_os_store::Fetch::CountWithOffset(u32::from_str(value.as_str().unwrap()).unwrap(), count));
1318                        }
1319                    },
1320                    "$sort" => {
1321                        let mut sort_vec = vec!();
1322                        for (key, value) in value.as_object().unwrap() {
1323                            match i32::from_str(value.as_str().unwrap()).unwrap() {
1324                                -1 => sort_vec.push((key.to_string(), product_os_store::SortOrder::DESC)),
1325                                _ => sort_vec.push((key.to_string(), product_os_store::SortOrder::ASC))
1326                            }
1327                        }
1328                        sort_by = Some(sort_vec);
1329                    }
1330                    "$select" => {
1331                        let mut array = vec!();
1332                        let value_array = value.as_array().unwrap();
1333
1334                        for value in value_array {
1335                            array.push(value.as_str().unwrap().to_string());
1336                        }
1337
1338                        fields = Some(product_os_store::Fields::SpecificString(array));
1339                    }
1340                    "$or" => {
1341                        match query_object_to_expression(value.to_owned()) {
1342                            Ok(expression) => filter_expression.push(expression),
1343                            Err(e) => return Err(e)
1344                        };
1345                    },
1346                    key /* $eq */ => {
1347                        build_query(&mut filter_expression, key, value);
1348                    }
1349                }
1350            }
1351        }
1352    }
1353
1354    tracing::info!("Expression query: {:?}", filter_expression);
1355    let and_expression_count = filter_expression.len();
1356
1357    let expression = match and_expression_count {
1358        0 => None,
1359        1 => Some(filter_expression.remove(0)),
1360        2 => Some(product_os_store::Expression::And(Box::new(filter_expression.remove(0)), Box::new(filter_expression.remove(0)))),
1361        3 => Some(product_os_store::Expression::And3(Box::new(filter_expression.remove(0)), Box::new(filter_expression.remove(0)), Box::new(filter_expression.remove(0)))),
1362        4 => Some(product_os_store::Expression::And4(Box::new(filter_expression.remove(0)), Box::new(filter_expression.remove(0)), Box::new(filter_expression.remove(0)), Box::new(filter_expression.remove(0)))),
1363        5 => Some(product_os_store::Expression::And5(Box::new(filter_expression.remove(0)), Box::new(filter_expression.remove(0)), Box::new(filter_expression.remove(0)), Box::new(filter_expression.remove(0)), Box::new(filter_expression.remove(0)))),
1364        _ => return Err(ProductOSRouterError::Process(String::from("Unable to handle more than 5 expressions joined")))
1365    };
1366
1367    Ok(product_os_store::Query::QueryComplete(
1368        table,
1369        join,
1370        fields,
1371        distinct,
1372        expression,
1373        group_by,
1374        having,
1375        sort_by,
1376        fetch,
1377        table_creation))
1378
1379    /*
1380        Table, // table, Option is for providing an alias
1381        Option<Join>, // join
1382        Option<Fields>, // fields
1383        Option<(DistinctType, Vec<String>)>, // distinct
1384        Option<Expression>, // where conditions
1385        Option<Vec<String>>, // group_by, PostgreSQL evaluates the GROUP BY clause after the FROM and WHERE clauses and before the HAVING SELECT, DISTINCT, ORDER BY and LIMIT/FETCH clauses
1386        Option<Expression>, // having, PostgreSQL evaluates the HAVING clause after the FROM, WHERE, GROUP BY, and before the SELECT, DISTINCT, ORDER BY and LIMIT/FETCH clauses
1387        Option<Vec<(String, SortOrder)>>, // sort_by
1388        Option<Fetch>, // fetch
1389        Option<(bool, String)> // Into -> temporary/permanent table name creation
1390    */
1391}
1392
1393
1394
1395fn build_query(filter_expression: &mut Vec<Expression>, key: &str, value: &serde_json::Value) {
1396    match value {
1397        serde_json::Value::Object(obj) => {
1398            if obj.contains_key("$in") {
1399                let mut array = vec!();
1400                let value_array = obj.get("$in").unwrap().as_array().unwrap();
1401
1402                for value in value_array {
1403                    array.push(product_os_store::Value::String(value.as_str().unwrap().to_string()));
1404                }
1405
1406                filter_expression.push(product_os_store::Expression::In(key.to_string(), array));
1407            }
1408            if obj.contains_key("$nin") {
1409                let mut array = vec!();
1410                let value_array = obj.get("$nin").unwrap().as_array().unwrap();
1411
1412                for value in value_array {
1413                    array.push(product_os_store::Value::String(value.as_str().unwrap().to_string()));
1414                }
1415
1416                filter_expression.push(product_os_store::Expression::Not(Box::new(product_os_store::Expression::In(key.to_string(), array))));
1417            }
1418            if obj.contains_key("$lt") { filter_expression.push(product_os_store::Expression::LessThan(key.to_string(), obj.get("$lt").unwrap().as_str().unwrap().to_string())); }
1419            if obj.contains_key("$lte") { filter_expression.push(product_os_store::Expression::LessThanEqualTo(key.to_string(), obj.get("$lte").unwrap().as_str().unwrap().to_string())); }
1420            if obj.contains_key("$gt") { filter_expression.push(product_os_store::Expression::GreaterThan(key.to_string(), obj.get("$gt").unwrap().as_str().unwrap().to_string())); }
1421            if obj.contains_key("$gte") { filter_expression.push(product_os_store::Expression::GreaterThanEqualTo(key.to_string(), obj.get("$gte").unwrap().as_str().unwrap().to_string())); }
1422            if obj.contains_key("$ne") { filter_expression.push(product_os_store::Expression::NotEqualTo(key.to_string(), obj.get("$ne").unwrap().as_str().unwrap().to_string())); }
1423
1424            tracing::info!("Looping through object value: {:?}", obj);
1425            for (sub_key, sub_value) in obj {
1426                if !sub_key.starts_with("$") {
1427                    let mut extended_key = key.to_string();
1428
1429                    if extended_key.contains(">>") {
1430                        extended_key = extended_key.replace(">>", ">");
1431                    }
1432
1433                    extended_key.push_str("->>'");
1434                    extended_key.push_str(sub_key.as_str());
1435                    extended_key.push('\'');
1436
1437                    tracing::info!("Looping through subs {:?} {:?}", extended_key, sub_value);
1438
1439                    match sub_value {
1440                        serde_json::Value::Object(_) => {
1441                            build_query(filter_expression, extended_key.as_str(), sub_value);
1442                        },
1443                        serde_json::Value::Array(_) => {
1444                            build_query(filter_expression, extended_key.as_str(), sub_value);
1445                        }
1446                        _ => {
1447                            if query_key_value_to_expression(filter_expression, extended_key.as_str(), sub_value).is_ok() {};
1448                        }
1449                    }
1450                }
1451            }
1452        }
1453        serde_json::Value::Array(value_array) => {
1454            let mut array = vec!();
1455
1456            for value in value_array {
1457                array.push(product_os_store::Value::String(value.as_str().unwrap().to_string()));
1458            }
1459
1460            filter_expression.push(product_os_store::Expression::In(key.to_string(), array));
1461        }
1462        /*
1463        serde_json::Value::Null => {}
1464        serde_json::Value::Bool(_) => {}
1465        serde_json::Value::Number(_) => {}
1466        serde_json::Value::String(_) => {}
1467        */
1468        _ => {
1469            tracing::info!("Expression evaluating: {:?} {:?}", key, value);
1470            if query_key_value_to_expression(filter_expression, key, value).is_ok() {};
1471        }
1472    }
1473}
1474
1475
1476
1477
1478fn query_object_to_expression(object: serde_json::Value) -> Result<product_os_store::Expression, ProductOSRouterError> {
1479    let mut filter_expression = vec!();
1480
1481    match object.as_object() {
1482        None => (),
1483        Some(query_object) => {
1484            for (key, value) in query_object {
1485                if query_key_value_to_expression(&mut filter_expression, key.as_str(), value).is_ok() {};
1486            }
1487        }
1488    }
1489
1490    let and_expression_count = filter_expression.len();
1491
1492    match and_expression_count {
1493        0 => Ok(product_os_store::Expression::Empty),
1494        1 => Ok(filter_expression.remove(0)),
1495        2 => Ok(product_os_store::Expression::And(Box::new(filter_expression.remove(0)), Box::new(filter_expression.remove(0)))),
1496        3 => Ok(product_os_store::Expression::And3(Box::new(filter_expression.remove(0)), Box::new(filter_expression.remove(0)), Box::new(filter_expression.remove(0)))),
1497        4 => Ok(product_os_store::Expression::And4(Box::new(filter_expression.remove(0)), Box::new(filter_expression.remove(0)), Box::new(filter_expression.remove(0)), Box::new(filter_expression.remove(0)))),
1498        5 => Ok(product_os_store::Expression::And5(Box::new(filter_expression.remove(0)), Box::new(filter_expression.remove(0)), Box::new(filter_expression.remove(0)), Box::new(filter_expression.remove(0)), Box::new(filter_expression.remove(0)))),
1499        _ => Err(ProductOSRouterError::Process(String::from("Unable to handle more than 5 expressions joined")))
1500    }
1501}
1502
1503fn query_key_value_to_expression(filter_expression: &mut Vec<Expression>, key: &str, value: &serde_json::Value) -> Result<(), ProductOSRouterError> {
1504    match key {
1505        "$in" => {
1506            let mut array = vec!();
1507            let value_array = value.as_array().unwrap();
1508
1509            for value in value_array {
1510                array.push(product_os_store::Value::String(value.as_str().unwrap().to_string()));
1511            }
1512
1513            key.to_string(); drop(array);
1514        }
1515        "$nin" => {
1516            let mut array = vec!();
1517            let value_array = value.as_array().unwrap();
1518
1519            for value in value_array {
1520                array.push(product_os_store::Value::String(value.as_str().unwrap().to_string()));
1521            }
1522
1523            filter_expression.push(product_os_store::Expression::Not(Box::new(product_os_store::Expression::In(key.to_string(), array))));
1524        }
1525        "$lt" => { filter_expression.push(product_os_store::Expression::LessThan(key.to_string(), value.as_str().unwrap().to_string())) },
1526        "$lte" => { filter_expression.push(product_os_store::Expression::LessThanEqualTo(key.to_string(), value.as_str().unwrap().to_string())) },
1527        "$gt" => { filter_expression.push(product_os_store::Expression::GreaterThan(key.to_string(), value.as_str().unwrap().to_string())) },
1528        "$gte" => { filter_expression.push(product_os_store::Expression::GreaterThanEqualTo(key.to_string(), value.as_str().unwrap().to_string())) },
1529        "$or" => {
1530            match query_object_to_expression(value.to_owned()) {
1531                Ok(expression) => filter_expression.push(expression),
1532                Err(e) => return Err(e)
1533            }
1534        },
1535        "$ne" => { filter_expression.push(product_os_store::Expression::NotEqualTo(key.to_string(), value.as_str().unwrap().to_string())) },
1536        "$eq" => { filter_expression.push(product_os_store::Expression::EqualTo(key.to_string(), value.as_str().unwrap().to_string())) },
1537        _ => {
1538            let search_value = value.as_str().unwrap().to_string().replace("*", "%");
1539            filter_expression.push(product_os_store::Expression::Like(key.to_string(), search_value))
1540        }
1541    }
1542
1543    Ok(())
1544}
1545
1546
1547fn update_object_to_fields_values(object: serde_json::Value) -> Result<(Vec<String>, Vec<product_os_store::Value>), ProductOSRouterError> {
1548    let mut fields = vec!();
1549    let mut values = vec!();
1550
1551    match object.as_object() {
1552        None => (),
1553        Some(update_object) => {
1554            for (key, value) in update_object {
1555                match build_update_object(&mut fields, &mut values, key, value, false, None) {
1556                    Ok(_) => {}
1557                    Err(e) => return Err(e)
1558                }
1559            }
1560        }
1561    }
1562
1563    Ok((fields, values))
1564}
1565
1566
1567fn build_update_object(fields: &mut Vec<String>, values: &mut Vec<product_os_store::Value>, key: &str, value: &serde_json::Value, is_json: bool, json_key: Option<&str>) -> Result<(), ProductOSRouterError> {
1568    match value {
1569        serde_json::Value::Object(obj) => {
1570            tracing::info!("Looping through object value: {:?}", obj);
1571            for (sub_key, sub_value) in obj {
1572                match sub_key.as_str() {
1573                    "$push" => {
1574                        if let serde_json::Value::Object(obj) = sub_value {
1575                            let mut extended_key = String::new();
1576                            let mut sub_value = serde_json::Value::Object(serde_json::Map::new());
1577
1578                            for (s_key, s_value) in obj {
1579                                extended_key = s_key.clone();
1580                                sub_value = s_value.clone();
1581                            }
1582
1583                            extended_key.push(',');
1584                            extended_key.push_str("999999999");
1585
1586                            match update_key_value_to_fields_values(fields, values, key, &sub_value, true, Some(extended_key.as_str())) {
1587                                Ok(_) => {}
1588                                Err(e) => return Err(e)
1589                            }
1590                        }
1591                    }
1592                    "$pull" => {
1593                        /*
1594                        Remove the last tag:
1595                        UPDATE test SET data = data #- '{tags,-1}'
1596                        */
1597                    }
1598                    _ => {
1599                        let extended_key = match json_key {
1600                            None => {
1601                                String::from(sub_key)
1602                            },
1603                            Some(jk) => {
1604                                let mut extended_key = jk.to_string();
1605
1606                                extended_key.push(',');
1607                                extended_key.push_str(sub_key.as_str());
1608
1609                                extended_key
1610                            }
1611                        };
1612
1613                        tracing::info!("Looping through subs {:?} {:?}", extended_key, sub_value);
1614
1615                        match update_key_value_to_fields_values(fields, values, key, sub_value, true, Some(extended_key.as_str())) {
1616                            Ok(_) => {}
1617                            Err(e) => return Err(e)
1618                        }
1619
1620                        /*
1621                        match sub_value {
1622                            serde_json::Value::Object(obj) => {
1623                                if obj.keys().len() > 1 {
1624                                    match update_key_value_to_fields_values(fields, values, key, sub_value, true, Some(extended_key.as_str())) {
1625                                        Ok(_) => {}
1626                                        Err(e) => return Err(e)
1627                                    }
1628                                }
1629                                else {
1630                                    build_update_object(fields, values, key, sub_value, true, Some(extended_key.as_str()));
1631                                }
1632                            },
1633                            _ => {
1634                                match update_key_value_to_fields_values(fields, values, key, sub_value, true, Some(extended_key.as_str())) {
1635                                    Ok(_) => {}
1636                                    Err(e) => return Err(e)
1637                                }
1638                            }
1639                        }
1640                        */
1641                    }
1642                }
1643            }
1644        }
1645        _ => {
1646            match update_key_value_to_fields_values(fields, values, key, value, is_json, json_key) {
1647                Ok(_) => {}
1648                Err(e) => return Err(e)
1649            }
1650        }
1651    }
1652
1653    Ok(())
1654}
1655
1656fn update_key_value_to_fields_values(fields: &mut Vec<String>, values: &mut Vec<product_os_store::Value>, key: &str, value: &serde_json::Value, is_json: bool, json_key: Option<&str>) -> Result<(), ProductOSRouterError> {
1657    if fields.contains(&key.to_string()) && is_json {
1658        match fields.binary_search(&key.to_string()) {
1659            Ok(field_position) => {
1660                let current_value = values.remove(field_position);
1661
1662                if let product_os_store::Value::JsonSet(key, jkey, jvalue) = current_value {
1663                    let store_value = match value {
1664                        serde_json::Value::Null =>product_os_store::Value::Null,
1665                        serde_json::Value::Bool(b) => product_os_store::Value::Boolean(b.to_owned()),
1666                        serde_json::Value::Number(n) => { product_os_store::Value::BigNumber(i128::from(n.as_i64().unwrap())) }
1667                        serde_json::Value::String(s) => product_os_store::Value::String(s.to_string()),
1668                        serde_json::Value::Array(arr) => {
1669                            let mut a = vec!();
1670                            for e in arr {
1671                                match e {
1672                                    serde_json::Value::Bool(b) => { a.push(product_os_store::Value::Boolean(b.to_owned())) },
1673                                    serde_json::Value::Number(n) => { a.push(product_os_store::Value::BigNumber(i128::from(n.as_i64().unwrap()))) }
1674                                    serde_json::Value::String(s) => { a.push(product_os_store::Value::String(s.to_string())) }
1675                                    _ => return Err(ProductOSRouterError::Process("Error processing request data".to_string()))
1676                                }
1677                            };
1678
1679                            product_os_store::Value::Array(a.to_owned())
1680                        }
1681                        obj => {
1682                            product_os_store::Value::Json(obj.clone())
1683                        }
1684                    };
1685
1686                    values.insert(field_position,
1687                    product_os_store::Value::JsonSet(
1688                        Box::new(product_os_store::Value::JsonSet(key.clone(), jkey.clone(), jvalue.clone())),
1689                        json_key.unwrap().to_string(),
1690                        Box::new(store_value)
1691                    ));
1692                }
1693            },
1694            Err(_) => return Err(ProductOSRouterError::Process("Error processing request data".to_string()))
1695        }
1696    }
1697    else {
1698        fields.push(key.to_string());
1699
1700        match value {
1701            serde_json::Value::Null => {
1702                if is_json { values.push(product_os_store::Value::JsonSet(Box::new(product_os_store::Value::Raw(key.to_string())), json_key.unwrap().to_string(), Box::new(product_os_store::Value::Null))); }
1703                else { values.push(product_os_store::Value::Null); }
1704            }
1705            serde_json::Value::Bool(b) => {
1706                if is_json { values.push(product_os_store::Value::JsonSet(Box::new(product_os_store::Value::Raw(key.to_string())), json_key.unwrap().to_string(), Box::new(product_os_store::Value::Boolean(b.to_owned())))); }
1707                else { values.push(product_os_store::Value::Boolean(b.to_owned())); }
1708            }
1709            serde_json::Value::Number(n) => {
1710                if is_json { values.push(product_os_store::Value::JsonSet(Box::new(product_os_store::Value::Raw(key.to_string())), json_key.unwrap().to_string(), Box::new(product_os_store::Value::BigNumber(i128::from(n.as_i64().unwrap()))))); }
1711                else { values.push(product_os_store::Value::BigNumber(i128::from(n.as_i64().unwrap()))); }
1712            }
1713            serde_json::Value::String(s) => {
1714                if is_json { values.push(product_os_store::Value::JsonSet(Box::new(product_os_store::Value::Raw(key.to_string())), json_key.unwrap().to_string(), Box::new(product_os_store::Value::String(s.to_string())))); }
1715                else { values.push(product_os_store::Value::String(s.to_string())); }
1716            }
1717            serde_json::Value::Array(arr) => {
1718                let mut a = vec!();
1719                for e in arr {
1720                    match e {
1721                        serde_json::Value::Bool(b) => { a.push(product_os_store::Value::Boolean(b.to_owned())) },
1722                        serde_json::Value::Number(n) => { a.push(product_os_store::Value::BigNumber(i128::from(n.as_i64().unwrap()))) }
1723                        serde_json::Value::String(s) => { a.push(product_os_store::Value::String(s.to_string())) }
1724                        _ => return Err(ProductOSRouterError::Process("Error processing request data".to_string()))
1725                    }
1726                };
1727
1728                if is_json { values.push(product_os_store::Value::JsonSet(Box::new(product_os_store::Value::Raw(key.to_string())), json_key.unwrap().to_string(), Box::new(product_os_store::Value::Array(a.to_owned())))); }
1729                else { values.push(product_os_store::Value::Array(a.to_owned())); }
1730            }
1731            obj => {
1732                if is_json { values.push(product_os_store::Value::JsonSet(Box::new(product_os_store::Value::Raw(key.to_string())), json_key.unwrap().to_string(), Box::new(product_os_store::Value::Json(obj.clone())))); }
1733                else { values.push(product_os_store::Value::Json(obj.clone())); }
1734            }
1735        }
1736    }
1737
1738
1739
1740    Ok(())
1741}
1742
1743
1744/*
1745    jsonb_set(
1746        jsonb_set(
1747            '{age:26}'::jsonb,
1748            '{age}',
1749            '"30"'::jsonb)::jsonb,
1750        '{city}',
1751        '"new york city"'::jsonb
1752    )
1753*/