diff --git a/dll/editor-bricks-helper/manifest.snapshot.json b/dll/editor-bricks-helper/manifest.snapshot.json index 30a2e7eee9..3619f08e52 100644 --- a/dll/editor-bricks-helper/manifest.snapshot.json +++ b/dll/editor-bricks-helper/manifest.snapshot.json @@ -20,6 +20,7 @@ "PrecookVisitor", "asyncProcessBrick", "asyncProcessStoryboard", + "collectBricksByCustomTemplates", "computeRealRoutePath", "convertValueByPrecision", "cook", diff --git a/etc/brick-types.api.md b/etc/brick-types.api.md index ee34d73cc6..ed4a9f2aab 100644 --- a/etc/brick-types.api.md +++ b/etc/brick-types.api.md @@ -958,6 +958,7 @@ export interface CustomDisplay> { // @public export interface CustomTemplate { bricks: BrickConfInTemplate[]; + contracts?: Contract[]; name: string; proxy?: CustomTemplateProxy; state?: CustomTemplateState[]; diff --git a/packages/brick-dll/manifest.snapshot.json b/packages/brick-dll/manifest.snapshot.json index 8719efbf16..5bcd90d97d 100644 --- a/packages/brick-dll/manifest.snapshot.json +++ b/packages/brick-dll/manifest.snapshot.json @@ -3501,6 +3501,7 @@ "PrecookVisitor", "asyncProcessBrick", "asyncProcessStoryboard", + "collectBricksByCustomTemplates", "computeRealRoutePath", "convertValueByPrecision", "cook", diff --git a/packages/brick-kit/src/core/CollectContracts.spec.ts b/packages/brick-kit/src/core/CollectContracts.spec.ts index c7343df3ee..282b6078c7 100644 --- a/packages/brick-kit/src/core/CollectContracts.spec.ts +++ b/packages/brick-kit/src/core/CollectContracts.spec.ts @@ -1,4 +1,9 @@ -import { collectContract, getContract } from "./CollectContracts"; +import { + collectContract, + getContract, + collectWidgetContract, + clearCollectWidgetContract, +} from "./CollectContracts"; describe("CollectContract", () => { it("should work", () => { @@ -23,4 +28,30 @@ describe("CollectContract", () => { version: "1.0.0", }); }); + + it("should work with widget", () => { + const contracts = [ + { + namespaceId: "easyops.api.cmdb.model", + name: "getDetail", + version: "1.0.0", + }, + { + namespaceId: "easyops.api.cmdb.model", + name: "postSearch", + version: "1.2.0", + }, + ]; + collectWidgetContract(contracts); + + expect(getContract("easyops.api.cmdb.model.postSearch")).toEqual({ + namespaceId: "easyops.api.cmdb.model", + name: "postSearch", + version: "1.2.0", + }); + + clearCollectWidgetContract(); + + expect(getContract("easyops.api.cmdb.model.postSearch")).toEqual(undefined); + }); }); diff --git a/packages/brick-kit/src/core/CollectContracts.ts b/packages/brick-kit/src/core/CollectContracts.ts index 5b0d40c54b..bcd8498bf4 100644 --- a/packages/brick-kit/src/core/CollectContracts.ts +++ b/packages/brick-kit/src/core/CollectContracts.ts @@ -1,13 +1,29 @@ import { Contract } from "@next-core/brick-types"; const contractsMap: Map = new Map(); +const widgetContractMap: Map = new Map(); -export function collectContract(contracts: Contract[]): void { +const addContract = ( + contracts: Contract[], + map: Map +): void => { contracts?.forEach((contract) => { - contractsMap.set(`${contract.namespaceId}.${contract.name}`, contract); + map.set(`${contract.namespaceId}.${contract.name}`, contract); }); +}; + +export function collectContract(contracts: Contract[]): void { + addContract(contracts, contractsMap); +} + +export function collectWidgetContract(contracts: Contract[]): void { + addContract(contracts, widgetContractMap); +} + +export function clearCollectWidgetContract(): void { + widgetContractMap.clear(); } export function getContract(name: string): Contract { - return contractsMap.get(name); + return contractsMap.get(name) || widgetContractMap.get(name); } diff --git a/packages/brick-kit/src/core/CustomTemplates/expandCustomTemplate.ts b/packages/brick-kit/src/core/CustomTemplates/expandCustomTemplate.ts index e2dcc5b27e..c4d22ec96f 100644 --- a/packages/brick-kit/src/core/CustomTemplates/expandCustomTemplate.ts +++ b/packages/brick-kit/src/core/CustomTemplates/expandCustomTemplate.ts @@ -23,6 +23,7 @@ import { collectMergeBases } from "./collectMergeBases"; import { CustomTemplateContext } from "./CustomTemplateContext"; import { setupUseBrickInTemplate } from "./setupUseBrickInTemplate"; import { setupTemplateProxy } from "./setupTemplateProxy"; +import { collectWidgetContract } from "../CollectContracts"; export interface ProxyContext { reversedProxies: ReversedProxies; @@ -87,7 +88,7 @@ function lowLevelExpandCustomTemplate( context: PluginRuntimeContext, tplContext: CustomTemplateContext ): RuntimeBrickConf { - const { bricks, proxy, state } = template; + const { bricks, proxy, state, contracts } = template; const { properties: templateProperties, slots: externalSlots, @@ -103,6 +104,9 @@ function lowLevelExpandCustomTemplate( proxyBrick.proxyRefs = new Map(); proxyBrick.stateNames = state?.map((item) => item.name); + if (contracts) { + collectWidgetContract(contracts); + } const refToBrickConf = collectRefsInTemplate(template); // Reversed proxies are used for expand storyboard before rendering page. diff --git a/packages/brick-kit/src/core/Router.ts b/packages/brick-kit/src/core/Router.ts index 981e35bea5..cc7f4f85a0 100644 --- a/packages/brick-kit/src/core/Router.ts +++ b/packages/brick-kit/src/core/Router.ts @@ -50,7 +50,10 @@ import { registerStoryboardFunctions } from "./StoryboardFunctions"; import { HttpResponseError } from "@next-core/brick-http"; import { registerMock } from "./MockRegistry"; import { registerFormRenderer } from "./CustomForms/registerFormRenderer"; -import { collectContract } from "./CollectContracts"; +import { + clearCollectWidgetContract, + collectContract, +} from "./CollectContracts"; import { StoryboardContextWrapper } from "./StoryboardContext"; import { Media, mediaEventTarget } from "../internal/mediaQuery"; import { @@ -205,6 +208,7 @@ export class Router { resetAllInjected(); clearPollTimeout(); + clearCollectWidgetContract(); if (this.locationContext) { this.locationContext.resolver.resetRefreshQueue(); diff --git a/packages/brick-types/src/manifest.ts b/packages/brick-types/src/manifest.ts index b133951132..3802e6b342 100644 --- a/packages/brick-types/src/manifest.ts +++ b/packages/brick-types/src/manifest.ts @@ -1601,6 +1601,9 @@ export interface CustomTemplate { /** 状态数据配置列表。 */ state?: CustomTemplateState[]; + + /** 契约的定义,只有 widget 才有该字段 */ + contracts?: Contract[]; } /** 自定义模板状态数据配置。 */ diff --git a/packages/brick-utils/src/index.ts b/packages/brick-utils/src/index.ts index 72345ff7dd..5d7db9a765 100644 --- a/packages/brick-utils/src/index.ts +++ b/packages/brick-utils/src/index.ts @@ -19,7 +19,10 @@ export * from "./cook"; export * from "./resolveContextConcurrently"; export * from "./scanCustomApisInStoryboard"; export * from "./smartDisplayForEvaluableString"; -export { scanStoryboard } from "./scanStoryboard"; +export { + scanStoryboard, + collectBricksByCustomTemplates, +} from "./scanStoryboard"; export * from "./JsonStorage"; export * from "./builder"; export * from "./deepFreeze"; diff --git a/packages/brick-utils/src/scanStoryboard.ts b/packages/brick-utils/src/scanStoryboard.ts index 7907d704fe..397d663a48 100644 --- a/packages/brick-utils/src/scanStoryboard.ts +++ b/packages/brick-utils/src/scanStoryboard.ts @@ -301,7 +301,7 @@ function collectBricksInCustomTemplates( } } -function collectBricksByCustomTemplates( +export function collectBricksByCustomTemplates( customTemplates: CustomTemplate[] ): Map { const collectionByTpl = new Map(); @@ -310,6 +310,7 @@ function collectBricksByCustomTemplates( const collection = [] as string[]; collectionByTpl.set(tpl.name, collection); collectBricksInBrickConfs(tpl.bricks, collection); + collectBricksInContext(tpl.state, collection); }); } return collectionByTpl;