Back to list
Rytass

cms-modules

by Rytass

7🍴 2📅 Jan 19, 2026

SKILL.md


name: cms-modules description: | CMS NestJS module integration (內容管理系統 NestJS 模組). Use when working with article management (文章管理), category systems (分類系統), approval workflows (審核流程), multi-language content (多語言內容), or GraphQL CMS integration. Covers DataLoader patterns, TypeORM integration, and permission control. Keywords: CMS, 內容管理, 文章管理, 分類, 審核, GraphQL, NestJS, DataLoader, TypeORM, 多語言

CMS NestJS Modules (內容管理系統模組)

Overview

@rytass/cms-base-nestjs-module 系列提供完整的 NestJS CMS 解決方案,支援文章管理、分類系統、審核流程和多語言內容。

套件清單

套件說明
@rytass/cms-base-nestjs-module核心 CMS 模組(服務層、實體、DataLoader)
@rytass/cms-base-nestjs-graphql-moduleGraphQL 整合層(Resolvers、Queries、Mutations)

Quick Start

安裝

# 核心模組
npm install @rytass/cms-base-nestjs-module

# GraphQL 整合(可選)
npm install @rytass/cms-base-nestjs-graphql-module

基本設定

import { CMSBaseModule } from '@rytass/cms-base-nestjs-module';

@Module({
  imports: [
    TypeOrmModule.forRoot({ /* 資料庫配置 */ }),
    CMSBaseModule.forRoot({
      multipleLanguageMode: true,
      enableDraftMode: true,
      signatureLevels: ['編輯', '主編'],
    }),
  ],
})
export class AppModule {}

GraphQL 整合

import { CMSBaseGraphQLModule } from '@rytass/cms-base-nestjs-graphql-module';

@Module({
  imports: [
    GraphQLModule.forRoot({ /* Apollo 配置 */ }),
    CMSBaseGraphQLModule.forRoot({
      multipleLanguageMode: true,
      enableDraftMode: true,
      signatureLevels: ['編輯', '主編'],
    }),
  ],
})
export class AppModule {}

Core Concepts

文章生命週期 (Article Stages)

DRAFT → REVIEWING → VERIFIED → SCHEDULED/RELEASED
                  ↓
               DELETED
階段說明觸發操作
DRAFT草稿建立/退回
REVIEWING審核中submit()
VERIFIED已核准approve()
SCHEDULED預約發布release(futureDate)
RELEASED已發布release()
DELETED已刪除archive()
UNKNOWN未知狀態例外狀態

Symbol-Based 注入

import {
  RESOLVED_ARTICLE_REPO,
  ArticleBaseService,
} from '@rytass/cms-base-nestjs-module';

@Injectable()
export class ArticleResolver {
  constructor(
    @Inject(RESOLVED_ARTICLE_REPO)
    private readonly articleRepo: Repository<BaseArticleEntity>,

    // ArticleBaseService 直接使用類別注入
    private readonly articleService: ArticleBaseService,
  ) {}
}

DataLoader 模式

防止 N+1 查詢問題:

import { ArticleDataLoader } from '@rytass/cms-base-nestjs-module';

@Injectable()
export class ArticleResolver {
  constructor(private readonly articleDataLoader: ArticleDataLoader) {}

  @ResolveField()
  async categories(@Parent() article: Article) {
    return this.articleDataLoader.categoriesLoader.load(article.id);
  }
}

可用的 DataLoaders:

DataLoader提供的 Loaders
ArticleDataLoaderstageLoader, categoriesLoader
ArticleVersionDataLoaderstageVersionsLoader, versionsLoader
ArticleSignatureDataLoaderversionSignaturesLoader
CategoryDataLoaderwithParentsLoader

Common Patterns

自訂實體擴展

import { BaseArticleEntity } from '@rytass/cms-base-nestjs-module';

@Entity('articles')
@ChildEntity()
export class CustomArticle extends BaseArticleEntity {
  @Column({ nullable: true })
  featuredImage?: string;

