Files
devos/apps/api/src/v2/registry/resource-registry.ts
T
phptits b1f17cf637 v2 platform foundation (docs 01/02/03): Action Runtime + Registry + unified API
- v2 foundation: ActionResult/DevError/ActorContext/ResourceRef/Execution types
- ActionRegistry + ResourceRegistry (namespaced types, FAIL FAST on duplicates)
- ActionRuntime pipeline: validate -> authorize -> middleware -> handler ->
  output validation -> audit -> event -> execution persisted (devos_action_executions)
- Legacy bridge: v1 services registered as devops.*/core.* resources & actions (47 actions, 9 resources)
- Unified Action API: POST /api/v2/actions/:actionId, GET discovery (actions/resources)
- 10 v2 unit tests (registry fail-fast, validation, authz, failure audit, events)
2026-09-10 21:09:44 +00:00

74 lines
2.3 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* # Resource Registry(docs 03 §11/§12)
* 平台级资源类型注册表:命名空间类型(core.user / devops.server / seo.website),
* 每个 Resource 声明 schema、actions、UI metadata。启动阶段 Core → Apps → Plugins 依次注册。
*/
import type { z } from "zod";
import type { ResourceRef } from "../foundation/types";
/** # 资源事件定义 **/
export interface ResourceEventDefinition {
/** # 形如 resource.created **/
type: string;
description?: string;
}
/** # 资源 UI 元数据(通用 UI 自动生成用) **/
export interface ResourceUI {
icon?: string;
listColumns?: string[];
}
/** # Resource 定义(docs 03 §5) **/
export interface ResourceDefinition<T = unknown> {
/** # 命名空间类型 <namespace>.<resource> **/
type: string;
label: string;
description?: string;
schema?: z.ZodType<T>;
/** # 该资源拥有的 Action id 列表(注册到 ActionRegistry) **/
actionIds: string[];
events?: ResourceEventDefinition[];
ui?: ResourceUI;
/** # 所有权:organization → 授权自动带组织 scope **/
ownership?: { organization: boolean };
/** # 父资源(Project → Website → Page) **/
parent?: { type: string };
}
export class ResourceRegistry {
private resources = new Map<string, ResourceDefinition<never>>();
/** # 注册:重复 type FAIL FAST(docs 03 §87) */
register(resource: ResourceDefinition<never>, registeredBy = "core"): void {
if (!resource.type.includes(".")) {
throw new Error(`[v2] resource type must be namespaced: ${resource.type}`);
}
if (this.resources.has(resource.type)) {
throw new Error(`[v2] duplicate resource type: ${resource.type}`);
}
this.resources.set(resource.type, resource);
}
get(type: string): ResourceDefinition<never> | undefined {
return this.resources.get(type);
}
has(type: string): boolean {
return this.resources.has(type);
}
list(): ResourceDefinition<never>[] {
return [...this.resources.values()].map((r) => r);
}
/** # ResourceRef → 定义(校验类型存在) */
resolveRef(ref: ResourceRef): ResourceDefinition<never> {
const def = this.resources.get(ref.type);
if (!def) throw new Error(`[v2] unknown resource type: ${ref.type}`);
return def;
}
}
export const resourceRegistry = new ResourceRegistry();