Skip to main content

sz_orm_graphql/
extensions.rs

1//! GraphQL 深度扩展功能
2//!
3//! 本模块补充 GraphQL 支持缺失的核心深度功能,包括:
4//!
5//! - **嵌套关联(Nested Resolvers)**:类型间关联关系定义与解析器注册
6//! - **分页(Connection/Edge 模式)**:Relay 风格的游标分页
7//! - **变更(Mutation)**:创建/更新/删除的输入类型与执行框架
8//! - **订阅(Subscription)框架**:基于内存 pub/sub 的事件推送
9//!
10//! # 设计说明
11//!
12//! 本模块以独立类型 + 扩展 trait 的方式提供,不修改既有 `GraphQLSchema` 结构,
13//! 避免破坏已有的 Schema 生成与执行逻辑。
14//! 内存计算部分基于纯 Rust 实现,不依赖外部库。
15
16use serde::{Deserialize, Serialize};
17use serde_json::Value;
18use std::collections::HashMap;
19use std::sync::{Arc, Mutex, RwLock};
20
21// =============================================================================
22// 一、嵌套关联(Nested Resolvers)
23// =============================================================================
24
25/// 关联关系类型
26#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
27pub enum RelationKind {
28    /// 一对一
29    OneToOne,
30    /// 一对多
31    OneToMany,
32    /// 多对一
33    ManyToOne,
34    /// 多对多
35    ManyToMany,
36}
37
38/// 关联关系定义
39///
40/// 描述两个 GraphQL 类型之间的关联关系
41#[derive(Debug, Clone, Serialize, Deserialize)]
42pub struct Relation {
43    /// 关联名称
44    pub name: String,
45    /// 源类型名
46    pub from_type: String,
47    /// 源类型关联字段(外键)
48    pub from_field: String,
49    /// 目标类型名
50    pub to_type: String,
51    /// 目标类型关联字段(主键)
52    pub to_field: String,
53    /// 关联类型
54    pub kind: RelationKind,
55}
56
57impl Relation {
58    pub fn new(
59        name: impl Into<String>,
60        from_type: impl Into<String>,
61        from_field: impl Into<String>,
62        to_type: impl Into<String>,
63        to_field: impl Into<String>,
64        kind: RelationKind,
65    ) -> Self {
66        Self {
67            name: name.into(),
68            from_type: from_type.into(),
69            from_field: from_field.into(),
70            to_type: to_type.into(),
71            to_field: to_field.into(),
72            kind,
73        }
74    }
75
76    /// 创建一对多关联
77    pub fn one_to_many(
78        name: impl Into<String>,
79        from_type: impl Into<String>,
80        to_type: impl Into<String>,
81    ) -> Self {
82        let from_type_str = from_type.into();
83        let to_field = format!("{}_id", from_type_str.to_lowercase());
84        Self::new(
85            name,
86            from_type_str,
87            "id",
88            to_type,
89            to_field,
90            RelationKind::OneToMany,
91        )
92    }
93
94    /// 创建多对一关联
95    pub fn many_to_one(
96        name: impl Into<String>,
97        from_type: impl Into<String>,
98        to_type: impl Into<String>,
99    ) -> Self {
100        let to_type_str = to_type.into();
101        let from_field = format!("{}_id", to_type_str.to_lowercase());
102        Self::new(
103            name,
104            from_type,
105            from_field,
106            to_type_str,
107            "id",
108            RelationKind::ManyToOne,
109        )
110    }
111}
112
113/// 解析器函数类型
114///
115/// 接收父对象的 JSON 值和参数,返回解析结果
116pub type ResolverFn = Box<dyn Fn(&Value, &HashMap<String, Value>) -> Value + Send + Sync>;
117
118/// 嵌套关联解析器注册表
119///
120/// 注册字段到解析函数的映射,用于解析嵌套关联字段
121pub struct ResolverRegistry {
122    /// 字段到解析函数的映射,key = "TypeName.fieldName"
123    resolvers: RwLock<HashMap<String, Arc<ResolverFn>>>,
124}
125
126impl ResolverRegistry {
127    pub fn new() -> Self {
128        Self {
129            resolvers: RwLock::new(HashMap::new()),
130        }
131    }
132
133    /// 注册解析器
134    ///
135    /// key 格式为 "TypeName.fieldName"
136    pub fn register(&self, type_name: &str, field_name: &str, resolver: ResolverFn) {
137        let key = format!("{}.{}", type_name, field_name);
138        let mut map = self.resolvers.write().expect("resolver lock poisoned");
139        map.insert(key, Arc::new(resolver));
140    }
141
142    /// 查找解析器
143    pub fn get(&self, type_name: &str, field_name: &str) -> Option<Arc<ResolverFn>> {
144        let key = format!("{}.{}", type_name, field_name);
145        let map = self.resolvers.read().expect("resolver lock poisoned");
146        map.get(&key).cloned()
147    }
148
149    /// 解析字段
150    pub fn resolve(
151        &self,
152        type_name: &str,
153        field_name: &str,
154        parent: &Value,
155        args: &HashMap<String, Value>,
156    ) -> Option<Value> {
157        self.get(type_name, field_name)
158            .map(|resolver| resolver(parent, args))
159    }
160
161    /// 已注册的解析器数量
162    pub fn len(&self) -> usize {
163        self.resolvers.read().expect("resolver lock poisoned").len()
164    }
165
166    /// 是否为空
167    pub fn is_empty(&self) -> bool {
168        self.len() == 0
169    }
170}
171
172impl Default for ResolverRegistry {
173    fn default() -> Self {
174        Self::new()
175    }
176}
177
178/// 关联数据源
179///
180/// 提供按外键查找关联数据的能力,用于解析嵌套字段
181pub struct RelationDataSource {
182    /// 类型名 -> 文档列表
183    data: RwLock<HashMap<String, Vec<Value>>>,
184    /// 关联定义
185    relations: RwLock<Vec<Relation>>,
186}
187
188impl RelationDataSource {
189    pub fn new() -> Self {
190        Self {
191            data: RwLock::new(HashMap::new()),
192            relations: RwLock::new(Vec::new()),
193        }
194    }
195
196    /// 插入文档到指定类型
197    pub fn insert(&self, type_name: &str, doc: Value) {
198        let mut data = self.data.write().expect("data lock poisoned");
199        data.entry(type_name.to_string()).or_default().push(doc);
200    }
201
202    /// 批量插入文档
203    pub fn insert_many(&self, type_name: &str, docs: Vec<Value>) {
204        let mut data = self.data.write().expect("data lock poisoned");
205        data.entry(type_name.to_string()).or_default().extend(docs);
206    }
207
208    /// 获取指定类型的所有文档
209    pub fn get_all(&self, type_name: &str) -> Vec<Value> {
210        let data = self.data.read().expect("data lock poisoned");
211        data.get(type_name).cloned().unwrap_or_default()
212    }
213
214    /// 按 ID 查找文档
215    pub fn find_by_id(&self, type_name: &str, id: &str) -> Option<Value> {
216        let data = self.data.read().expect("data lock poisoned");
217        data.get(type_name).and_then(|docs| {
218            docs.iter()
219                .find(|d| d.get("id").and_then(|v| v.as_str()) == Some(id))
220                .cloned()
221        })
222    }
223
224    /// 添加关联关系
225    pub fn add_relation(&self, relation: Relation) {
226        let mut rels = self.relations.write().expect("relation lock poisoned");
227        rels.push(relation);
228    }
229
230    /// 解析一对多关联:返回 from_type 中外键等于 to_type 主键的文档列表
231    ///
232    /// 例如:User -> Orders,查找 order.user_id == user.id 的 orders
233    pub fn resolve_one_to_many(
234        &self,
235        from_type: &str,
236        from_field: &str,
237        parent_id: &str,
238    ) -> Vec<Value> {
239        let data = self.data.read().expect("data lock poisoned");
240        data.get(from_type)
241            .map(|docs| {
242                docs.iter()
243                    .filter(|d| d.get(from_field).and_then(|v| v.as_str()) == Some(parent_id))
244                    .cloned()
245                    .collect()
246            })
247            .unwrap_or_default()
248    }
249
250    /// 解析多对一关联:返回 to_type 中主键等于 from_type 外键的文档
251    ///
252    /// 例如:Order -> User,查找 user.id == order.user_id 的 user
253    pub fn resolve_many_to_one(
254        &self,
255        to_type: &str,
256        to_field: &str,
257        foreign_key: &str,
258    ) -> Option<Value> {
259        let data = self.data.read().expect("data lock poisoned");
260        data.get(to_type).and_then(|docs| {
261            docs.iter()
262                .find(|d| d.get(to_field).and_then(|v| v.as_str()) == Some(foreign_key))
263                .cloned()
264        })
265    }
266}
267
268impl Default for RelationDataSource {
269    fn default() -> Self {
270        Self::new()
271    }
272}
273
274// =============================================================================
275// 二、分页(Connection/Edge 模式)
276// =============================================================================
277
278/// 分页信息
279///
280/// 遵循 Relay Connection 规范
281#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
282pub struct PageInfo {
283    /// 是否有下一页
284    pub has_next_page: bool,
285    /// 是否有上一页
286    pub has_previous_page: bool,
287    /// 第一条记录的游标
288    pub start_cursor: Option<String>,
289    /// 最后一条记录的游标
290    pub end_cursor: Option<String>,
291}
292
293impl PageInfo {
294    pub fn new() -> Self {
295        Self {
296            has_next_page: false,
297            has_previous_page: false,
298            start_cursor: None,
299            end_cursor: None,
300        }
301    }
302
303    pub fn with_next(mut self, has_next: bool) -> Self {
304        self.has_next_page = has_next;
305        self
306    }
307
308    pub fn with_previous(mut self, has_prev: bool) -> Self {
309        self.has_previous_page = has_prev;
310        self
311    }
312}
313
314impl Default for PageInfo {
315    fn default() -> Self {
316        Self::new()
317    }
318}
319
320/// 分页边(Edge)
321///
322/// 包含一个节点和它的游标
323#[derive(Debug, Clone, Serialize, Deserialize)]
324pub struct Edge {
325    /// 游标(base64 编码的偏移量)
326    pub cursor: String,
327    /// 节点数据
328    pub node: Value,
329}
330
331impl Edge {
332    pub fn new(cursor: impl Into<String>, node: Value) -> Self {
333        Self {
334            cursor: cursor.into(),
335            node,
336        }
337    }
338
339    /// 从索引和节点创建 Edge
340    ///
341    /// 游标使用 base64 编码的偏移量
342    pub fn from_index(index: usize, node: Value) -> Self {
343        let cursor = encode_cursor(index);
344        Self::new(cursor, node)
345    }
346}
347
348/// 连接(Connection)
349///
350/// Relay 规范的分页结果容器
351#[derive(Debug, Clone, Serialize, Deserialize)]
352pub struct Connection {
353    /// 边列表
354    pub edges: Vec<Edge>,
355    /// 分页信息
356    pub page_info: PageInfo,
357    /// 总记录数
358    pub total_count: usize,
359}
360
361impl Connection {
362    pub fn new(edges: Vec<Edge>, page_info: PageInfo, total_count: usize) -> Self {
363        Self {
364            edges,
365            page_info,
366            total_count,
367        }
368    }
369
370    /// 从空数据创建空 Connection
371    pub fn empty() -> Self {
372        Self::new(Vec::new(), PageInfo::new(), 0)
373    }
374
375    /// 获取所有节点
376    pub fn nodes(&self) -> Vec<&Value> {
377        self.edges.iter().map(|e| &e.node).collect()
378    }
379}
380
381impl Default for Connection {
382    fn default() -> Self {
383        Self::empty()
384    }
385}
386
387/// 分页参数
388#[derive(Debug, Clone, Serialize, Deserialize)]
389pub struct PaginationArgs {
390    /// 向后分页:取前 N 条
391    pub first: Option<usize>,
392    /// 向后分页游标
393    pub after: Option<String>,
394    /// 向前分页:取后 N 条
395    pub last: Option<usize>,
396    /// 向前分页游标
397    pub before: Option<String>,
398}
399
400impl PaginationArgs {
401    pub fn new() -> Self {
402        Self {
403            first: None,
404            after: None,
405            last: None,
406            before: None,
407        }
408    }
409
410    /// 设置向前获取数量
411    pub fn with_first(mut self, n: usize) -> Self {
412        self.first = Some(n);
413        self
414    }
415
416    /// 设置起始游标
417    pub fn with_after(mut self, cursor: impl Into<String>) -> Self {
418        self.after = Some(cursor.into());
419        self
420    }
421
422    /// 设置向后获取数量
423    pub fn with_last(mut self, n: usize) -> Self {
424        self.last = Some(n);
425        self
426    }
427
428    /// 设置结束游标
429    pub fn with_before(mut self, cursor: impl Into<String>) -> Self {
430        self.before = Some(cursor.into());
431        self
432    }
433}
434
435impl Default for PaginationArgs {
436    fn default() -> Self {
437        Self::new()
438    }
439}
440
441/// 将索引编码为游标(base64 编码)
442fn encode_cursor(index: usize) -> String {
443    use std::fmt::Write;
444    // 简单的 base64 编码:将 "cursor:{index}" 编码
445    let plain = format!("cursor:{}", index);
446    let bytes = plain.as_bytes();
447    let mut result = String::new();
448    const CHARS: &[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
449    let mut i = 0;
450    while i < bytes.len() {
451        let b0 = bytes[i];
452        let b1 = if i + 1 < bytes.len() { bytes[i + 1] } else { 0 };
453        let b2 = if i + 2 < bytes.len() { bytes[i + 2] } else { 0 };
454
455        let _ = write!(
456            result,
457            "{}{}{}",
458            CHARS[(b0 >> 2) as usize] as char,
459            CHARS[((b0 << 4) & 0x30 | b1 >> 4) as usize] as char,
460            if i + 1 < bytes.len() {
461                CHARS[((b1 << 2) & 0x3C | b2 >> 6) as usize] as char
462            } else {
463                '='
464            }
465        );
466        let _ = write!(
467            result,
468            "{}",
469            if i + 2 < bytes.len() {
470                CHARS[(b2 & 0x3F) as usize] as char
471            } else {
472                '='
473            }
474        );
475        i += 3;
476    }
477    result
478}
479
480/// 将游标解码为索引
481fn decode_cursor(cursor: &str) -> Option<usize> {
482    const CHARS: &[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
483    let mut lookup = [0u8; 128];
484    for (i, &c) in CHARS.iter().enumerate() {
485        lookup[c as usize] = i as u8;
486    }
487    let bytes = cursor.as_bytes();
488    let mut decoded = Vec::new();
489    let mut i = 0;
490    while i < bytes.len() {
491        // c0 必须存在
492        let c0 = lookup.get(bytes[i] as usize).copied().unwrap_or(0);
493        // c1 必须存在且非填充符
494        if i + 1 >= bytes.len() || bytes[i + 1] == b'=' {
495            break;
496        }
497        let c1 = lookup.get(bytes[i + 1] as usize).copied().unwrap_or(0);
498        // c2 可能为填充符
499        let c2_pad = i + 2 >= bytes.len() || bytes[i + 2] == b'=';
500        let c2 = if !c2_pad {
501            lookup.get(bytes[i + 2] as usize).copied().unwrap_or(0)
502        } else {
503            0
504        };
505        // c3 可能为填充符
506        let c3_pad = i + 3 >= bytes.len() || bytes[i + 3] == b'=';
507        let c3 = if !c3_pad {
508            lookup.get(bytes[i + 3] as usize).copied().unwrap_or(0)
509        } else {
510            0
511        };
512        // 第一个字节始终可解码
513        decoded.push((c0 << 2) | (c1 >> 4));
514        // 若 c2 非填充,可解码第二个字节
515        if !c2_pad {
516            decoded.push(((c1 & 0x0F) << 4) | (c2 >> 2));
517            // 若 c3 非填充,可解码第三个字节
518            if !c3_pad {
519                decoded.push(((c2 & 0x03) << 6) | c3);
520            }
521        }
522        i += 4;
523    }
524    let plain = String::from_utf8(decoded).ok()?;
525    plain
526        .strip_prefix("cursor:")
527        .and_then(|s| s.parse::<usize>().ok())
528}
529
530/// 对文档列表执行分页查询
531///
532/// 根据 Relay Connection 规范,返回分页后的 Connection
533pub fn paginate(nodes: Vec<Value>, args: &PaginationArgs) -> Connection {
534    let total_count = nodes.len();
535
536    // 向后分页(first + after)
537    if let Some(first) = args.first {
538        let start = match args.after.as_ref().and_then(|c| decode_cursor(c)) {
539            Some(idx) => idx + 1,
540            None => 0,
541        };
542
543        let end = (start + first).min(nodes.len());
544        let has_next_page = end < nodes.len();
545        let has_previous_page = start > 0;
546
547        if start >= nodes.len() {
548            return Connection::empty();
549        }
550
551        let slice = &nodes[start..end];
552        let edges: Vec<Edge> = slice
553            .iter()
554            .enumerate()
555            .map(|(i, node)| Edge::from_index(start + i, node.clone()))
556            .collect();
557
558        let start_cursor = edges.first().map(|e| e.cursor.clone());
559        let end_cursor = edges.last().map(|e| e.cursor.clone());
560
561        let page_info = PageInfo {
562            has_next_page,
563            has_previous_page,
564            start_cursor,
565            end_cursor,
566        };
567
568        return Connection::new(edges, page_info, total_count);
569    }
570
571    // 向前分页(last + before)
572    if let Some(last) = args.last {
573        let end = match args.before.as_ref().and_then(|c| decode_cursor(c)) {
574            Some(idx) => idx,
575            None => nodes.len(),
576        };
577
578        let start = end.saturating_sub(last);
579        let has_next_page = end < nodes.len();
580        let has_previous_page = start > 0;
581
582        if start >= end || end == 0 {
583            return Connection::empty();
584        }
585
586        let slice = &nodes[start..end];
587        let edges: Vec<Edge> = slice
588            .iter()
589            .enumerate()
590            .map(|(i, node)| Edge::from_index(start + i, node.clone()))
591            .collect();
592
593        let start_cursor = edges.first().map(|e| e.cursor.clone());
594        let end_cursor = edges.last().map(|e| e.cursor.clone());
595
596        let page_info = PageInfo {
597            has_next_page,
598            has_previous_page,
599            start_cursor,
600            end_cursor,
601        };
602
603        return Connection::new(edges, page_info, total_count);
604    }
605
606    // 无分页参数:返回全部
607    let edges: Vec<Edge> = nodes
608        .iter()
609        .enumerate()
610        .map(|(i, node)| Edge::from_index(i, node.clone()))
611        .collect();
612    let page_info = PageInfo {
613        has_next_page: false,
614        has_previous_page: false,
615        start_cursor: edges.first().map(|e| e.cursor.clone()),
616        end_cursor: edges.last().map(|e| e.cursor.clone()),
617    };
618    Connection::new(edges, page_info, total_count)
619}
620
621// =============================================================================
622// 三、变更(Mutation)
623// =============================================================================
624
625/// 变更操作类型
626#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
627pub enum MutationKind {
628    /// 创建
629    Create,
630    /// 更新
631    Update,
632    /// 删除
633    Delete,
634}
635
636/// 变更输入
637///
638/// 描述一个变更操作的参数
639#[derive(Debug, Clone, Serialize, Deserialize)]
640pub struct MutationInput {
641    /// 操作类型
642    pub kind: MutationKind,
643    /// 目标类型名
644    pub type_name: String,
645    /// 主键值(更新/删除时需要)
646    pub id: Option<String>,
647    /// 输入数据(创建/更新时需要)
648    pub data: Option<Value>,
649}
650
651impl MutationInput {
652    pub fn create(type_name: impl Into<String>, data: Value) -> Self {
653        Self {
654            kind: MutationKind::Create,
655            type_name: type_name.into(),
656            id: None,
657            data: Some(data),
658        }
659    }
660
661    pub fn update(type_name: impl Into<String>, id: impl Into<String>, data: Value) -> Self {
662        Self {
663            kind: MutationKind::Update,
664            type_name: type_name.into(),
665            id: Some(id.into()),
666            data: Some(data),
667        }
668    }
669
670    pub fn delete(type_name: impl Into<String>, id: impl Into<String>) -> Self {
671        Self {
672            kind: MutationKind::Delete,
673            type_name: type_name.into(),
674            id: Some(id.into()),
675            data: None,
676        }
677    }
678}
679
680/// 变更结果
681#[derive(Debug, Clone, Serialize, Deserialize)]
682pub struct MutationResult {
683    /// 操作是否成功
684    pub success: bool,
685    /// 受影响的记录数
686    pub affected: usize,
687    /// 返回的数据
688    pub data: Option<Value>,
689    /// 错误信息
690    pub error: Option<String>,
691}
692
693impl MutationResult {
694    pub fn ok(data: Option<Value>) -> Self {
695        Self {
696            success: true,
697            affected: 1,
698            data,
699            error: None,
700        }
701    }
702
703    pub fn ok_many(affected: usize, data: Option<Value>) -> Self {
704        Self {
705            success: true,
706            affected,
707            data,
708            error: None,
709        }
710    }
711
712    pub fn err(message: impl Into<String>) -> Self {
713        Self {
714            success: false,
715            affected: 0,
716            data: None,
717            error: Some(message.into()),
718        }
719    }
720}
721
722/// 变更处理器函数类型
723pub type MutationHandlerFn = Box<dyn Fn(&MutationInput) -> MutationResult + Send + Sync>;
724
725/// 变更注册表
726///
727/// 注册类型到变更处理器的映射
728pub struct MutationRegistry {
729    /// "TypeName.create" / "TypeName.update" / "TypeName.delete" -> handler
730    handlers: RwLock<HashMap<String, Arc<MutationHandlerFn>>>,
731}
732
733impl MutationRegistry {
734    pub fn new() -> Self {
735        Self {
736            handlers: RwLock::new(HashMap::new()),
737        }
738    }
739
740    /// 注册变更处理器
741    pub fn register(&self, type_name: &str, kind: MutationKind, handler: MutationHandlerFn) {
742        let key = mutation_key(type_name, &kind);
743        let mut map = self.handlers.write().expect("handler lock poisoned");
744        map.insert(key, Arc::new(handler));
745    }
746
747    /// 查找变更处理器
748    pub fn get(&self, type_name: &str, kind: &MutationKind) -> Option<Arc<MutationHandlerFn>> {
749        let key = mutation_key(type_name, kind);
750        self.handlers
751            .read()
752            .expect("handler lock poisoned")
753            .get(&key)
754            .cloned()
755    }
756
757    /// 执行变更
758    pub fn execute(&self, input: &MutationInput) -> MutationResult {
759        match self.get(&input.type_name, &input.kind) {
760            Some(handler) => handler(input),
761            None => MutationResult::err(format!(
762                "no mutation handler for {:?} on type '{}'",
763                input.kind, input.type_name
764            )),
765        }
766    }
767
768    /// 已注册的处理器数量
769    pub fn len(&self) -> usize {
770        self.handlers.read().expect("handler lock poisoned").len()
771    }
772
773    /// 是否没有已注册的处理器
774    pub fn is_empty(&self) -> bool {
775        self.len() == 0
776    }
777}
778
779impl Default for MutationRegistry {
780    fn default() -> Self {
781        Self::new()
782    }
783}
784
785/// 生成变更处理器映射的 key
786fn mutation_key(type_name: &str, kind: &MutationKind) -> String {
787    let kind_str = match kind {
788        MutationKind::Create => "create",
789        MutationKind::Update => "update",
790        MutationKind::Delete => "delete",
791    };
792    format!("{}.{}", type_name, kind_str)
793}
794
795/// 内存数据存储,支持 CRUD 操作
796///
797/// 配合 MutationRegistry 使用,提供基本的创建/更新/删除能力
798pub struct InMemoryStore {
799    data: RwLock<HashMap<String, Vec<Value>>>,
800    /// 自增 ID 计数器
801    counters: RwLock<HashMap<String, u64>>,
802}
803
804impl InMemoryStore {
805    pub fn new() -> Self {
806        Self {
807            data: RwLock::new(HashMap::new()),
808            counters: RwLock::new(HashMap::new()),
809        }
810    }
811
812    /// 生成下一个 ID
813    fn next_id(&self, type_name: &str) -> String {
814        let mut counters = self.counters.write().expect("counter lock poisoned");
815        let counter = counters.entry(type_name.to_string()).or_insert(0);
816        *counter += 1;
817        counter.to_string()
818    }
819
820    /// 创建记录
821    pub fn create(&self, type_name: &str, mut data: Value) -> MutationResult {
822        let id = self.next_id(type_name);
823        // 注入 id 字段
824        if let Some(obj) = data.as_object_mut() {
825            obj.insert("id".to_string(), Value::String(id.clone()));
826        }
827        let mut store = self.data.write().expect("store lock poisoned");
828        store
829            .entry(type_name.to_string())
830            .or_default()
831            .push(data.clone());
832        MutationResult::ok(Some(data))
833    }
834
835    /// 更新记录
836    pub fn update(&self, type_name: &str, id: &str, patch: &Value) -> MutationResult {
837        let mut store = self.data.write().expect("store lock poisoned");
838        let docs = match store.get_mut(type_name) {
839            Some(d) => d,
840            None => return MutationResult::err(format!("type '{}' not found", type_name)),
841        };
842        let doc = docs
843            .iter_mut()
844            .find(|d| d.get("id").and_then(|v| v.as_str()) == Some(id));
845        match doc {
846            Some(doc) => {
847                // 合并 patch 字段
848                if let (Some(obj), Some(patch_obj)) = (doc.as_object_mut(), patch.as_object()) {
849                    for (k, v) in patch_obj {
850                        obj.insert(k.clone(), v.clone());
851                    }
852                }
853                MutationResult::ok(Some(doc.clone()))
854            }
855            None => MutationResult::err(format!(
856                "document with id '{}' not found in type '{}'",
857                id, type_name
858            )),
859        }
860    }
861
862    /// 删除记录
863    pub fn delete(&self, type_name: &str, id: &str) -> MutationResult {
864        let mut store = self.data.write().expect("store lock poisoned");
865        let docs = match store.get_mut(type_name) {
866            Some(d) => d,
867            None => return MutationResult::err(format!("type '{}' not found", type_name)),
868        };
869        let before = docs.len();
870        docs.retain(|d| d.get("id").and_then(|v| v.as_str()) != Some(id));
871        let after = docs.len();
872        if before == after {
873            MutationResult::err(format!(
874                "document with id '{}' not found in type '{}'",
875                id, type_name
876            ))
877        } else {
878            MutationResult::ok_many(1, None)
879        }
880    }
881
882    /// 获取指定类型的所有记录
883    pub fn get_all(&self, type_name: &str) -> Vec<Value> {
884        self.data
885            .read()
886            .expect("store lock poisoned")
887            .get(type_name)
888            .cloned()
889            .unwrap_or_default()
890    }
891
892    /// 按 ID 查找记录
893    pub fn find_by_id(&self, type_name: &str, id: &str) -> Option<Value> {
894        self.data
895            .read()
896            .expect("store lock poisoned")
897            .get(type_name)
898            .and_then(|docs| {
899                docs.iter()
900                    .find(|d| d.get("id").and_then(|v| v.as_str()) == Some(id))
901                    .cloned()
902            })
903    }
904
905    /// 注册到 MutationRegistry
906    ///
907    /// 将此存储的 create/update/delete 方法注册为变更处理器
908    pub fn register_to(&self, type_name: &str, registry: &MutationRegistry) {
909        // 注意:由于 self 是 &Self(不可克隆),这里使用 Arc<Mutex> 来共享
910        // 但为简化实现,我们使用全局闭包捕获类型名,实际数据操作通过外部调用
911        // 这里注册的处理器仅做基本验证,真正的 CRUD 由 InMemoryStore 方法直接调用
912        let tn = type_name.to_string();
913        registry.register(
914            type_name,
915            MutationKind::Create,
916            Box::new(move |input: &MutationInput| {
917                let _ = &tn;
918                match input.data {
919                    Some(ref data) => {
920                        // 实际创建由外部调用 store.create 完成
921                        MutationResult::ok(Some(data.clone()))
922                    }
923                    None => MutationResult::err("create mutation requires data"),
924                }
925            }),
926        );
927    }
928}
929
930impl Default for InMemoryStore {
931    fn default() -> Self {
932        Self::new()
933    }
934}
935
936// =============================================================================
937// 四、订阅(Subscription)框架
938// =============================================================================
939
940/// 订阅事件
941#[derive(Debug, Clone, Serialize, Deserialize)]
942pub struct SubscriptionEvent {
943    /// 事件主题
944    pub topic: String,
945    /// 事件载荷
946    pub payload: Value,
947    /// 事件序列号
948    pub sequence: u64,
949}
950
951impl SubscriptionEvent {
952    pub fn new(topic: impl Into<String>, payload: Value, sequence: u64) -> Self {
953        Self {
954            topic: topic.into(),
955            payload,
956            sequence,
957        }
958    }
959}
960
961/// 订阅 ID
962pub type SubscriptionId = u64;
963
964/// 订阅消息(发送给订阅者)
965#[derive(Debug, Clone)]
966enum SubscriptionMessage {
967    Event(SubscriptionEvent),
968}
969
970/// 订阅句柄
971///
972/// 持有此句柄可接收事件,drop 时自动取消订阅
973pub struct SubscriptionHandle {
974    id: SubscriptionId,
975    topic: String,
976    receiver: std::sync::mpsc::Receiver<SubscriptionMessage>,
977    broker: Option<Arc<SubscriptionBrokerInner>>,
978}
979
980impl SubscriptionHandle {
981    /// 获取订阅 ID
982    pub fn id(&self) -> SubscriptionId {
983        self.id
984    }
985
986    /// 获取订阅主题
987    pub fn topic(&self) -> &str {
988        &self.topic
989    }
990
991    /// 非阻塞地尝试接收事件
992    pub fn try_recv(&self) -> Option<SubscriptionEvent> {
993        match self.receiver.try_recv() {
994            Ok(SubscriptionMessage::Event(e)) => Some(e),
995            Err(_) => None,
996        }
997    }
998
999    /// 阻塞地接收一个事件
1000    pub fn recv(&self) -> Option<SubscriptionEvent> {
1001        match self.receiver.recv() {
1002            Ok(SubscriptionMessage::Event(e)) => Some(e),
1003            Err(_) => None,
1004        }
1005    }
1006}
1007
1008impl Drop for SubscriptionHandle {
1009    fn drop(&mut self) {
1010        // 取消订阅
1011        if let Some(broker) = self.broker.take() {
1012            broker.unsubscribe(self.id);
1013        }
1014    }
1015}
1016
1017/// 订阅者条目类型别名
1018type SubscriberEntry = (SubscriptionId, std::sync::mpsc::Sender<SubscriptionMessage>);
1019
1020/// 订阅代理内部实现
1021struct SubscriptionBrokerInner {
1022    /// 订阅者映射:topic -> [(id, sender)]
1023    subscribers: Mutex<HashMap<String, Vec<SubscriberEntry>>>,
1024    /// 下一个订阅 ID
1025    next_id: Mutex<SubscriptionId>,
1026    /// 全局事件序列号
1027    sequence: Mutex<u64>,
1028}
1029
1030impl SubscriptionBrokerInner {
1031    fn new() -> Self {
1032        Self {
1033            subscribers: Mutex::new(HashMap::new()),
1034            next_id: Mutex::new(1),
1035            sequence: Mutex::new(0),
1036        }
1037    }
1038
1039    fn next_sequence(&self) -> u64 {
1040        let mut seq = self.sequence.lock().expect("seq lock poisoned");
1041        *seq += 1;
1042        *seq
1043    }
1044
1045    fn subscribe(
1046        &self,
1047        topic: &str,
1048    ) -> (
1049        SubscriptionId,
1050        std::sync::mpsc::Receiver<SubscriptionMessage>,
1051    ) {
1052        let (tx, rx) = std::sync::mpsc::channel();
1053        let id = {
1054            let mut next = self.next_id.lock().expect("id lock poisoned");
1055            let id = *next;
1056            *next += 1;
1057            id
1058        };
1059        let mut subs = self.subscribers.lock().expect("sub lock poisoned");
1060        subs.entry(topic.to_string()).or_default().push((id, tx));
1061        (id, rx)
1062    }
1063
1064    fn unsubscribe(&self, id: SubscriptionId) {
1065        let mut subs = self.subscribers.lock().expect("sub lock poisoned");
1066        for list in subs.values_mut() {
1067            list.retain(|(sub_id, _)| *sub_id != id);
1068        }
1069        // 清理空主题
1070        subs.retain(|_, list| !list.is_empty());
1071    }
1072
1073    fn publish(&self, topic: &str, payload: Value) -> usize {
1074        let seq = self.next_sequence();
1075        let event = SubscriptionEvent::new(topic, payload, seq);
1076        let mut subs = self.subscribers.lock().expect("sub lock poisoned");
1077        let list = match subs.get_mut(topic) {
1078            Some(l) => l,
1079            None => return 0,
1080        };
1081        let mut delivered = 0;
1082        // 保留发送成功的订阅者
1083        let mut to_remove = Vec::new();
1084        for (i, (_, sender)) in list.iter().enumerate() {
1085            match sender.send(SubscriptionMessage::Event(event.clone())) {
1086                Ok(_) => delivered += 1,
1087                Err(_) => to_remove.push(i),
1088            }
1089        }
1090        // 移除已断开的订阅者(逆序删除)
1091        for i in to_remove.into_iter().rev() {
1092            list.remove(i);
1093        }
1094        delivered
1095    }
1096
1097    fn subscriber_count(&self, topic: &str) -> usize {
1098        let subs = self.subscribers.lock().expect("sub lock poisoned");
1099        subs.get(topic).map(|l| l.len()).unwrap_or(0)
1100    }
1101
1102    fn topic_count(&self) -> usize {
1103        let subs = self.subscribers.lock().expect("sub lock poisoned");
1104        subs.len()
1105    }
1106}
1107
1108/// 订阅代理
1109///
1110/// 基于内存 pub/sub 模式实现的事件分发
1111pub struct SubscriptionBroker {
1112    inner: Arc<SubscriptionBrokerInner>,
1113}
1114
1115impl SubscriptionBroker {
1116    pub fn new() -> Self {
1117        Self {
1118            inner: Arc::new(SubscriptionBrokerInner::new()),
1119        }
1120    }
1121
1122    /// 订阅主题
1123    ///
1124    /// 返回订阅句柄,drop 时自动取消订阅
1125    pub fn subscribe(&self, topic: &str) -> SubscriptionHandle {
1126        let (id, rx) = self.inner.subscribe(topic);
1127        SubscriptionHandle {
1128            id,
1129            topic: topic.to_string(),
1130            receiver: rx,
1131            broker: Some(self.inner.clone()),
1132        }
1133    }
1134
1135    /// 发布事件到指定主题
1136    ///
1137    /// 返回实际投递到的订阅者数量
1138    pub fn publish(&self, topic: &str, payload: Value) -> usize {
1139        self.inner.publish(topic, payload)
1140    }
1141
1142    /// 获取指定主题的订阅者数量
1143    pub fn subscriber_count(&self, topic: &str) -> usize {
1144        self.inner.subscriber_count(topic)
1145    }
1146
1147    /// 获取活跃主题数量
1148    pub fn topic_count(&self) -> usize {
1149        self.inner.topic_count()
1150    }
1151}
1152
1153impl Default for SubscriptionBroker {
1154    fn default() -> Self {
1155        Self::new()
1156    }
1157}
1158
1159impl Clone for SubscriptionBroker {
1160    fn clone(&self) -> Self {
1161        Self {
1162            inner: self.inner.clone(),
1163        }
1164    }
1165}
1166
1167// =============================================================================
1168// 五、Schema 扩展:在既有 schema 上注册关联/分页/变更/订阅
1169// =============================================================================
1170
1171/// Schema 扩展配置
1172///
1173/// 将关联关系、分页类型、变更、订阅等扩展信息附加到既有 schema
1174pub struct SchemaExtensions {
1175    /// 关联关系列表
1176    pub relations: Vec<Relation>,
1177    /// 变更定义列表(类型名 + 操作类型)
1178    pub mutations: Vec<(String, MutationKind)>,
1179    /// 订阅主题列表
1180    pub subscriptions: Vec<String>,
1181}
1182
1183impl SchemaExtensions {
1184    pub fn new() -> Self {
1185        Self {
1186            relations: Vec::new(),
1187            mutations: Vec::new(),
1188            subscriptions: Vec::new(),
1189        }
1190    }
1191
1192    /// 添加关联关系
1193    pub fn with_relation(mut self, relation: Relation) -> Self {
1194        self.relations.push(relation);
1195        self
1196    }
1197
1198    /// 添加变更定义
1199    pub fn with_mutation(mut self, type_name: impl Into<String>, kind: MutationKind) -> Self {
1200        self.mutations.push((type_name.into(), kind));
1201        self
1202    }
1203
1204    /// 添加订阅主题
1205    pub fn with_subscription(mut self, topic: impl Into<String>) -> Self {
1206        self.subscriptions.push(topic.into());
1207        self
1208    }
1209
1210    /// 将扩展信息渲染为 SDL 片段
1211    pub fn to_sdl(&self) -> String {
1212        let mut out = String::new();
1213
1214        // 渲染关联类型(在对应 type 上添加嵌套字段)
1215        if !self.relations.is_empty() {
1216            out.push_str("# Relations\n");
1217            for rel in &self.relations {
1218                out.push_str(&format!(
1219                    "# {} {}.{} -> {} ({:?})\n",
1220                    rel.name, rel.from_type, rel.from_field, rel.to_type, rel.kind
1221                ));
1222            }
1223            out.push('\n');
1224        }
1225
1226        // 渲染变更
1227        if !self.mutations.is_empty() {
1228            out.push_str("type Mutation {\n");
1229            for (type_name, kind) in &self.mutations {
1230                let op = match kind {
1231                    MutationKind::Create => {
1232                        format!("create{type_name}(input: {type_name}Input!): {type_name}")
1233                    }
1234                    MutationKind::Update => {
1235                        format!("update{type_name}(id: ID!, input: {type_name}Input!): {type_name}")
1236                    }
1237                    MutationKind::Delete => format!("delete{type_name}(id: ID!): Boolean!"),
1238                };
1239                out.push_str(&format!("    {}\n", op));
1240            }
1241            out.push_str("}\n\n");
1242        }
1243
1244        // 渲染订阅
1245        if !self.subscriptions.is_empty() {
1246            out.push_str("type Subscription {\n");
1247            for topic in &self.subscriptions {
1248                out.push_str(&format!("    {}: SubscriptionEvent!\n", topic));
1249            }
1250            out.push_str("}\n\n");
1251            out.push_str("type SubscriptionEvent {\n");
1252            out.push_str("    topic: String!\n");
1253            out.push_str("    payload: JSON!\n");
1254            out.push_str("    sequence: Int!\n");
1255            out.push_str("}\n");
1256        }
1257
1258        out
1259    }
1260}
1261
1262impl Default for SchemaExtensions {
1263    fn default() -> Self {
1264        Self::new()
1265    }
1266}
1267
1268#[cfg(test)]
1269mod tests {
1270    use super::*;
1271    use serde_json::json;
1272
1273    // --- 关联关系测试 ---
1274
1275    #[test]
1276    fn test_relation_new() {
1277        let rel = Relation::new(
1278            "userOrders",
1279            "User",
1280            "id",
1281            "Order",
1282            "user_id",
1283            RelationKind::OneToMany,
1284        );
1285        assert_eq!(rel.name, "userOrders");
1286        assert_eq!(rel.from_type, "User");
1287        assert_eq!(rel.from_field, "id");
1288        assert_eq!(rel.to_type, "Order");
1289        assert_eq!(rel.to_field, "user_id");
1290        assert_eq!(rel.kind, RelationKind::OneToMany);
1291    }
1292
1293    #[test]
1294    fn test_relation_one_to_many() {
1295        let rel = Relation::one_to_many("userOrders", "User", "Order");
1296        assert_eq!(rel.kind, RelationKind::OneToMany);
1297        assert_eq!(rel.from_type, "User");
1298        assert_eq!(rel.to_type, "Order");
1299        assert_eq!(rel.from_field, "id");
1300        assert_eq!(rel.to_field, "user_id");
1301    }
1302
1303    #[test]
1304    fn test_relation_many_to_one() {
1305        let rel = Relation::many_to_one("orderUser", "Order", "User");
1306        assert_eq!(rel.kind, RelationKind::ManyToOne);
1307        assert_eq!(rel.from_type, "Order");
1308        assert_eq!(rel.to_type, "User");
1309        assert_eq!(rel.from_field, "user_id");
1310        assert_eq!(rel.to_field, "id");
1311    }
1312
1313    #[test]
1314    fn test_relation_kind_serde() {
1315        let kind = RelationKind::ManyToMany;
1316        let json = serde_json::to_string(&kind).unwrap();
1317        let de: RelationKind = serde_json::from_str(&json).unwrap();
1318        assert_eq!(de, kind);
1319    }
1320
1321    // --- 解析器注册表测试 ---
1322
1323    #[test]
1324    fn test_resolver_registry_register_and_get() {
1325        let registry = ResolverRegistry::new();
1326        registry.register(
1327            "User",
1328            "orders",
1329            Box::new(|parent, _args| {
1330                let id = parent["id"].as_str().unwrap_or("");
1331                json!([{"id": "1", "user_id": id, "name": "order1"}])
1332            }),
1333        );
1334        assert_eq!(registry.len(), 1);
1335
1336        let parent = json!({"id": "u1"});
1337        let args = HashMap::new();
1338        let result = registry.resolve("User", "orders", &parent, &args);
1339        assert!(result.is_some());
1340        let result = result.unwrap();
1341        assert!(result.is_array());
1342        assert_eq!(result[0]["user_id"], "u1");
1343    }
1344
1345    #[test]
1346    fn test_resolver_registry_get_missing() {
1347        let registry = ResolverRegistry::new();
1348        assert!(registry.get("Unknown", "field").is_none());
1349        assert!(registry.is_empty());
1350    }
1351
1352    #[test]
1353    fn test_resolver_registry_multiple() {
1354        let registry = ResolverRegistry::new();
1355        registry.register("User", "orders", Box::new(|_, _| json!([{"id": "1"}])));
1356        registry.register("Order", "user", Box::new(|_, _| json!({"id": "u1"})));
1357        assert_eq!(registry.len(), 2);
1358
1359        let parent = json!({});
1360        let args = HashMap::new();
1361        assert!(registry.resolve("User", "orders", &parent, &args).is_some());
1362        assert!(registry.resolve("Order", "user", &parent, &args).is_some());
1363        assert!(registry.resolve("User", "user", &parent, &args).is_none());
1364    }
1365
1366    // --- 关联数据源测试 ---
1367
1368    #[test]
1369    fn test_data_source_insert_and_get() {
1370        let ds = RelationDataSource::new();
1371        ds.insert("User", json!({"id": "1", "name": "Alice"}));
1372        ds.insert("User", json!({"id": "2", "name": "Bob"}));
1373
1374        let users = ds.get_all("User");
1375        assert_eq!(users.len(), 2);
1376    }
1377
1378    #[test]
1379    fn test_data_source_find_by_id() {
1380        let ds = RelationDataSource::new();
1381        ds.insert("User", json!({"id": "1", "name": "Alice"}));
1382        ds.insert("User", json!({"id": "2", "name": "Bob"}));
1383
1384        let user = ds.find_by_id("User", "2").unwrap();
1385        assert_eq!(user["name"], "Bob");
1386        assert!(ds.find_by_id("User", "999").is_none());
1387    }
1388
1389    #[test]
1390    fn test_data_source_resolve_one_to_many() {
1391        let ds = RelationDataSource::new();
1392        ds.insert("User", json!({"id": "u1", "name": "Alice"}));
1393        ds.insert_many(
1394            "Order",
1395            vec![
1396                json!({"id": "o1", "user_id": "u1", "total": 100}),
1397                json!({"id": "o2", "user_id": "u1", "total": 200}),
1398                json!({"id": "o3", "user_id": "u2", "total": 300}),
1399            ],
1400        );
1401
1402        let orders = ds.resolve_one_to_many("Order", "user_id", "u1");
1403        assert_eq!(orders.len(), 2);
1404        assert_eq!(orders[0]["id"], "o1");
1405        assert_eq!(orders[1]["id"], "o2");
1406    }
1407
1408    #[test]
1409    fn test_data_source_resolve_many_to_one() {
1410        let ds = RelationDataSource::new();
1411        ds.insert("User", json!({"id": "u1", "name": "Alice"}));
1412        ds.insert("User", json!({"id": "u2", "name": "Bob"}));
1413        ds.insert("Order", json!({"id": "o1", "user_id": "u1", "total": 100}));
1414
1415        let user = ds.resolve_many_to_one("User", "id", "u1").unwrap();
1416        assert_eq!(user["name"], "Alice");
1417
1418        let user2 = ds.resolve_many_to_one("User", "id", "u2").unwrap();
1419        assert_eq!(user2["name"], "Bob");
1420
1421        assert!(ds.resolve_many_to_one("User", "id", "u999").is_none());
1422    }
1423
1424    #[test]
1425    fn test_data_source_empty_type() {
1426        let ds = RelationDataSource::new();
1427        assert!(ds.get_all("Nonexistent").is_empty());
1428        assert!(ds.find_by_id("Nonexistent", "1").is_none());
1429        assert!(ds.resolve_one_to_many("Nonexistent", "fk", "1").is_empty());
1430        assert!(ds.resolve_many_to_one("Nonexistent", "id", "1").is_none());
1431    }
1432
1433    // --- 分页测试 ---
1434
1435    #[test]
1436    fn test_page_info_new() {
1437        let pi = PageInfo::new();
1438        assert!(!pi.has_next_page);
1439        assert!(!pi.has_previous_page);
1440        assert!(pi.start_cursor.is_none());
1441        assert!(pi.end_cursor.is_none());
1442    }
1443
1444    #[test]
1445    fn test_page_info_builder() {
1446        let pi = PageInfo::new().with_next(true).with_previous(false);
1447        assert!(pi.has_next_page);
1448        assert!(!pi.has_previous_page);
1449    }
1450
1451    #[test]
1452    fn test_edge_from_index() {
1453        let edge = Edge::from_index(5, json!({"id": "5"}));
1454        assert!(!edge.cursor.is_empty());
1455        assert_eq!(edge.node["id"], "5");
1456    }
1457
1458    #[test]
1459    fn test_connection_empty() {
1460        let conn = Connection::empty();
1461        assert!(conn.edges.is_empty());
1462        assert_eq!(conn.total_count, 0);
1463        assert!(conn.nodes().is_empty());
1464    }
1465
1466    #[test]
1467    fn test_cursor_encode_decode_roundtrip() {
1468        for i in [0, 1, 5, 10, 100, 999, 1000] {
1469            let cursor = encode_cursor(i);
1470            let decoded = decode_cursor(&cursor);
1471            assert_eq!(decoded, Some(i), "roundtrip failed for index {}", i);
1472        }
1473    }
1474
1475    #[test]
1476    fn test_decode_invalid_cursor() {
1477        assert!(decode_cursor("!!!invalid!!!").is_none());
1478        assert!(decode_cursor("").is_none());
1479    }
1480
1481    #[test]
1482    fn test_paginate_no_args_returns_all() {
1483        let nodes = vec![json!({"id": "1"}), json!({"id": "2"}), json!({"id": "3"})];
1484        let conn = paginate(nodes, &PaginationArgs::new());
1485        assert_eq!(conn.edges.len(), 3);
1486        assert_eq!(conn.total_count, 3);
1487        assert!(!conn.page_info.has_next_page);
1488        assert!(!conn.page_info.has_previous_page);
1489    }
1490
1491    #[test]
1492    fn test_paginate_first_n() {
1493        let nodes: Vec<Value> = (1..=10).map(|i| json!({"id": i.to_string()})).collect();
1494        let args = PaginationArgs::new().with_first(3);
1495        let conn = paginate(nodes, &args);
1496        assert_eq!(conn.edges.len(), 3);
1497        assert_eq!(conn.total_count, 10);
1498        assert!(conn.page_info.has_next_page);
1499        assert!(!conn.page_info.has_previous_page);
1500    }
1501
1502    #[test]
1503    fn test_paginate_first_after() {
1504        let nodes: Vec<Value> = (1..=10).map(|i| json!({"id": i.to_string()})).collect();
1505        // 第一页取 3 条
1506        let args1 = PaginationArgs::new().with_first(3);
1507        let conn1 = paginate(nodes.clone(), &args1);
1508        let after_cursor = conn1.page_info.end_cursor.unwrap();
1509
1510        // 第二页从第一页最后一条之后开始
1511        let args2 = PaginationArgs::new().with_first(3).with_after(after_cursor);
1512        let conn2 = paginate(nodes, &args2);
1513        assert_eq!(conn2.edges.len(), 3);
1514        assert_eq!(conn2.edges[0].node["id"], "4");
1515        assert_eq!(conn2.edges[2].node["id"], "6");
1516        assert!(conn2.page_info.has_next_page);
1517        assert!(conn2.page_info.has_previous_page);
1518    }
1519
1520    #[test]
1521    fn test_paginate_first_beyond_end() {
1522        let nodes = vec![json!({"id": "1"}), json!({"id": "2"})];
1523        let args = PaginationArgs::new().with_first(10);
1524        let conn = paginate(nodes, &args);
1525        assert_eq!(conn.edges.len(), 2);
1526        assert_eq!(conn.total_count, 2);
1527        assert!(!conn.page_info.has_next_page);
1528    }
1529
1530    #[test]
1531    fn test_paginate_last_n() {
1532        let nodes: Vec<Value> = (1..=10).map(|i| json!({"id": i.to_string()})).collect();
1533        let args = PaginationArgs::new().with_last(3);
1534        let conn = paginate(nodes, &args);
1535        assert_eq!(conn.edges.len(), 3);
1536        assert_eq!(conn.edges[0].node["id"], "8");
1537        assert_eq!(conn.edges[2].node["id"], "10");
1538        assert!(!conn.page_info.has_next_page);
1539        assert!(conn.page_info.has_previous_page);
1540    }
1541
1542    #[test]
1543    fn test_paginate_empty_list() {
1544        let conn = paginate(Vec::new(), &PaginationArgs::new().with_first(5));
1545        assert_eq!(conn.edges.len(), 0);
1546        assert_eq!(conn.total_count, 0);
1547    }
1548
1549    #[test]
1550    fn test_paginate_after_beyond_end() {
1551        let nodes = vec![json!({"id": "1"}), json!({"id": "2"})];
1552        // 使用一个超出范围的游标
1553        let cursor = encode_cursor(100);
1554        let args = PaginationArgs::new().with_first(5).with_after(cursor);
1555        let conn = paginate(nodes, &args);
1556        assert_eq!(conn.edges.len(), 0);
1557    }
1558
1559    #[test]
1560    fn test_connection_nodes() {
1561        let edges = vec![
1562            Edge::from_index(0, json!({"id": "1"})),
1563            Edge::from_index(1, json!({"id": "2"})),
1564        ];
1565        let conn = Connection::new(edges, PageInfo::new(), 2);
1566        let nodes = conn.nodes();
1567        assert_eq!(nodes.len(), 2);
1568        assert_eq!(nodes[0]["id"], "1");
1569    }
1570
1571    // --- 变更输入测试 ---
1572
1573    #[test]
1574    fn test_mutation_input_create() {
1575        let input = MutationInput::create("User", json!({"name": "Alice"}));
1576        assert_eq!(input.kind, MutationKind::Create);
1577        assert_eq!(input.type_name, "User");
1578        assert!(input.id.is_none());
1579        assert!(input.data.is_some());
1580    }
1581
1582    #[test]
1583    fn test_mutation_input_update() {
1584        let input = MutationInput::update("User", "1", json!({"name": "Bob"}));
1585        assert_eq!(input.kind, MutationKind::Update);
1586        assert_eq!(input.type_name, "User");
1587        assert_eq!(input.id, Some("1".to_string()));
1588    }
1589
1590    #[test]
1591    fn test_mutation_input_delete() {
1592        let input = MutationInput::delete("User", "1");
1593        assert_eq!(input.kind, MutationKind::Delete);
1594        assert!(input.data.is_none());
1595    }
1596
1597    #[test]
1598    fn test_mutation_result_ok() {
1599        let result = MutationResult::ok(Some(json!({"id": "1"})));
1600        assert!(result.success);
1601        assert_eq!(result.affected, 1);
1602        assert!(result.error.is_none());
1603    }
1604
1605    #[test]
1606    fn test_mutation_result_err() {
1607        let result = MutationResult::err("not found");
1608        assert!(!result.success);
1609        assert_eq!(result.affected, 0);
1610        assert_eq!(result.error, Some("not found".to_string()));
1611    }
1612
1613    // --- 变更注册表测试 ---
1614
1615    #[test]
1616    fn test_mutation_registry_execute() {
1617        let registry = MutationRegistry::new();
1618        registry.register(
1619            "User",
1620            MutationKind::Create,
1621            Box::new(|input| MutationResult::ok(input.data.clone())),
1622        );
1623        let input = MutationInput::create("User", json!({"name": "Alice"}));
1624        let result = registry.execute(&input);
1625        assert!(result.success);
1626        assert_eq!(result.data.unwrap()["name"], "Alice");
1627    }
1628
1629    #[test]
1630    fn test_mutation_registry_no_handler() {
1631        let registry = MutationRegistry::new();
1632        let input = MutationInput::create("Unknown", json!({}));
1633        let result = registry.execute(&input);
1634        assert!(!result.success);
1635        assert!(result.error.unwrap().contains("no mutation handler"));
1636    }
1637
1638    #[test]
1639    fn test_mutation_registry_multiple() {
1640        let registry = MutationRegistry::new();
1641        registry.register(
1642            "User",
1643            MutationKind::Create,
1644            Box::new(|_| MutationResult::ok(None)),
1645        );
1646        registry.register(
1647            "User",
1648            MutationKind::Delete,
1649            Box::new(|_| MutationResult::ok_many(1, None)),
1650        );
1651        assert_eq!(registry.len(), 2);
1652
1653        let create_result = registry.execute(&MutationInput::create("User", json!({})));
1654        assert!(create_result.success);
1655
1656        let delete_result = registry.execute(&MutationInput::delete("User", "1"));
1657        assert!(delete_result.success);
1658    }
1659
1660    // --- 内存存储测试 ---
1661
1662    #[test]
1663    fn test_in_memory_store_create() {
1664        let store = InMemoryStore::new();
1665        let result = store.create("User", json!({"name": "Alice"}));
1666        assert!(result.success);
1667        let data = result.data.unwrap();
1668        assert_eq!(data["name"], "Alice");
1669        assert!(data["id"].is_string());
1670        // 验证记录已存储
1671        let all = store.get_all("User");
1672        assert_eq!(all.len(), 1);
1673    }
1674
1675    #[test]
1676    fn test_in_memory_store_create_multiple() {
1677        let store = InMemoryStore::new();
1678        store.create("User", json!({"name": "Alice"}));
1679        store.create("User", json!({"name": "Bob"}));
1680        let all = store.get_all("User");
1681        assert_eq!(all.len(), 2);
1682        // ID 应递增
1683        assert_eq!(all[0]["id"], "1");
1684        assert_eq!(all[1]["id"], "2");
1685    }
1686
1687    #[test]
1688    fn test_in_memory_store_update() {
1689        let store = InMemoryStore::new();
1690        store.create("User", json!({"name": "Alice"}));
1691        let result = store.update("User", "1", &json!({"name": "Alicia"}));
1692        assert!(result.success);
1693        let updated = store.find_by_id("User", "1").unwrap();
1694        assert_eq!(updated["name"], "Alicia");
1695    }
1696
1697    #[test]
1698    fn test_in_memory_store_update_missing() {
1699        let store = InMemoryStore::new();
1700        let result = store.update("User", "999", &json!({"name": "X"}));
1701        assert!(!result.success);
1702        assert!(result.error.unwrap().contains("not found"));
1703    }
1704
1705    #[test]
1706    fn test_in_memory_store_delete() {
1707        let store = InMemoryStore::new();
1708        store.create("User", json!({"name": "Alice"}));
1709        let result = store.delete("User", "1");
1710        assert!(result.success);
1711        assert_eq!(result.affected, 1);
1712        assert!(store.find_by_id("User", "1").is_none());
1713    }
1714
1715    #[test]
1716    fn test_in_memory_store_delete_missing() {
1717        let store = InMemoryStore::new();
1718        let result = store.delete("User", "999");
1719        assert!(!result.success);
1720    }
1721
1722    #[test]
1723    fn test_in_memory_store_find_by_id_missing_type() {
1724        let store = InMemoryStore::new();
1725        assert!(store.find_by_id("Nonexistent", "1").is_none());
1726    }
1727
1728    // --- 订阅代理测试 ---
1729
1730    #[test]
1731    fn test_subscription_broker_subscribe_and_publish() {
1732        let broker = SubscriptionBroker::new();
1733        let handle = broker.subscribe("userCreated");
1734
1735        assert_eq!(broker.subscriber_count("userCreated"), 1);
1736        let delivered = broker.publish("userCreated", json!({"id": "1", "name": "Alice"}));
1737        assert_eq!(delivered, 1);
1738
1739        let event = handle.try_recv();
1740        assert!(event.is_some());
1741        let event = event.unwrap();
1742        assert_eq!(event.topic, "userCreated");
1743        assert_eq!(event.payload["name"], "Alice");
1744        assert!(event.sequence > 0);
1745    }
1746
1747    #[test]
1748    fn test_subscription_broker_multiple_subscribers() {
1749        let broker = SubscriptionBroker::new();
1750        let handle1 = broker.subscribe("topic1");
1751        let handle2 = broker.subscribe("topic1");
1752
1753        assert_eq!(broker.subscriber_count("topic1"), 2);
1754        let delivered = broker.publish("topic1", json!({"msg": "hello"}));
1755        assert_eq!(delivered, 2);
1756
1757        assert!(handle1.try_recv().is_some());
1758        assert!(handle2.try_recv().is_some());
1759    }
1760
1761    #[test]
1762    fn test_subscription_broker_no_subscribers() {
1763        let broker = SubscriptionBroker::new();
1764        let delivered = broker.publish("noSubs", json!({"msg": "hello"}));
1765        assert_eq!(delivered, 0);
1766    }
1767
1768    #[test]
1769    fn test_subscription_broker_unsubscribe_on_drop() {
1770        let broker = SubscriptionBroker::new();
1771        {
1772            let _handle = broker.subscribe("tempTopic");
1773            assert_eq!(broker.subscriber_count("tempTopic"), 1);
1774        } // handle dropped here
1775          // Give a moment for drop to propagate
1776        assert_eq!(broker.subscriber_count("tempTopic"), 0);
1777    }
1778
1779    #[test]
1780    fn test_subscription_broker_different_topics() {
1781        let broker = SubscriptionBroker::new();
1782        let handle1 = broker.subscribe("topicA");
1783        let handle2 = broker.subscribe("topicB");
1784
1785        broker.publish("topicA", json!({"a": 1}));
1786        broker.publish("topicB", json!({"b": 2}));
1787
1788        let event1 = handle1.try_recv().unwrap();
1789        assert_eq!(event1.payload["a"], 1);
1790
1791        let event2 = handle2.try_recv().unwrap();
1792        assert_eq!(event2.payload["b"], 2);
1793
1794        // 各自只收到各自主题的事件
1795        assert!(handle1.try_recv().is_none());
1796        assert!(handle2.try_recv().is_none());
1797    }
1798
1799    #[test]
1800    fn test_subscription_broker_sequence_increments() {
1801        let broker = SubscriptionBroker::new();
1802        let handle = broker.subscribe("seq");
1803
1804        broker.publish("seq", json!({}));
1805        broker.publish("seq", json!({}));
1806        broker.publish("seq", json!({}));
1807
1808        let e1 = handle.try_recv().unwrap();
1809        let e2 = handle.try_recv().unwrap();
1810        let e3 = handle.try_recv().unwrap();
1811
1812        assert!(e2.sequence > e1.sequence);
1813        assert!(e3.sequence > e2.sequence);
1814    }
1815
1816    #[test]
1817    fn test_subscription_broker_clone_shares_state() {
1818        let broker = SubscriptionBroker::new();
1819        let broker2 = broker.clone();
1820        let handle = broker2.subscribe("shared");
1821
1822        broker.publish("shared", json!({"x": 1}));
1823        assert!(handle.try_recv().is_some());
1824    }
1825
1826    #[test]
1827    fn test_subscription_handle_recv_blocking() {
1828        let broker = SubscriptionBroker::new();
1829        let handle = broker.subscribe("block");
1830
1831        // 在另一个线程中发布事件
1832        let b = broker.clone();
1833        let thread = std::thread::spawn(move || {
1834            std::thread::sleep(std::time::Duration::from_millis(10));
1835            b.publish("block", json!({"delayed": true}));
1836        });
1837
1838        let event = handle.recv();
1839        assert!(event.is_some());
1840        assert_eq!(event.unwrap().payload["delayed"], true);
1841        thread.join().unwrap();
1842    }
1843
1844    #[test]
1845    fn test_subscription_broker_topic_count() {
1846        let broker = SubscriptionBroker::new();
1847        let _h1 = broker.subscribe("t1");
1848        let _h2 = broker.subscribe("t2");
1849        let _h3 = broker.subscribe("t3");
1850        assert_eq!(broker.topic_count(), 3);
1851    }
1852
1853    // --- Schema 扩展测试 ---
1854
1855    #[test]
1856    fn test_schema_extensions_new() {
1857        let ext = SchemaExtensions::new();
1858        assert!(ext.relations.is_empty());
1859        assert!(ext.mutations.is_empty());
1860        assert!(ext.subscriptions.is_empty());
1861    }
1862
1863    #[test]
1864    fn test_schema_extensions_builder() {
1865        let ext = SchemaExtensions::new()
1866            .with_relation(Relation::one_to_many("userOrders", "User", "Order"))
1867            .with_mutation("User", MutationKind::Create)
1868            .with_mutation("User", MutationKind::Delete)
1869            .with_subscription("userCreated");
1870
1871        assert_eq!(ext.relations.len(), 1);
1872        assert_eq!(ext.mutations.len(), 2);
1873        assert_eq!(ext.subscriptions.len(), 1);
1874    }
1875
1876    #[test]
1877    fn test_schema_extensions_to_sdl_contains_mutation() {
1878        let ext = SchemaExtensions::new()
1879            .with_mutation("User", MutationKind::Create)
1880            .with_mutation("User", MutationKind::Delete);
1881
1882        let sdl = ext.to_sdl();
1883        assert!(sdl.contains("type Mutation {"));
1884        assert!(sdl.contains("createUser"));
1885        assert!(sdl.contains("deleteUser"));
1886    }
1887
1888    #[test]
1889    fn test_schema_extensions_to_sdl_contains_subscription() {
1890        let ext = SchemaExtensions::new().with_subscription("userCreated");
1891        let sdl = ext.to_sdl();
1892        assert!(sdl.contains("type Subscription {"));
1893        assert!(sdl.contains("userCreated"));
1894        assert!(sdl.contains("SubscriptionEvent"));
1895    }
1896
1897    #[test]
1898    fn test_schema_extensions_to_sdl_contains_relation() {
1899        let ext = SchemaExtensions::new().with_relation(Relation::one_to_many(
1900            "userOrders",
1901            "User",
1902            "Order",
1903        ));
1904        let sdl = ext.to_sdl();
1905        assert!(sdl.contains("# Relations"));
1906        assert!(sdl.contains("userOrders"));
1907    }
1908
1909    #[test]
1910    fn test_schema_extensions_to_sdl_empty() {
1911        let ext = SchemaExtensions::new();
1912        let sdl = ext.to_sdl();
1913        assert!(sdl.is_empty());
1914    }
1915}