fix: ES2020 compatibility for automation engine build#750
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Fixes the service-automation build under the repo’s ES2020 TypeScript target by removing use of the ES2021-only String.prototype.replaceAll() API in the automation engine’s condition/template substitution logic.
Changes:
- Replaced
replaceAll()with ES2020-compatiblesplit().join()inAutomationEngine.evaluateCondition(). - Replaced
replaceAll()with ES2020-compatiblesplit().join()in the logic plugin’s decision-node expression evaluation.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| packages/services/service-automation/src/engine.ts | Removes ES2021 replaceAll() usage in condition expression variable substitution. |
| packages/services/service-automation/src/plugins/logic-nodes-plugin.ts | Removes ES2021 replaceAll() usage in decision-node condition variable substitution. |
Comments suppressed due to low confidence (1)
packages/services/service-automation/src/plugins/logic-nodes-plugin.ts:37
- There’s no test that exercises decision-node expression substitution (e.g. a flow with a decision condition that references
{status}and branches accordingly). Since this logic is part of the plugin and impacts runtime behavior, adding an integration test in the existing service-automation test suite would help prevent future regressions.
for (const cond of conditions) {
// MVP: Simple template replacement + expression evaluation.
// Flow definitions are authored by trusted developers/admins.
// TODO: Replace with safe expression evaluator (e.g., jexl) for production.
let expr = cond.expression;
for (const [k, v] of variables) {
expr = expr.split(`{${k}}`).join(String(v));
}
try {
if (new Function(`return (${expr})`)()) {
return { success: true, branchLabel: cond.label };
| let expr = cond.expression; | ||
| for (const [k, v] of variables) { | ||
| expr = expr.replaceAll(`{${k}}`, String(v)); | ||
| expr = expr.split(`{${k}}`).join(String(v)); |
There was a problem hiding this comment.
Same as in engine.ts: split().join() inserts the replacement literally and does not interpret "$" sequences the way replaceAll() does. Please confirm literal insertion is intended for decision expressions (it avoids surprising "$1"/"$&" behavior in values); otherwise you’ll need an ES2020-compatible implementation that preserves replaceAll semantics.
| expr = expr.split(`{${k}}`).join(String(v)); | |
| expr = expr.replaceAll(`{${k}}`, String(v)); |
| for (const [key, value] of variables) { | ||
| resolved = resolved.replaceAll(`{${key}}`, String(value)); | ||
| resolved = resolved.split(`{${key}}`).join(String(value)); | ||
| } |
There was a problem hiding this comment.
Using split().join() is not fully equivalent to replaceAll() when the replacement string contains "$" sequences (e.g. "$&", "$1"); replaceAll interprets those as replacement patterns, while join inserts them literally. Please confirm the intended semantics for template substitution (literal insertion is usually what you want here); if you need to preserve replaceAll’s behavior, you’ll need an ES2020-compatible polyfill that reproduces those "$" replacement patterns.
| private evaluateCondition(expression: string, variables: Map<string, unknown>): boolean { | ||
| // MVP: Simple template replacement + expression evaluation. | ||
| // Flow definitions are authored by trusted developers/admins. | ||
| // TODO: Replace with safe expression evaluator (e.g., jexl) for production. | ||
| let resolved = expression; | ||
| for (const [key, value] of variables) { | ||
| resolved = resolved.replaceAll(`{${key}}`, String(value)); | ||
| resolved = resolved.split(`{${key}}`).join(String(value)); | ||
| } |
There was a problem hiding this comment.
The template substitution/evaluation path isn’t covered by current tests (existing coverage only checks constant conditions like "true"/"false"). Adding a small test that exercises {var} substitution—especially with values containing $—would lock in the intended behavior and prevent regressions when changing the ES target/polyfills later.
CI build fails because
String.prototype.replaceAll()(ES2021) is used in the automation engine, but the project targets ES2020 via roottsconfig.json.Changes
replaceAll(pattern, replacement)with equivalentsplit(pattern).join(replacement)in:engine.ts—evaluateCondition()template variable substitutionlogic-nodes-plugin.ts— decision node condition expression evaluationOriginal prompt
This section details on the original issue you should resolve
<issue_title>实现自动化引擎插件化架构,支持能力无限扩展</issue_title>
<issue_description>## 目标
设计并实现一个基础的自动化引擎,允许通过插件持续扩展节点能力。
方案概述
技术任务拆分
MVP
二期
示例代码
验收标准
备注:开发任务完成后需补充 test,并及时更新 roadmap。
🏗️ 整体架构:基于 ObjectStack MicroKernel 的插件化 Automation Engine
ObjectStack 已经有一套成熟的 MicroKernel + Plugin 架构,自动化引擎应该 完全复用 这套体系,而不是另起炉灶。
核心思路
第一步:创建核心自动化引擎插件
这是唯一的「硬核」部分——它只做 DAG 解析 + 节点分发 + 变量流转,不实现任何具体节点逻辑。