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)
This commit is contained in:
@@ -0,0 +1,73 @@
|
||||
/**
|
||||
* # 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();
|
||||
Reference in New Issue
Block a user