Files
Edu/services/content/src/graphql/resolvers/textbook.resolver.ts
SpecialX d59c4e585f feat(content): graphql subgraph with dataloader for textbook/chapter/kp/question
- GraphQLModule: Apollo Federation 2 at /graphql

- Textbook/Chapter/KnowledgePoint/Question @key with @ResolveReference

- RouterAuthGuard: validate Router-Authorization header (ADR-036)

- batchFind methods added to 4 repositories

- Domain modules export repositories for GraphqlModule injection
2026-07-15 00:18:57 +08:00

85 lines
1.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* content Textbook Resolverv2.1 M1
*
* Apollo Federation 子图Textbook Entity
* - @key(fields: "id") 支持跨子图引用
* - @ResolveReference 使用 DataLoader 批量加载ADR-035
* - Query 入口供 Apollo Router 直接查询
*/
import {
Resolver,
Query,
Args,
ID,
ResolveReference,
ObjectType,
Field,
Directive,
} from "@nestjs/graphql";
import {
DataLoaderService,
type TextbookEntity,
} from "../dataloader.service.js";
/**
* Textbook ObjectTypeFederation @key
* 对应 content_textbooks 表
*/
@ObjectType()
@Directive(`@key(fields: "id")`)
export class Textbook {
@Field(() => ID)
id!: string;
@Field()
title!: string;
@Field()
subjectId!: string;
@Field()
gradeId!: string;
@Field()
version!: string;
@Field()
status!: string;
@Field({ nullable: true })
tenantId: string | null = null;
@Field()
createdAt!: Date;
@Field()
updatedAt!: Date;
}
@Resolver(() => Textbook)
export class TextbookResolver {
constructor(private readonly loader: DataLoaderService) {}
/**
* Federation Reference Resolver
*
* 当其他子图通过 @key 引用 Textbook 时Router 调用此方法解析。
* 使用 DataLoader 批量加载,消除 N+1 查询ADR-035
*/
@ResolveReference()
async resolveReference(ref: { id: string }): Promise<TextbookEntity | null> {
return this.loader.textbookLoader.load(ref.id);
}
/**
* Query: textbook(id) → Textbook
* 通过 Apollo Router 访问,直连被 RouterAuthGuard 拒绝ADR-036
*/
@Query(() => Textbook, { nullable: true })
async textbook(
@Args("id", { type: () => ID }) id: string,
): Promise<TextbookEntity | null> {
return this.loader.textbookLoader.load(id);
}
}