@ 经典/ arc
Fastify数据库不可知资源框架. 一个 defineResource() 调用 - > REST + 认证 + 权限 + 事件 + 缓存 + OpenAPI + MCP 工具.
仅将5+ + + + 节点.js 22+ + + + 无害环境管理
npm install @classytic/arc fastify
# Security defaults createApp() loads (each opt-out via `cors: false` etc.)
npm install @fastify/cors @fastify/helmet @fastify/rate-limit @fastify/under-pressure @fastify/sensible
# Storage adapter — pick one (kits ship their own adapters under `/adapter`)
npm install @classytic/mongokit mongoose # MongoDB → @classytic/mongokit/adapter
# OR @classytic/sqlitekit drizzle-orm better-sqlite3 # → @classytic/sqlitekit/adapter
# OR @classytic/prismakit @prisma/client # → @classytic/prismakit/adapter
# OR implement DataAdapter / RepositoryLike from @classytic/repo-core/adapter
为什么弧
| 一通电话,全速前进 | defineResource({ name, adapter, presets, permissions }) → GET /, (中文(简体) ), GET /:id, (中文(简体) ), POST /, (中文(简体) ), PATCH /:id, (中文(简体) ), DELETE /:id +自定义路线+动作 |
| DB 不可知论 | Mong (@classytic/mongokit/adapter), Drizzle/SQLite (英语:@classytic/sqlitekit/adapter),普里斯玛(@classytic/prismakit/adapter),或任意 RepositoryLike impl – 互换后端而无需重写路径 。 适应者合同居住在 @classytic/repo-core/adapter; 弧形 2.12 舰只为零套具专用适配器. |
| 默认多租户 | 租户田地自动注入,有视野的查询,每升缓存密钥,高地事件. |
| 树上可动摇的子路径 | @classytic/arc/auth, (中文(简体) ), /events, (中文(简体) ), /cache, (中文(简体) ), /mcp, (中文(简体) ), /integrations/jobs ——只支付进口品. |
| 免费MCP工具 | 资源自动生成模型背景协议工具用于AI代理. 相同的权限,相同的字段规则. |
快开始
import mongoose from 'mongoose';
import { createApp, loadResources } from '@classytic/arc/factory';
await mongoose.connect(process.env.DB_URI);
// Fail fast on missing CORS env — silent `undefined` here drops to surprising
// browser defaults. Browser apps: declare an explicit allowlist (below).
// Server-to-server / API-key services: `cors: { origin: '*', credentials: false }`
// or `cors: false` to disable entirely (CORS is a browser-only concern).
const ALLOWED_ORIGINS = process.env.ALLOWED_ORIGINS;
if (!ALLOWED_ORIGINS) throw new Error('ALLOWED_ORIGINS env is required');
const app = await createApp({
preset: 'production',
resourcePrefix: '/api/v1',
resources: await loadResources(import.meta.url), // auto-discover *.resource.ts
auth: { type: 'jwt', jwt: { secret: process.env.JWT_SECRET } },
cors: { origin: ALLOWED_ORIGINS.split(','), credentials: true },
});
await app.listen({ port: 8040, host: '0.0.0.0' });
资源可以是静态阵列,Async厂(引擎装入),也可以是从磁盘上自动发现的:
// Auto-discover (recommended for >5 resources)
resources: await loadResources(import.meta.url),
// Explicit list
resources: [productResource, orderResource],
// Async factory — runs after `bootstrap[]`, before route wiring
resources: async () => {
const [catalog, flow] = await Promise.all([ensureCatalogEngine(), ensureFlowEngine()]);
return loadResources(import.meta.url, { context: { catalog, flow } });
},
loadResources({ context }) 线程引擎处理为默认导出的资源 (ctx) => defineResource(...)。没有并行的工厂文件,没有 exclude: [...] 簿记.
定义资源
import { defineResource } from '@classytic/arc';
import { allowPublic, requireRoles, requireAuth } from '@classytic/arc/permissions';
import { createMongooseAdapter } from '@classytic/mongokit/adapter';
import { buildCrudSchemasFromModel } from '@classytic/mongokit';
import ProductModel from './product.model.js';
import productRepository from './product.repository.js';
export default defineResource({
name: 'product',
adapter: createMongooseAdapter({
model: ProductModel,
repository: productRepository,
schemaGenerator: buildCrudSchemasFromModel, // auto-derives CRUD schemas
}),
presets: ['softDelete', 'slugLookup', { name: 'multiTenant', tenantField: 'organizationId' }],
permissions: {
list: allowPublic(),
get: allowPublic(),
create: requireRoles(['admin']),
update: requireRoles(['admin']),
delete: requireRoles(['admin']),
},
schemaOptions: {
fieldRules: {
name: { minLength: 2, maxLength: 200 },
sku: { pattern: '^[A-Z]{3}-\\d{3}$' },
status: { enum: ['draft', 'active', 'archived'] },
priceMode: { nullable: true }, // accept null for round-trips
organizationId: { systemManaged: true, preserveForElevated: true },
},
query: {
allowedPopulate: ['category', 'createdBy'], // populate whitelist
filterableFields: { status: { type: 'string' } },
},
},
cache: { staleTime: 30, gcTime: 300, tags: ['catalog'] },
routes: [
{ method: 'GET', path: '/featured', handler: 'getFeatured', permissions: allowPublic() },
],
actions: {
approve: { handler: approveOrder, permissions: requireRoles(['admin']) },
},
// mcp: false, // opt out of MCP tool generation for this resource
});
自动生成 : GET /products, (中文(简体) ), GET /products/:id, (中文(简体) ), POST /products, (中文(简体) ), PATCH /products/:id, (中文(简体) ), DELETE /products/:id + 软删除后添加 GET /products/deleted, (中文(简体) ), POST /products/:id/restore + 搜索键添加 GET /products/slug/:slug + 定制路线 + POST /products/:id/action。 。 。 .
资源简称
// Reference data — read-only list+get, fetch-all limits (1000), 5min/10min cache.
defineResource({ name: 'currency', adapter, referenceData: true });
// Service resource — custom routes only, no adapter, no auto-CRUD, no registry entry.
defineResource({
name: 'health',
customRoutesOnly: true,
routes: [{ method: 'GET', path: '/ping', permissions: allowPublic(), handler: () => ({ ok: true }) }],
});
// Tune pagination caps inline (no custom queryParser needed).
defineResource({ name: 'pipeline', adapter, defaultLimit: 200, maxLimit: 500 });
A 类 ?limit= 上限以上为 夹住它 已服过役,未遭拒绝(在2.33中更改)。 拒绝使有记录的夹子无法取用,并将一个良性的任务变成400个通常由呼叫者制作的空清单。 有效的封顶在 OpenAPI 参数描述中被携带, 并且响应是自己的 limit 报告适用的情况.
权限
基于功能的——非洲区域局、ABAC、REBAC或任何组合.
import {
allowPublic, requireAuth, requireRoles, requireOwnership,
requireOrgMembership, requireOrgRole, requireServiceScope,
requireScopeContext, requireOrgInScope,
allOf, anyOf, when, denyAll,
createDynamicPermissionMatrix,
} from '@classytic/arc/permissions';
permissions: {
list: allowPublic(),
get: requireAuth(),
create: requireRoles(['admin', 'editor']),
update: anyOf(requireOwnership('userId'), requireRoles(['admin'])),
delete: allOf(requireAuth(), requireRoles(['admin'])),
}
自定义检查返回 { granted, reason?, filters?, scope? } —— 说 filters 传播到 repo 查询( row- level ABAC) , scope 下游的邮票属性.
合计
添加 aggregations: { … } 到一个资源和弧登记册 GET /:prefix/aggregations/:name 每个条目。 每个运行一个便携式 $match → $group → $project → $sort → $limit 输油管对装箱 repo.aggregate(req, options) ——同形状横跨mongokit / sqlitekit / prismakit,所以仪表板在后端工作不变.
import { defineResource, defineAggregation } from '@classytic/arc';
defineResource({
name: 'transaction',
adapter,
presets: [multiTenantPreset({ tenantField: 'organizationId' })],
permissions: { list: canViewRevenue() },
aggregations: {
byPaymentMethod: defineAggregation({
groupBy: 'method',
measures: { total: 'sum:amount', count: 'count' },
sort: { total: -1 },
cache: { staleTime: 60, swr: true, tags: ['revenue'] },
permissions: canViewRevenue(),
}),
byDay: defineAggregation({
dateBuckets: { day: { field: 'createdAt', interval: 'day' } },
groupBy: 'flow',
measures: { total: 'sum:amount', count: 'count' },
requireDateRange: { field: 'createdAt', maxRangeDays: 365 },
cache: { staleTime: 60, swr: true, tags: ['revenue'] },
permissions: canViewRevenue(),
}),
},
});
通过查询字符串调用过滤器与声明一起组成 :
GET /api/transactions/aggregations/byPaymentMethod?status=verified
GET /api/transactions/aggregations/byDay?createdAt[gte]=2026-01-01&createdAt[lt]=2026-02-01
租户范围流经 repo.aggregate(req, options) – 工具包的多租户插件处理类型强制(字符串) – ObjectId for mongokit fieldType: 'objectId',用于 sqlitekit 的UUID/文本等). 弧本身不进入滤波槽,因为它具有DB-不可知性. 申报的警卫: requireFilters, (中文(简体) ), requireDateRange { maxRangeDays }, (中文(简体) ), maxGroups。 SWR 缓存 + 标记无效绑定集合到 CRUD 写入 。 每个聚合自导出作为具有相同权限和过滤验证的MCP工具.
认证
歧视工会 type数字 :
// JWT (with optional revocation + custom token extractor)
auth: { type: 'jwt', jwt: { secret, expiresIn: '15m' } }
// Better Auth (recommended for SaaS with orgs)
import { createBetterAuthAdapter } from '@classytic/arc/auth';
auth: { type: 'betterAuth', betterAuth: createBetterAuthAdapter({ auth: getAuth(), orgContext: true }) }
// Custom Fastify plugin
auth: { type: 'custom', plugin: myAuthPlugin }
// Disabled (e.g. internal services)
auth: false
更好的Auth + 弧度资源超过 BA 表:工具包拥有桥. @classytic/mongokit/better-auth 船舶 createBetterAuthOverlay() (按年计) DataAdapter 页:1 defineResource和 registerBetterAuthStubs() (用于 populate()) (中文(简体) ). Sqlitekit 用户手卷 Drizzle 表格——见 auth-bet-auth-overlay.md (英语)。 。 。 .
子路径导入
仅导入您需要的子路径 :
| 子路径 | 目的 |
|---|---|
@classytic/arc | defineResource, (中文(简体) ), BaseController,错误类别 |
@classytic/repo-core/adapter | 适应合同类型: DataAdapter, (中文(简体) ), RepositoryLike, (中文(简体) ), AdapterRepositoryInput, (中文(简体) ), asRepositoryLike, (中文(简体) ), isRepository。 。 。 . 直接从还原核心导入 ——arc故意不再出口合同以保持一个真相来源. |
@classytic/arc/factory | createApp, (中文(简体) ), loadResources预设 |
@classytic/arc/auth | JWT + 更好的认证适配器 |
@classytic/mongokit/better-auth | BA为蒙哥斯: createBetterAuthOverlay, (中文(简体) ), registerBetterAuthStubs (公斤拥有) |
@classytic/repo-core/better-auth | 每套包件的共享BA收集登记册 |
@classytic/arc/permissions | 所有权限助手 |
@classytic/arc/scope | RequestScope 访问者isMember, (中文(简体) ), isElevated, (中文(简体) ), getOrgId, (...) (中文(简体) ) |
@classytic/arc/cache | QueryCache,运输,插件 |
@classytic/arc/events | 事件插件, MemoryEventTransport外框(活动类型) @classytic/primitives/events(中文(简体) ) |
@classytic/arc/events/redis • 妇女 /redis-stream | Redis Pub/Sub + 流运输(选择入) |
@classytic/arc/plugins | 健康、请求识别、版本、追踪、反应-缓存 |
@classytic/arc/integrations/jobs | BullMQ 工作调度器 |
@classytic/arc/integrations/websocket | WebSocket 集成系统 |
@classytic/arc/mcp | 示范背景协议工具+ createMcpAuthFromBetterAuthApiKey (Better Auth API- key settlementer),(更好的Auth API-键解析器), resolveToolCollisions |
@classytic/arc/utils | pipeUIMessageStreamToReply, (中文(简体) ), UI_MESSAGE_STREAM_HEADERS (Vercel AI SDK → 快速回复);错误、查询解析器、断路器 |
@classytic/arc/testing | createTestApp, (中文(简体) ), expectArc, (中文(简体) ), TestAuthProvider, (中文(简体) ), createTestFixtures |
@classytic/arc/types | 仅管型(零运行时间成本) |
测试
import { createTestApp, expectArc } from '@classytic/arc/testing';
import productResource from './product.resource.js';
const ctx = await createTestApp({
resources: [productResource],
authMode: 'jwt',
connectMongoose: true, // in-memory Mongo + Mongoose connect
});
ctx.auth.register('admin', { user: { id: '1', role: 'admin' }, orgId: 'org-1' });
const res = await ctx.app.inject({
method: 'POST',
url: '/products',
headers: ctx.auth.as('admin').headers,
payload: { name: 'Widget' },
});
expectArc(res).ok().hidesField('password');
await ctx.close();
三个切入点: createTestApp (海关设想), createHttpTestHarness (~16个自动生成的CRUD/每个资源允许/验证测试),, runStorageContract (适应).
国 际
arc init my-api --mongokit --better-auth --ts # scaffold a new project
arc generate resource product # generate a resource
arc generate resource product --mcp # + MCP tools file
arc docs ./openapi.json --entry ./dist/index.js # emit OpenAPI
arc introspect --entry ./dist/index.js # introspect resources
arc doctor # diagnose env
文档
- 技能 对于人工智能特工:
npx skills add classytic/arc——电线弧入克洛德代码/代理流. - 概念参考数字 : 维基文库/index.md ——短而相通的页.
- 指南数字 : 文档/ ——启动,框架延伸,生产操作,测试,生态系统.
- 发布注释数字 : 变化日志/v2.md。 。 。 .
许可证
麻省理工学院
商标
密码是麻省理工学院许可的. "classytic","arc",并标志为: 经典专卖局长 并且现在 没有 根据麻省理工学院颁发的许可证——见 贸易商。 。 。 . 叉子必须更名;许可证覆盖了代码,而不是品牌.