diff --git a/dll/editor-bricks-helper/manifest.snapshot.json b/dll/editor-bricks-helper/manifest.snapshot.json index c07484c8d6..ebc9ff5f46 100644 --- a/dll/editor-bricks-helper/manifest.snapshot.json +++ b/dll/editor-bricks-helper/manifest.snapshot.json @@ -200,6 +200,7 @@ "getCurrentTheme", "getHistory", "getMockInfo", + "getRealValue", "getRuntime", "getRuntimeMisc", "handleHttpError", diff --git a/etc/brick-kit.api.md b/etc/brick-kit.api.md index b70085dda2..f0a2e877b2 100644 --- a/etc/brick-kit.api.md +++ b/etc/brick-kit.api.md @@ -347,6 +347,9 @@ export const getMockInfo: (requestUrl: string, method: string) => { mockId: string; } | undefined; +// @public +export function getRealValue(value: unknown): unknown; + // @public export function getRuntime(): Runtime; diff --git a/packages/brick-dll/manifest.snapshot.json b/packages/brick-dll/manifest.snapshot.json index d26db11273..62ceccb292 100644 --- a/packages/brick-dll/manifest.snapshot.json +++ b/packages/brick-dll/manifest.snapshot.json @@ -18541,6 +18541,7 @@ "getCurrentTheme", "getHistory", "getMockInfo", + "getRealValue", "getRuntime", "getRuntimeMisc", "handleHttpError", diff --git a/packages/brick-kit/src/getRealValue.spec.ts b/packages/brick-kit/src/getRealValue.spec.ts new file mode 100644 index 0000000000..0a33c22f90 --- /dev/null +++ b/packages/brick-kit/src/getRealValue.spec.ts @@ -0,0 +1,35 @@ +import { PluginRuntimeContext } from "@next-core/brick-types"; +import * as runtime from "./core/Runtime"; +import { getRealValue } from "./getRealValue"; + +const mockCurrentContext = jest.spyOn(runtime, "_internalApiGetCurrentContext"); + +describe("getRealValue", () => { + const context: PluginRuntimeContext = { + query: new URLSearchParams({ + quality: "good", + }), + }; + + beforeEach(() => { + mockCurrentContext.mockReturnValue(context); + }); + + it.each<[unknown, unknown]>([ + ["${QUERY.quality}", "good"], + [["<% QUERY.quality %>"], ["good"]], + [ + { + "<% QUERY.quality %>": "<% QUERY.quality.toUpperCase() %>", + }, + { + good: "GOOD", + }, + ], + ["oops", "oops"], + [2, 2], + ])("test getRealValue(%j)", (input, output) => { + const result = getRealValue(input); + expect(result).toEqual(output); + }); +}); diff --git a/packages/brick-kit/src/getRealValue.ts b/packages/brick-kit/src/getRealValue.ts new file mode 100644 index 0000000000..c9d14a3ed2 --- /dev/null +++ b/packages/brick-kit/src/getRealValue.ts @@ -0,0 +1,39 @@ +import type { PluginRuntimeContext } from "@next-core/brick-types"; +import { inject, isEvaluable, isObject } from "@next-core/brick-utils"; +import { _internalApiGetCurrentContext } from "./core/exports"; +import { evaluate } from "./internal/evaluate"; +import { haveBeenInjected, recursiveMarkAsInjected } from "./internal/injected"; + +/** + * An equivalent of `computeRealValue` but for external usages, with no custom + * context or options. + * + * @param value - Any value which may contains evaluations or placeholders. + * @returns Computed real value. + */ +export function getRealValue(value: unknown): unknown { + const compute = (data: unknown, ctx: PluginRuntimeContext): unknown => { + if (typeof data === "string") { + if (isEvaluable(data)) { + const result = evaluate(data); + recursiveMarkAsInjected(result); + return result; + } + return inject(data, ctx); + } + + if (!isObject(data) || haveBeenInjected(value)) { + return data; + } + + if (Array.isArray(data)) { + return data.map((v) => compute(v, ctx)); + } + + return Object.fromEntries( + Object.entries(data).map(([k, v]) => [compute(k, ctx), compute(v, ctx)]) + ); + }; + + return compute(value, _internalApiGetCurrentContext()); +} diff --git a/packages/brick-kit/src/index.ts b/packages/brick-kit/src/index.ts index ad1eabd519..28287b9537 100644 --- a/packages/brick-kit/src/index.ts +++ b/packages/brick-kit/src/index.ts @@ -42,3 +42,4 @@ export { getMockInfo } from "./core/MockRegistry"; export * from "./hooks"; export * from "./internal/misc"; export * from "./abortController"; +export * from "./getRealValue";