cms-modules

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

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "cms-modules" with this command: npx skills add rytass/utils/rytass-utils-cms-modules

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

Overview

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

套件清單

套件 說明

@rytass/cms-base-nestjs-module

核心 CMS 模組(服務層、實體、DataLoader)

@rytass/cms-base-nestjs-graphql-module

GraphQL 整合層(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

ArticleDataLoader

stageLoader , categoriesLoader

ArticleVersionDataLoader

stageVersionsLoader , versionsLoader

ArticleSignatureDataLoader

versionSignaturesLoader

CategoryDataLoader

withParentsLoader

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 } } } }

權限控制整合

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

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

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

Module Options

選項 預設 說明

multipleLanguageMode

false 啟用多語言內容

allowMultipleParentCategories

false 分類允許多個父分類

allowCircularCategories

false 分類允許循環參照

fullTextSearchMode

false 啟用全文搜尋

enableDraftMode

false 啟用草稿模式

signatureLevels

[] 審核層級定義

autoReleaseWhenLatestSignatureApproved

false 最終核准後自動發布

articleEntity

BaseArticleEntity 自訂文章實體類別

articleVersionEntity

BaseArticleVersionEntity 自訂文章版本實體類別

articleVersionContentEntity

BaseArticleVersionContentEntity 自訂文章內容實體類別

categoryEntity

BaseCategoryEntity 自訂分類實體類別

categoryMultiLanguageNameEntity

BaseCategoryMultiLanguageNameEntity 自訂多語言分類名稱實體類別

signatureLevelEntity

BaseSignatureLevelEntity 自訂審核層級實體類別

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 ,否則只能存取第一個語言內容。

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

wms-module

No summary provided by upstream source.

Repository SourceNeeds Review
General

quadrats-module

No summary provided by upstream source.

Repository SourceNeeds Review
General

wms-react-components

No summary provided by upstream source.

Repository SourceNeeds Review
General

payment-adapters

No summary provided by upstream source.

Repository SourceNeeds Review