npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@wecode-team/cms-supabase-api

v0.1.31

Published

A CMS API package using Hono framework with Supabase and dynamic table management

Readme

@wecode-team/cms-supabase-api

一个基于 Hono 框架的动态 CMS API 包,使用 Supabase 作为后端数据库,支持动态表管理、数据关联、用户认证等功能。

📖 设计理念

核心思想

本包的核心理念是 "JSON Schema 驱动的动态 CMS"

  1. 模型即配置:通过 JSON Schema 定义数据模型,系统自动创建对应的数据库表
  2. 动态表管理:无需手写 SQL,通过 API 动态创建、修改、删除数据表
  3. 关系支持:支持 belongsTohasManybelongsToMany 三种关联关系
  4. 多租户隔离:通过表名前缀(Session ID)实现数据隔离

架构设计

┌─────────────────────────────────────────────────────────────┐
│                      Hono Application                        │
├─────────────────────────────────────────────────────────────┤
│  Route Helpers                                               │
│  ├── createCmsRoutes()     一键创建所有路由                  │
│  ├── createModelRoute()    模型管理路由                      │
│  ├── createDynamicDataRoute()  动态数据路由                  │
│  └── createDynamicAuthRoute()  动态认证路由                  │
├─────────────────────────────────────────────────────────────┤
│  Handlers (处理器层)                                         │
│  ├── models.ts      模型 CRUD                               │
│  ├── data.ts        数据 CRUD + 关联查询                    │
│  └── auth.ts        登录/认证/用户管理                       │
├─────────────────────────────────────────────────────────────┤
│  Services (服务层)                                           │
│  ├── DynamicTableService   动态表操作                       │
│  ├── CmsModelService       模型配置管理                     │
│  └── AuthService           认证服务                         │
├─────────────────────────────────────────────────────────────┤
│  Supabase (数据层)                                           │
│  ├── PostgreSQL            关系型数据库                     │
│  ├── RPC Functions         存储过程                         │
│  └── Row Level Security    行级安全                         │
└─────────────────────────────────────────────────────────────┘

🚀 安装

npm install @wecode-team/cms-supabase-api
# 或
pnpm add @wecode-team/cms-supabase-api
# 或
yarn add @wecode-team/cms-supabase-api

📋 依赖

Peer Dependencies(必须安装)

{
  "hono": "^4.0.0",
  "@supabase/supabase-js": "^2.0.0"
}

🔧 快速开始

第一步:初始化 Supabase

在 Supabase SQL 编辑器中执行 supabase-setup.sql 文件中的 SQL 脚本:

-- 执行完整的 supabase-setup.sql 文件
-- 这将创建必要的函数和表

🔐 Auth(登录/注册/权限)方案

本项目的 CMS 鉴权支持:

  • 首次进入需要注册管理员
  • 每个 session_id 仅一个管理员
  • session_id 维度权限隔离
  • Supabase Auth 邮箱重写(避免跨 session 冲突)
  • 不依赖 execute_sql(需要的 registry 表由你手动创建)

详见:AUTH_SCHEME.md

第二步:创建 Hono 应用

import { Hono } from 'hono'
import { cors } from 'hono/cors'
import { 
  initializeSupabase, 
  initializeCmsSystem,
  createCmsRoutes 
} from '@wecode-team/cms-supabase-api'

const app = new Hono()

// CORS 配置
app.use('/*', cors())

// 初始化 Supabase
initializeSupabase({
  url: process.env.SUPABASE_URL!,
  key: process.env.SUPABASE_ANON_KEY!
})

// 初始化 CMS 系统表
await initializeCmsSystem()

// 一键创建所有 CMS 路由
createCmsRoutes(app)

export default app

第三步:定义数据模型

通过 API 创建模型:

// POST /models
{
  "name": "文章模型",
  "table_name": "posts",
  "json_schema": {
    "fields": [
      {
        "name": "title",
        "type": "string",
        "comment": "文章标题",
        "required": true,
        "maxLength": 255
      },
      {
        "name": "content",
        "type": "text",
        "comment": "文章内容",
        "required": true
      },
      {
        "name": "author",
        "type": "relation",
        "comment": "作者",
        "required": true,
        "relation": {
          "type": "belongsTo",
          "target": "users",
          "foreignKey": "author_id",
          "displayField": "name"
        }
      },
      {
        "name": "status",
        "type": "string",
        "comment": "状态",
        "defaultValue": "draft"
      }
    ]
  }
}

📚 API 路由

模型管理

| 方法 | 路径 | 描述 | |------|------|------| | GET | /models | 获取所有模型 | | POST | /models | 创建新模型(同时创建数据表) | | PUT | /models | 更新模型 | | DELETE | /models?id={id} | 删除模型(同时删除数据表) |

