Skip to main content

cratestack_sqlx/
delegate.rs

1use cratestack_core::{CoolContext, CoolError};
2
3use crate::{
4    CreateModelInput, CreateRecord, DeleteRecord, Filter, FilterExpr, FindMany, FindUnique,
5    ModelDescriptor, OrderClause, SqlxRuntime, UpdateModelInput, UpdateRecord, UpdateRecordSet,
6};
7
8#[derive(Debug, Clone, Copy)]
9pub struct ModelDelegate<'a, M: 'static, PK: 'static> {
10    runtime: &'a SqlxRuntime,
11    descriptor: &'static ModelDescriptor<M, PK>,
12}
13
14impl<'a, M: 'static, PK: 'static> ModelDelegate<'a, M, PK> {
15    pub fn new(runtime: &'a SqlxRuntime, descriptor: &'static ModelDescriptor<M, PK>) -> Self {
16        Self {
17            runtime,
18            descriptor,
19        }
20    }
21
22    pub fn descriptor(&self) -> &'static ModelDescriptor<M, PK> {
23        self.descriptor
24    }
25
26    pub fn bind(self, ctx: CoolContext) -> ScopedModelDelegate<'a, M, PK> {
27        ScopedModelDelegate {
28            delegate: self,
29            ctx,
30        }
31    }
32
33    pub fn find_many(&self) -> FindMany<'a, M, PK> {
34        FindMany {
35            runtime: self.runtime,
36            descriptor: self.descriptor,
37            filters: Vec::new(),
38            order_by: Vec::new(),
39            limit: None,
40            offset: None,
41        }
42    }
43
44    pub fn find_unique(&self, id: PK) -> FindUnique<'a, M, PK> {
45        FindUnique {
46            runtime: self.runtime,
47            descriptor: self.descriptor,
48            id,
49        }
50    }
51
52    pub fn create<I>(&self, input: I) -> CreateRecord<'a, M, PK, I> {
53        CreateRecord {
54            runtime: self.runtime,
55            descriptor: self.descriptor,
56            input,
57        }
58    }
59
60    pub fn update(&self, id: PK) -> UpdateRecord<'a, M, PK> {
61        UpdateRecord {
62            runtime: self.runtime,
63            descriptor: self.descriptor,
64            id,
65        }
66    }
67
68    pub fn delete(&self, id: PK) -> DeleteRecord<'a, M, PK> {
69        DeleteRecord {
70            runtime: self.runtime,
71            descriptor: self.descriptor,
72            id,
73        }
74    }
75
76    pub async fn authorize_detail(&self, id: PK, ctx: &CoolContext) -> Result<(), CoolError>
77    where
78        PK: Send + sqlx::Type<sqlx::Postgres> + for<'q> sqlx::Encode<'q, sqlx::Postgres>,
79    {
80        crate::query::authorize_record_action(
81            self.runtime,
82            self.descriptor,
83            id,
84            self.descriptor.detail_allow_policies,
85            self.descriptor.detail_deny_policies,
86            ctx,
87            "detail",
88        )
89        .await
90    }
91
92    pub async fn authorize_update(&self, id: PK, ctx: &CoolContext) -> Result<(), CoolError>
93    where
94        PK: Send + sqlx::Type<sqlx::Postgres> + for<'q> sqlx::Encode<'q, sqlx::Postgres>,
95    {
96        crate::query::authorize_record_action(
97            self.runtime,
98            self.descriptor,
99            id,
100            self.descriptor.update_allow_policies,
101            self.descriptor.update_deny_policies,
102            ctx,
103            "update",
104        )
105        .await
106    }
107
108    pub async fn authorize_delete(&self, id: PK, ctx: &CoolContext) -> Result<(), CoolError>
109    where
110        PK: Send + sqlx::Type<sqlx::Postgres> + for<'q> sqlx::Encode<'q, sqlx::Postgres>,
111    {
112        crate::query::authorize_record_action(
113            self.runtime,
114            self.descriptor,
115            id,
116            self.descriptor.delete_allow_policies,
117            self.descriptor.delete_deny_policies,
118            ctx,
119            "delete",
120        )
121        .await
122    }
123}
124
125#[derive(Debug, Clone)]
126pub struct ScopedModelDelegate<'a, M: 'static, PK: 'static> {
127    delegate: ModelDelegate<'a, M, PK>,
128    ctx: CoolContext,
129}
130
131impl<'a, M: 'static, PK: 'static> ScopedModelDelegate<'a, M, PK> {
132    pub fn descriptor(&self) -> &'static ModelDescriptor<M, PK> {
133        self.delegate.descriptor()
134    }
135
136    pub fn context(&self) -> &CoolContext {
137        &self.ctx
138    }
139
140    pub fn find_many(&self) -> ScopedFindMany<'a, M, PK> {
141        ScopedFindMany {
142            request: self.delegate.find_many(),
143            ctx: self.ctx.clone(),
144        }
145    }
146
147    pub fn find_unique(&self, id: PK) -> ScopedFindUnique<'a, M, PK> {
148        ScopedFindUnique {
149            request: self.delegate.find_unique(id),
150            ctx: self.ctx.clone(),
151        }
152    }
153
154    pub fn create<I>(&self, input: I) -> ScopedCreateRecord<'a, M, PK, I> {
155        ScopedCreateRecord {
156            request: self.delegate.create(input),
157            ctx: self.ctx.clone(),
158        }
159    }
160
161    pub fn update(&self, id: PK) -> ScopedUpdateRecord<'a, M, PK> {
162        ScopedUpdateRecord {
163            request: self.delegate.update(id),
164            ctx: self.ctx.clone(),
165        }
166    }
167
168    pub fn delete(&self, id: PK) -> ScopedDeleteRecord<'a, M, PK> {
169        ScopedDeleteRecord {
170            request: self.delegate.delete(id),
171            ctx: self.ctx.clone(),
172        }
173    }
174}
175
176#[derive(Debug, Clone)]
177pub struct ScopedFindMany<'a, M: 'static, PK: 'static> {
178    request: FindMany<'a, M, PK>,
179    ctx: CoolContext,
180}
181
182impl<'a, M: 'static, PK: 'static> ScopedFindMany<'a, M, PK> {
183    pub fn where_(mut self, filter: Filter) -> Self {
184        self.request = self.request.where_(filter);
185        self
186    }
187
188    pub fn where_expr(mut self, filter: FilterExpr) -> Self {
189        self.request = self.request.where_expr(filter);
190        self
191    }
192
193    pub fn where_any(mut self, filters: impl IntoIterator<Item = FilterExpr>) -> Self {
194        self.request = self.request.where_any(filters);
195        self
196    }
197
198    pub fn order_by(mut self, clause: OrderClause) -> Self {
199        self.request = self.request.order_by(clause);
200        self
201    }
202
203    pub fn limit(mut self, limit: i64) -> Self {
204        self.request = self.request.limit(limit);
205        self
206    }
207
208    pub fn offset(mut self, offset: i64) -> Self {
209        self.request = self.request.offset(offset);
210        self
211    }
212
213    pub fn preview_sql(&self) -> String {
214        self.request.preview_sql()
215    }
216
217    pub fn preview_scoped_sql(&self) -> String {
218        self.request.preview_scoped_sql(&self.ctx)
219    }
220
221    pub async fn run(self) -> Result<Vec<M>, CoolError>
222    where
223        for<'r> M: Send + Unpin + sqlx::FromRow<'r, sqlx::postgres::PgRow>,
224    {
225        self.request.run(&self.ctx).await
226    }
227}
228
229#[derive(Debug, Clone)]
230pub struct ScopedFindUnique<'a, M: 'static, PK: 'static> {
231    request: FindUnique<'a, M, PK>,
232    ctx: CoolContext,
233}
234
235impl<'a, M: 'static, PK: 'static> ScopedFindUnique<'a, M, PK> {
236    pub fn preview_sql(&self) -> String {
237        self.request.preview_sql()
238    }
239
240    pub fn preview_scoped_sql(&self) -> String {
241        self.request.preview_scoped_sql(&self.ctx)
242    }
243
244    pub async fn run(self) -> Result<Option<M>, CoolError>
245    where
246        for<'r> M: Send + Unpin + sqlx::FromRow<'r, sqlx::postgres::PgRow>,
247        PK: Send + sqlx::Type<sqlx::Postgres> + for<'q> sqlx::Encode<'q, sqlx::Postgres>,
248    {
249        self.request.run(&self.ctx).await
250    }
251}
252
253#[derive(Debug, Clone)]
254pub struct ScopedCreateRecord<'a, M: 'static, PK: 'static, I> {
255    request: CreateRecord<'a, M, PK, I>,
256    ctx: CoolContext,
257}
258
259impl<'a, M: 'static, PK: 'static, I> ScopedCreateRecord<'a, M, PK, I>
260where
261    I: CreateModelInput<M>,
262{
263    pub fn preview_sql(&self) -> String {
264        self.request.preview_sql()
265    }
266
267    pub async fn run(self) -> Result<M, CoolError>
268    where
269        for<'r> M: Send + Unpin + sqlx::FromRow<'r, sqlx::postgres::PgRow> + serde::Serialize,
270    {
271        self.request.run(&self.ctx).await
272    }
273}
274
275#[derive(Debug, Clone)]
276pub struct ScopedUpdateRecord<'a, M: 'static, PK: 'static> {
277    request: UpdateRecord<'a, M, PK>,
278    ctx: CoolContext,
279}
280
281impl<'a, M: 'static, PK: 'static> ScopedUpdateRecord<'a, M, PK> {
282    pub fn set<I>(self, input: I) -> ScopedUpdateRecordSet<'a, M, PK, I> {
283        ScopedUpdateRecordSet {
284            request: self.request.set(input),
285            ctx: self.ctx,
286        }
287    }
288}
289
290#[derive(Debug, Clone)]
291pub struct ScopedUpdateRecordSet<'a, M: 'static, PK: 'static, I> {
292    request: UpdateRecordSet<'a, M, PK, I>,
293    ctx: CoolContext,
294}
295
296impl<'a, M: 'static, PK: 'static, I> ScopedUpdateRecordSet<'a, M, PK, I>
297where
298    I: UpdateModelInput<M>,
299{
300    pub fn preview_sql(&self) -> String {
301        self.request.preview_sql()
302    }
303
304    pub async fn run(self) -> Result<M, CoolError>
305    where
306        for<'r> M: Send + Unpin + sqlx::FromRow<'r, sqlx::postgres::PgRow> + serde::Serialize,
307        PK: Send + sqlx::Type<sqlx::Postgres> + for<'q> sqlx::Encode<'q, sqlx::Postgres>,
308    {
309        self.request.run(&self.ctx).await
310    }
311}
312
313#[derive(Debug, Clone)]
314pub struct ScopedDeleteRecord<'a, M: 'static, PK: 'static> {
315    request: DeleteRecord<'a, M, PK>,
316    ctx: CoolContext,
317}
318
319impl<'a, M: 'static, PK: 'static> ScopedDeleteRecord<'a, M, PK> {
320    pub fn preview_sql(&self) -> String {
321        self.request.preview_sql()
322    }
323
324    pub async fn run(self) -> Result<M, CoolError>
325    where
326        for<'r> M: Send + Unpin + sqlx::FromRow<'r, sqlx::postgres::PgRow> + serde::Serialize,
327        PK: Send + sqlx::Type<sqlx::Postgres> + for<'q> sqlx::Encode<'q, sqlx::Postgres>,
328    {
329        self.request.run(&self.ctx).await
330    }
331}