Andersseen/ForgeCMS

GitHub: Andersseen/ForgeCMS

ForgeCMS 是一个基于 TypeScript 的代码优先无头 CMS,专为 Angular 与 Analog.js 打造,可一键部署至 Cloudflare 边缘架构。

Stars: 0 | Forks: 0

ForgeCMS — the code-first, TypeScript-native headless CMS for Angular & Analog.js
**Payload 的 Angular 版本。** 一个代码优先、原生 TypeScript 且运行在边缘的无头 CMS 底座 —— 支持 Cloudflare Pages、D1 和 R2。
[![CI](https://img.shields.io/github/actions/workflow/status/Andersseen/ForgeCMS/ci.yml?branch=main&label=CI&style=flat-square&logo=githubactions&logoColor=white)](https://github.com/Andersseen/ForgeCMS/actions/workflows/ci.yml) [![License: MIT](https://img.shields.io/badge/License-MIT-8B5CF6.svg?style=flat-square)](./LICENSE) [![Status](https://img.shields.io/badge/status-pre--alpha-22D3EE.svg?style=flat-square)](docs/STATE.md) [![PRs welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](CONTRIBUTING.md) ![TypeScript](https://img.shields.io/badge/TypeScript-3178C6?style=for-the-badge&logo=typescript&logoColor=white) ![Angular](https://img.shields.io/badge/Angular-DD0031?style=for-the-badge&logo=angular&logoColor=white) ![Analog.js](https://img.shields.io/badge/Analog.js-FF3E00?style=for-the-badge&logo=vite&logoColor=white) ![Cloudflare](https://img.shields.io/badge/Cloudflare-F38020?style=for-the-badge&logo=cloudflare&logoColor=white) ![pnpm](https://img.shields.io/badge/pnpm-F69220?style=for-the-badge&logo=pnpm&logoColor=white) **[在线演示](https://forge-cms.pages.dev)** · **[快速开始](docs/QUICKSTART.md)** · **[架构](docs/ARCHITECTURE.md)** · **[路线图](docs/ROADMAP.md)** · **[状态](docs/STATE.md)**
## 什么是 ForgeCMS? ForgeCMS 展示了如果从第一天起就以 **Angular 优先** 和 **边缘原生** 的理念来打造一个类似 [Payload](https://payloadcms.com) 风格的无头 CMS,它将会是什么样子。你只需用 TypeScript 描述你的内容模型,就能获得一个带类型的 CRUD runtime、一个后台管理 UI 以及一个 Angular 客户端 SDK —— 所有这些都设计为以一次 Cloudflare Pages 部署的形式运行,并由 D1 (SQLite) 和 R2 (对象存储) 提供底层支持。 无需独立的数据库服务器,无需容器,也没有冷启动的 Node 进程。你的 schema、API 和后台管理界面将一起部署到边缘。 ## ✨ 亮点 | | | | --------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | 🧩 **代码优先的 schema DSL** | 通过 `defineCollection` / `defineField` 定义集合和 15 种字段类型——包括 `relation`、`upload`、`richtext` 以及复合类型 `group` / `array` / `blocks`——并免费获得完整的类型推断。 | | ⚡ **边缘原生 runtime** | 一个 `ForgeCmsRuntime` 编排器运行整个流水线 (访问控制 → hooks → 草稿 → 验证 → relation 填充),**全程零 HTTP 介入** —— 可直接从服务端代码中调用。 | | 🔌 **适配器驱动** | 无需改动业务逻辑即可替换数据库、存储和身份验证。本地使用内存数据库和 LibSQL,生产环境使用 **Cloudflare D1 + R2** —— 所有实现都遵循同一套契约测试套件。 | | 🛡️ **真正的身份验证与访问控制** | 签名 token 身份验证,带有 PBKDF2 哈希加密的用户集合,基于角色的访问控制 (admin / editor / viewer),以及基于函数的行级访问规则。 | | 🅰️ **Angular 客户端与管理后台** | 基于 fetch 的 `CmsApiService`、`provideForgeCms`,以及由 schema 驱动的管理组件 (列表、表单、嵌套复合字段) —— 演示版 `/admin` 使用的是真实的包,而非副本。 | | ☁️ **单一部署目标** | 构建为一个 Cloudflare Pages bundle,能够真实地处理 `/api/*` 请求 (而不仅仅是静态资源),并通过单一的 CI 流水线进行检查和部署。 | ## 📐 Schema DSL 你的内容模型 _就是_ TypeScript。只需定义一次;类型、验证、API 和管理表单都会随之自动生成。 ``` import { defineCollection, defineField } from '@forge-cms/core'; export const posts = defineCollection({ slug: 'posts', drafts: true, // adds published/draft status + visibility rules fields: { title: defineField.text({ label: 'Title', required: true }), slug: defineField.slug({ label: 'Slug', sourceField: 'title', autoGenerate: true }), excerpt: defineField.textarea({ label: 'Excerpt' }), body: defineField.richtext({ label: 'Body' }), cover: defineField.upload({ label: 'Cover image', collection: 'media' }), author: defineField.relation({ label: 'Author', collection: 'users' }), tags: defineField.select({ label: 'Tags', options: ['ng', 'edge', 'cms'] }), publishedAt: defineField.date({ label: 'Published at', withTime: true }) } }); ``` 然后通过 **Local API** 对其进行读写 —— 这是与 HTTP 层使用的相同的流水线,只是去掉了 HTTP 部分: ``` // Trusted server code (an Analog route, a seed script). No fetch, fully typed. const { docs, totalDocs } = await runtime.find({ collection: 'posts', where: { _status: { eq: 'published' } }, sort: 'publishedAt', order: 'desc', depth: 1, // populate the `author` relation with the real record limit: 10 }); await runtime.create({ collection: 'posts', data: { title: 'Hello, edge' } }); ``` …或者通过 HTTP 进行调用,使用一个你的客户端可以信赖的稳定响应结构: ``` GET /api/v1/posts?status=published&sort=publishedAt&order=desc&depth=1 POST /api/v1/posts # validated, auth-protected write ``` ## 🏗️ 架构 严格的单向数据流:客户端和 HTTP 层很薄;所有的业务逻辑都存在于 runtime 的 Local API 中;适配器则隔离了边缘环境的具体实现。 ``` flowchart TD subgraph client["Client"] NG["@forge-cms/angular
CmsApiService · provideForgeCms"] ADMIN["@forge-cms/admin
schema-driven UI"] end subgraph edge["Cloudflare Pages (apps/www)"] HTTP["HTTP handlers
parse · auth gate · JSON envelope"] RT["ForgeCmsRuntime — Local API
access · hooks · drafts · validation · populate"] end subgraph adapters["Adapters (contract-tested)"] DB["DatabaseAdapter
InMemory · LibSQL · D1"] ST["StorageAdapter
InMemory · R2"] AU["AuthAdapter
SignedToken · UsersCollection"] end subgraph cf["Edge infrastructure"] D1[("Cloudflare D1")] R2[("Cloudflare R2")] end NG -->|"fetch /api/v1/*"| HTTP ADMIN --> NG HTTP --> RT RT --> DB & ST & AU DB --> D1 ST --> R2 ``` 有关完整的包依赖关系图、数据流和 API 契约,请参阅 [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md)。 ## 🚀 快速开始 需要 **Node ≥ 22** 和 **pnpm 10** (`corepack enable`)。 ``` git clone https://github.com/Andersseen/ForgeCMS.git cd ForgeCMS pnpm install # 落地页 + /admin demo(真实 API,内存 adapters,种子数据) pnpm dev:www # 或者用于尝试 CMS APIs 的 sandbox pnpm dev:playground ``` 打开 `/admin` 演示页面,并使用 `demo@forgecms.dev` / `forgecms-demo` 登录。 **[10 分钟教程](docs/QUICKSTART.md)** 将指导你添加自己的 collection,并使用 `curl` 测试 CRUD API。 ## 📦 包 这是一个基于 pnpm-workspaces + Turborepo 的 monorepo。仅支持 ESM,采用 TypeScript 严格模式。目前尚未发布到 npm。 | Package | Version | Description | | ---------------------------------------------- | :-----: | --------------------------------------------------------------------------------------- | | [`@forge-cms/core`](packages/core) | 0.1.0 | Schema DSL (`defineCollection` / `defineField`) + runtime 验证 | | [`@forge-cms/db`](packages/db) | 0.1.0 | `DatabaseAdapter` 契约 + InMemory 与 LibSQL 适配器 + SQL schema 生成器 | | [`@forge-cms/auth`](packages/auth) | 0.2.0 | `AuthAdapter` 契约 + InMemory / 外部 / 签名 token / 用户集合适配器 | | [`@forge-cms/storage`](packages/storage) | 0.1.0 | `StorageAdapter` 契约 + InMemory 适配器 | | [`@forge-cms/api`](packages/api) | 0.1.0 | `ApiContext` / CRUD handler 类型 | | [`@forge-cms/runtime`](packages/runtime) | 0.1.0 | `ForgeCmsRuntime` 编排器 + Local API + 框架无关的 HTTP handler | | [`@forge-cms/cloudflare`](packages/cloudflare) | 0.1.0 | Cloudflare **D1** + **R2** 适配器 | | [`@forge-cms/angular`](packages/angular) | 0.2.0 | Angular 客户端 SDK (`CmsApiService`, `provideForgeCms`) | | [`@forge-cms/admin`](packages/admin) | 0.2.0 | Angular 管理组件 (布局、列表、schema 驱动的表单) | | [`@forge-cms/testing`](packages/testing) | 0.1.0 | 共享的适配器契约测试套件 | ``` apps/ www/ Analog.js landing + /admin demo + h3 server API (/api/v1/*) → Cloudflare Pages playground/ Analog.js sandbox for trying the CMS APIs ``` ## ☁️ 部署 (仅限 Cloudflare) ForgeCMS 部署到 **唯一目标:Cloudflare Pages**。`apps/www` 通过 Nitro 的 `cloudflare-pages` 预设构建到 `apps/www/dist/analog/public` —— 其中包含 `_worker.js` (即编译后的 API 服务端) —— 因此部署后的站点能够使用真实的 D1 持久化来处理 `/api/*` 请求,而不仅仅是提供静态文件。 **单一的 GitHub Actions 流水线** ([`.github/workflows/ci.yml`](.github/workflows/ci.yml)) 会在每次推送/PR 时运行: ``` checks → lint · typecheck · test · build · e2e └── deploy (main only) → wrangler pages deploy → Cloudflare ``` 随时可以从你的本地机器手动部署: ``` pnpm deploy:www # build:www + wrangler pages deploy ``` **必需的仓库密钥** (Settings → Secrets → Actions): | Secret | 用途 | | ----------------------- | -------------------------------------------------- | | `CLOUDFLARE_API_TOKEN` | 具有 _Cloudflare Pages: Edit_ 权限的 Token | | `CLOUDFLARE_ACCOUNT_ID` | 你的 Cloudflare 账户 ID | D1 绑定 (`DB`) 在 [`wrangler.toml`](wrangler.toml) 中配置;当存在 `env.DB` 时,runtime 会自动选择 D1 适配器,并在本地回退到内存模式。 ## 🧰 命令 ``` pnpm dev:www # landing app + /admin demo pnpm dev:playground # playground sandbox pnpm build # build all packages and apps (topological, Turbo-cached) pnpm test # unit tests (Vitest) pnpm e2e:www # Playwright e2e for apps/www pnpm lint # ESLint across the repo pnpm typecheck # tsc --noEmit across the repo pnpm format # Prettier write pnpm deploy:www # build + deploy to Cloudflare Pages pnpm changeset # add a changeset (required for packages/* changes) ``` **质量门禁:** `pnpm lint && pnpm typecheck && pnpm test && pnpm build` ## 🗺️ 路线图 阶段 1 —— 即将带类型的 CRUD 层与真正的 CMS 区分开来的结构核心 —— 已经 **完成**。 - [x] **阶段 0** — D1 身份验证 schema 修复,分页元数据 _(发布到 npm 的工作仍待完成)_ - [x] **阶段 1** — Local API,基于函数的访问控制,完整的 hook 流水线,复合字段 - [ ] **阶段 2** — 内容模型:globals、版本/修订、本地化、查询功能完善 - [ ] **阶段 3** — 身份验证与开发体验 (DX):cookies/refresh/API keys,邮件适配器,配置与插件系统,CLI - [ ] **阶段 4** — 管理后台 UI:富文本编辑器,媒体选择器,可搜索的 relation 选择器,实时预览 - [ ] **阶段 5** — Angular 的护城河:基于 Signals 的客户端资源,Analog 集成包 完整的阶段排期与设计初衷详见 [docs/ROADMAP.md](docs/ROADMAP.md)。 ## 🤝 贡献 重要的新功能需从 [`docs/specs/`](docs/specs) 中的规范说明开始 ([SDD 工作流](docs/SDD.md))。有关环境配置和准则,请参阅 [CONTRIBUTING.md](CONTRIBUTING.md) 以及 [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md)。对 `packages/*` 下的更改需要提供 changeset (`pnpm changeset`)。 ## 📄 许可证 [MIT](./LICENSE) © ForgeCMS 贡献者
标签:Angular, Cloudflare, Grype, MITRE ATT&CK, TypeScript, 内容管理系统, 安全插件, 无头CMS, 特征检测, 自动化攻击, 边缘计算