数据管理

| 方法 | 路径 | 描述 | |------|------|------| | GET | /data/:tableName | 获取表数据(支持分页、搜索) | | GET | /data/:tableName/with-relations | 获取带关联数据的表数据 | | POST | /data/:tableName | 创建新数据 | | PUT | /data/:tableName | 更新数据 | | DELETE | /data/:tableName?id={id} | 删除数据 |

关联数据

| 方法 | 路径 | 描述 | |------|------|------| | GET | /relation/:tableName/options | 获取关联表选项(用于下拉选择) |

认证

| 方法 | 路径 | 描述 | |------|------|------| | GET | /auth/signup/status/:tableName | 查询当前 session 是否允许首次注册管理员 | | POST | /auth/signup/:tableName | 首次注册管理员(服务端代理 Supabase signUp) | | POST | /auth/:tableName/login | 用户登录 | | GET | /auth/:tableName/current | 获取当前用户信息 | | POST | /auth/:tableName/verify | 验证 Token | | GET | /auth/user/:tableName | 获取当前用户信息(兼容历史路径) | | POST | /auth/verify/:tableName | 验证 Token(兼容历史路径) |

提示:后台管理接口(/models/data/* 等)建议携带请求头 X-Session-Id,用于按 session_id 维度校验管理员权限。

🏗️ 字段类型

| 类型 | PostgreSQL 类型 | 说明 | |------|-----------------|------| | string | text | 短文本 | | text | text | 长文本 | | integer | int4 | 整数 | | float | float8 | 浮点数 | | boolean | bool | 布尔值 | | date | date | 日期 | | datetime | timestamptz | 日期时间 | | json | jsonb | JSON 对象 | | email | text | 邮箱(前端验证) | | relation | uuid/int4 | 关联字段(外键) |

🔗 关系配置

belongsTo(多对一)

{
  "name": "author",
  "type": "relation",
  "relation": {
    "type": "belongsTo",
    "target": "users",           // 关联的目标表
    "foreignKey": "author_id",   // 当前表的外键字段
    "displayField": "name"       // 下拉显示的字段
  }
}

hasMany(一对多)

{
  "name": "posts",
  "type": "relation",
  "relation": {
    "type": "hasMany",
    "target": "posts",
    "foreignKey": "author_id"    // 目标表的外键字段
  }
}

🔐 多租户支持(Session ID)

通过表名前缀实现数据隔离:

// 前端设置 Session ID
setSessionId("tenant123")

// API 调用时自动添加前缀
// GET /data/posts → 实际查询 tenant123_posts 表

🛠️ 高级用法

自定义路由

import { Hono } from 'hono'
import { 
  createModelRoute,
  createDynamicDataRoute,
  createAuthRoute 
} from '@wecode-team/cms-supabase-api'

const app = new Hono()

// 只创建模型路由
createModelRoute(app)

// 只创建数据路由
createDynamicDataRoute(app)

// 创建固定表名的认证路由
createAuthRoute(app, 'cms_users')

使用认证中间件

import { requireAuth, getModels } from '@wecode-team/cms-supabase-api'

// 保护路由
app.get('/protected/models', requireAuth(getModels))

直接使用服务层

import { 
  getDynamicTableService, 
  getCmsModelService 
} from '@wecode-team/cms-supabase-api'

const tableService = getDynamicTableService()
const modelService = getCmsModelService()

// 创建表
await tableService.createTable('my_table', {
  fields: [
    { name: 'title', type: 'string', required: true }
  ]
})

// 插入数据
await tableService.insertData('my_table', { title: 'Hello' })

🔧 环境变量

| 变量 | 说明 | 默认值 | |------|------|--------| | SUPABASE_URL | Supabase 项目 URL | - | | SUPABASE_ANON_KEY | Supabase 匿名密钥 | - | | JWT_SECRET | JWT 签名密钥 | 'your-secret-key-change-in-production' |

🐛 常见问题

1. 外键约束错误

如果遇到 violates foreign key constraint 错误,是因为数据库中的外键约束引用了错误的表。解决方法:

-- 删除错误的外键约束
ALTER TABLE "your_table" DROP CONSTRAINT IF EXISTS "constraint_name";

2. CHECK 约束错误

如果遇到 violates check constraint 错误:

-- 删除 CHECK 约束
ALTER TABLE "your_table" DROP CONSTRAINT IF EXISTS "table_status_check";

3. 函数不存在错误

如果遇到 Could not find the function 错误,需要执行初始化 SQL:

-- 执行 supabase-setup.sql 中的所有语句

📄 许可证

MIT