  @Column({ type: 'jsonb', nullable: true })
  seoMetadata?: Record<string, any>;
}

// 模組配置
CMSBaseModule.forRoot({
  articleEntity: CustomArticle,
  articleVersionEntity: CustomArticleVersion,       // 可選
  articleVersionContentEntity: CustomContent,       // 可選
  categoryEntity: CustomCategory,                   // 可選
})

文章版本管理

// 新增版本
await articleService.addVersion(articleId, {
  title: '更新標題',
  content: [...],
  categoryIds: ['cat-1'],
  userId: 'user-1',
  submitted: true,  // 直接提交審核
});

// 刪除特定版本
await articleService.deleteVersion(articleId, 2);

// 封存文章(軟刪除)
await articleService.archive(articleId);

多語言內容

// 建立多語言文章
await articleService.create({
  multiLanguageContents: {
    'zh-TW': { title: '標題', content: '內容' },
    'en-US': { title: 'Title', content: 'Content' },
  },
  categoryIds: ['cat-1'],
});

審核流程

// 1. 提交審核
await articleService.submit(articleId, { userId: 'user-1' });

// 2. 核准
await articleService.approveVersion(
  { id: articleId, version: 1 },
  { signatureLevel: '主編', signerId: 'user-1' },
);

// 3. 發布
await articleService.release(articleId, {
  releasedAt: new Date(),
  version: 1,  // 可選,指定版本
  userId: 'user-1',
});

// 4. 退回(重新編輯)
await articleService.putBack(articleId);

// 5. 拒絕審核
await articleService.rejectVersion(
  { id: articleId },
  { signatureLevel: '主編', signerId: 'user-1', reason: '內容不完整' },
);

// 6. 撤回已發布文章
await articleService.withdraw(articleId, 1);  // id, version

GraphQL 查詢範例

# 公開文章列表
query Articles($page: Int, $limit: Int) {
  articles(page: $page, limit: $limit) {
    items {
      articleId
      title
      categories { id, name }
      releasedBy { username }
    }
    meta { totalCount, hasNextPage }
  }
}

# 後台文章(含所有階段)
query BackstageArticles($stage: ArticleStage) {
  backstageArticles(stage: $stage) {
    items {
      articleId
      stage
      signatures { approved, level }
    }
  }
}

權限控制整合

注意: BaseResourceBaseAction 枚舉定義在 @rytass/cms-base-nestjs-graphql-modulesrc/constants/enum/ 目錄下,但目前未從 index.ts 導出。如需使用,請直接引用字串或在專案中自行定義。

import { AllowActions } from '@rytass/member-base-nestjs-module';

@Mutation()
@AllowActions([['article', 'create']])  // 使用字串代替枚舉
async createArticle() { }

Module Options

選項預設說明
multipleLanguageModefalse啟用多語言內容
allowMultipleParentCategoriesfalse分類允許多個父分類
allowCircularCategoriesfalse分類允許循環參照
fullTextSearchModefalse啟用全文搜尋
enableDraftModefalse啟用草稿模式
signatureLevels[]審核層級定義
autoReleaseWhenLatestSignatureApprovedfalse最終核准後自動發布
articleEntityBaseArticleEntity自訂文章實體類別
articleVersionEntityBaseArticleVersionEntity自訂文章版本實體類別
articleVersionContentEntityBaseArticleVersionContentEntity自訂文章內容實體類別
categoryEntityBaseCategoryEntity自訂分類實體類別
categoryMultiLanguageNameEntityBaseCategoryMultiLanguageNameEntity自訂多語言分類名稱實體類別
signatureLevelEntityBaseSignatureLevelEntity自訂審核層級實體類別

Additional Types

Enums

// 文章階段
enum ArticleStage {
  DRAFT = 'DRAFT',
  REVIEWING = 'REVIEWING',
  VERIFIED = 'VERIFIED',
  SCHEDULED = 'SCHEDULED',
  RELEASED = 'RELEASED',
  DELETED = 'DELETED',
  UNKNOWN = 'UNKNOWN',
}

