Skip to main content

cratestack_core/
find_many.rs

1//! Built-in support for the `FindMany<Model>` procedure-argument type
2//! (`.cstack` syntax) — search-with-filters for procedures. Composes
3//! with `PageInput` rather than absorbing it — a procedure wanting both
4//! filtering and pagination declares two arguments, e.g. `procedure
5//! search(query: FindMany<Post>, page: PageInput): Page<Post>`.
6//!
7//! This module holds only the one piece that's genuinely shared across
8//! every model: the per-field operator envelope. Everything else — which
9//! fields a model has, which operators apply to which field — is
10//! per-model and lives in `cratestack-macros`-generated code
11//! (`<Model>Where`, `<Model>SortField`, `<Model>OrderByClause`,
12//! `<Model>FindManyInput`), mirroring how `Create<Model>Input`/
13//! `Update<Model>Input` are per-model generated structs rather than one
14//! shared generic wrapper.
15
16use serde::{Deserialize, Serialize};
17
18/// Every operator a filterable field might support, as one flat
19/// optional-per-operator envelope — generated per-model code reads only
20/// the operators that make sense for a given field's type (e.g. a
21/// `Boolean` field's generated `to_filters()` never looks at `contains`).
22/// `V` is the field's own scalar Rust type (`String`, `i64`, `bool`,
23/// `chrono::DateTime<Utc>`, ...) — never `Option<V>` even for an optional
24/// field, since these operators describe a *value to compare against*,
25/// not the field's own nullability (which `is_null` covers instead).
26///
27/// Deliberately not full parity with every `FieldRef` method:
28/// `isTrue`/`isFalse` are omitted (redundant with `eq: true`/`eq: false`
29/// once callers have a real JSON boolean) and `eqOrNull` is omitted (a
30/// Rust-ergonomics convenience over `eq` + `isNull`, not new capability).
31#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
32#[serde(rename_all = "camelCase")]
33pub struct FieldFilterInput<V> {
34    pub eq: Option<V>,
35    pub ne: Option<V>,
36    #[serde(rename = "in")]
37    pub in_: Option<Vec<V>>,
38    pub lt: Option<V>,
39    pub lte: Option<V>,
40    pub gt: Option<V>,
41    pub gte: Option<V>,
42    /// String/`Cuid`/`Uuid` fields only.
43    pub contains: Option<String>,
44    /// String/`Cuid`/`Uuid` fields only.
45    pub starts_with: Option<String>,
46    /// Optional-arity fields only. `Some(true)` filters to rows where
47    /// the column is `NULL`; `Some(false)` filters to rows where it is
48    /// not.
49    pub is_null: Option<bool>,
50}