// 文章排序
enum ArticleSorter {
  CREATED_AT_DESC = 'CREATED_AT_DESC',
  CREATED_AT_ASC = 'CREATED_AT_ASC',
  UPDATED_AT_DESC = 'UPDATED_AT_DESC',
  UPDATED_AT_ASC = 'UPDATED_AT_ASC',
  SUBMITTED_AT_DESC = 'SUBMITTED_AT_DESC',
  SUBMITTED_AT_ASC = 'SUBMITTED_AT_ASC',
  RELEASED_AT_DESC = 'RELEASED_AT_DESC',
  RELEASED_AT_ASC = 'RELEASED_AT_ASC',
}

// 文章搜尋模式
enum ArticleSearchMode {
  FULL_TEXT = 'full_text',
  TITLE = 'title',
  TITLE_AND_TAG = 'title-and-tag',
}

// 審核結果
enum ArticleSignatureResult {
  APPROVED = 'APPROVED',
  REJECTED = 'REJECTED',
}

Error Classes

// 基礎錯誤
class MultipleLanguageModeIsDisabledError extends Error {}

// 文章相關錯誤
class ArticleNotFoundError extends Error {}
class ArticleVersionNotFoundError extends Error {}

// 分類相關錯誤
class CategoryNotFoundError extends Error {}
class CircularCategoryNotAllowedError extends Error {}
class MultipleParentCategoryNotAllowedError extends Error {}
class ParentCategoryNotFoundError extends Error {}

Symbol Tokens

Repository Tokens(可用於依賴注入):

  • RESOLVED_ARTICLE_REPO
  • RESOLVED_ARTICLE_VERSION_REPO
  • RESOLVED_ARTICLE_VERSION_CONTENT_REPO
  • RESOLVED_CATEGORY_REPO
  • RESOLVED_CATEGORY_MULTI_LANGUAGE_NAME_REPO
  • RESOLVED_SIGNATURE_LEVEL_REPO

Mode Tokens(模組配置狀態):

  • MULTIPLE_LANGUAGE_MODE
  • DRAFT_MODE
  • MULTIPLE_CATEGORY_PARENT_MODE
  • CIRCULAR_CATEGORY_MODE
  • FULL_TEXT_SEARCH_MODE
  • SIGNATURE_LEVELS
  • AUTO_RELEASE_AFTER_APPROVED

API Reference

詳細 API 文件請參閱 reference.md

Troubleshooting

循環依賴錯誤

使用 Symbol Token 注入而非直接類別注入:

// 正確
@Inject(RESOLVED_ARTICLE_REPO) repo: Repository<Article>

// 避免
constructor(private readonly repo: ArticleRepository)

DataLoader 快取問題

ArticleDataLoader 提供的 loaders:

  • stageLoader - 帶 LRU 快取
  • categoriesLoader - 帶 LRU 快取

如需無快取版本,請在自訂 DataLoader 時設定:

// DataLoader 本身支援 cache: false 選項
const uncachedLoader = new DataLoader(
  (keys) => this.batchLoad(keys),
  { cache: false }
);

多語言模式未啟用

確認模組配置 multipleLanguageMode: true,否則只能存取第一個語言內容。

Score

Total Score

60/100

Based on repository quality metrics

SKILL.md

SKILL.mdファイルが含まれている

+20
LICENSE

ライセンスが設定されている

+10
説明文

100文字以上の説明がある

0/10
人気

GitHub Stars 100以上

0/15
最近の活動

3ヶ月以内に更新がある

0/10
フォーク

10回以上フォークされている

0/5
Issue管理

オープンIssueが50未満

+5
言語

プログラミング言語が設定されている

+5
タグ

1つ以上のタグが設定されている

0/5

Reviews

💬

Reviews coming soon