When to Use This Skill
This is triggered when the user needs to "deprecate / phase out / retire / no longer recommend using" a workflow node (for example, LoopNode、RunAppModule , etc.).
Deprecation goal:
- Existing workflows can still load and run normally (maintain runtime compatibility).
- When creating a new workflow, the template panelno longer displaysthis node.
- The node's type enum value (FlowNodeTypeEnum) must be retained; otherwise, old workflows will not be able to find the node definition.
Core concept
Deprecation ≠ deletion.Only cut off the "new entry point", not the "runtime path"。
| Dimension | Handling method |
|---|---|
| Type enum value | Retain (referenced by old workflows) |
| Template definition | Move to abandoned/ directory, remove from the template panel list |
| Dispatcher | Move to abandoned/ directory, add @deprecated comment |
| moduleTemplatesFlat | Must be retained; otherwise, the node cannot render on the canvas |
| Node-level UI badge | Add to template status: PluginStatusEnum.SoonOffline, and a yellow "retiring soon" label appears in the node header + tooltip "please replace as soon as possible" |
| Child nodes / associated nodes | Deprecate them together only when it is confirmed that no other nodes share them |
| i18n key | Do not touch (old workflows will still read the name/intro text) |
ℹ️ Field-level
deprecated: true(FlowNodeInputItemType.deprecated/FlowNodeOutputItemType.deprecated) is anindependent mechanism, used to phase out a single field while retaining the node (old fields remain compatible, new fields replace them).Do not use it when deprecating an entire node — the node-level badge is already sufficient as an indicator, and adding field-level would make the signal overly redundant.
Reference case
There is already a complete deprecation case in the repository for reference:FlowNodeTypeEnum.runApp. You can compare git log --diff-filter=R -- "**/abandoned/runApp/**" to find the migration commit from that time.
TODO template (copy and fill in before execution)
Operation target: deprecate
<NodeTemplateName>(FlowNodeTypeEnum.<enumKey>)
- 1. Confirm scope of impact
- 2. Move template definitionto the abandoned directory
- 3. Move Dispatcherto the abandoned directory
- 4. Update
template/constants.ts: fromsystemNodesremove, ensure it remains inmoduleTemplatesFlat - 5. Update
dispatch/constants.ts: add@deprecatedcomment, move to the end of callbackMap - 6. Node-level badge: add to template
status: PluginStatusEnum.SoonOffline(the node header displays a yellow "retiring soon" label) - 7. Check UI / Hook references(not necessarily requiring changes)
- 8. Run lint + typecheck + partial tests
Detailed steps
1. Confirm scope of impact (required)
Before starting,first use grep/Explore to globally searchfor all references to the node and confirm the scope of changes. Keywords to check:
# 类型枚举使用点
grep -rn "FlowNodeTypeEnum\.<enumKey>\b" packages/ projects/ --include="*.ts" --include="*.tsx"
# 模板对象(如 LoopNode)
grep -rn "<TemplateExport>\b" packages/ projects/ --include="*.ts"
# 子节点是否被其他容器复用(重要!)
grep -rn "FlowNodeTypeEnum\.<childEnum>" packages/ projects/
Output a categorized list of "needs changes / does not need changes".Usually no changes needed:
useWorkflow.tsxembedded into runtime-recognition lists like PARENT_NODE_TYPES / unsupportedInLoop — old instances still need to work.Flow/index.tsxof thenodeTypesmapping — old instances need UI rendering.- i18n copy — old instances still read it.
2. Move the template definition to the abandoned directory
Source path:packages/global/core/workflow/template/system/<dir>/
Target path:packages/global/core/workflow/template/system/abandoned/<dir>/
Action:
- Use
git mv(or Bashmv) for the entire directory or only the parent node'sindex.ts/type.ts。 - Modify the relative import paths inside the file (one extra level of depth
../)。 - If only the container node is deprecated while the child nodes are kept (for example,
loopStart/loopEndis still shared byparallelRun),move only the parent node file, and leave the child nodes in place.
3. Move the Dispatcher to the abandoned directory
Source path:packages/service/core/workflow/dispatch/<dir>/<file>.ts
Target path:packages/service/core/workflow/dispatch/abandoned/<file>.ts
Action:
git mvfile.- Add a
/* Abandoned */comment to the first line of the file (consistent withdispatch/abandoned/runApp.ts). - Modify the relative import paths inside the file.
4. Update packages/global/core/workflow/template/constants.ts
// 旧
import { LoopNode } from './system/loop/loop';
// 新
import { LoopNode } from './system/abandoned/loop/index';
// 从 systemNodes 移除(这是模板面板的来源)
const systemNodes: FlowNodeTemplateType[] = [
...
// LoopNode, ← 删除这一行
...
];
// 在 moduleTemplatesFlat 中保留 / 添加(保证旧工作流能解析)
export const moduleTemplatesFlat: FlowNodeTemplateType[] = [
...,
LoopNode, // ← 这里要有
];
⚠️ Verification point:
moduleTemplatesFlatis the lookup source from node ID → template object.must be kept, otherwise old workflows will fail to find the node when loading, and the canvas will report an error.
5. Update packages/service/core/workflow/dispatch/constants.ts
// 把 import 路径改成 abandoned 子目录
import { dispatchLoop } from './abandoned/runLoop';
Move the corresponding callbackMap entry to the end of the object, and add a /** @deprecated */ comment:
export const callbackMap: Record<FlowNodeTypeEnum, Function> = {
// ...其他正常节点...
/** @deprecated */
[FlowNodeTypeEnum.loop]: dispatchLoop
};
6. Node-level badge status: PluginStatusEnum.SoonOffline
FlowNodeTemplateTypeSchema.status is a node-level deprecation UI signal, attached to the NodeCard.tsx header and rendered by <NodeStatusBadge /> :
| Value | Label | Color | tooltip | Applicable scenario |
|---|---|---|---|---|
Normal = 1 |
Normal | Blue | — | Not deprecated |
SoonOffline = 2 |
Sunsetting soon | Yellow | "Please replace as soon as possible" | Deprecated but still runnable(recommended to use this) |
Offline = 3 |
Sunset | Red | "No longer usable, will interrupt application execution, please replace immediately" | Forced sunset (runtime error) |
Since the core idea of deprecation is "preserve the runtime path", you should use SoonOfflinewhen the node is changed to "throw an error directly at runtime". Offline。
import { PluginStatusEnum } from '../../../../../plugin/type';
export const FooNode: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.foo,
// ...
status: PluginStatusEnum.SoonOffline, // ← 加这个
// ...
};
⚠️ Note: this field is attached to
FlowNodeTemplateTypeSchema(that is,systemtemplate extension), not onFlowNodeCommonTypeSchema. This means it only applies tosystem node templates, and the nodeData saved in the store does not carry status; each time it is opened, it is looked up from the template viamoduleTemplatesFlat.find(...). Thereforeonly the template needs to be changed, no data migration is required。
⚠️ There is also a seemingly related
abandon: z.boolean().optional()(FlowNodeCommonTypeSchema:72)—— Do not use it; no UI/runtime code in the entire repository reads it, it is a dead field.
7. Check UI / Hook references
Usually the following filesremain as-is(required for runtime compatibility):
projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/index.tsx—nodeTypesReact render mapping in .projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/hooks/useWorkflow.tsx—PARENT_NODE_TYPES、unSupportedInLoopand other runtime validations.
If the node has an "Add button" shortcut entry in the frontend (not triggered through the template panel), that kind of entry can be deleted.
8. Run lint + typecheck + local tests
# typescript 检查
pnpm lint
# 跑相关单测(按改动文件局部跑)
cd packages/service && pnpm test ...
Don't run the full test suite, only run what's related to the changes.
Verification checklist
After deprecation is complete, confirm the following scenarios:
- In the template panel (the "Add Node" sidebar),you cannot findthis node by searching.
- Existing old workflows that already contain this node canopen, load, and run, and the UI renders normally.
- In old workflows, a yellow "deprecating soon" badge appears on the right side of the node header, and hovering shows a replacement hint.
-
pnpm lintpasses. - In dispatch/constants.ts, callbackMap is still
Record<FlowNodeTypeEnum, Function>fully covered (you cannot delete keys, otherwise TS will report an error).
Anti-patterns (do not do)
- ❌ Delete
FlowNodeTypeEnum.<enumKey>— old workflow JSON still contains this value. - ❌ Remove from
moduleTemplatesFlat— old workflows cannot find the template when loading. - ❌ Delete an entry from
dispatch/constants.ts's callbackMap — this will cause "unknown node type" at runtime. - ❌ Delete i18n name / intro keys — old workflows' tooltip / node titles will become raw keys.
- ❌ Delete the React node component (
Flow/index.tsx's nodeTypes mapping) — canvas rendering will crash. - ❌ Also deprecate shared child nodes (e.g.,
nestedStart/nestedEndis used by multiple containers at the same time). - ❌ When deprecating an entire node,add field-level
deprecated: trueto inputs/outputs — a node-level badge is sufficient; field-level is a separate mechanism (used for the scenario of "keep the node, retire a single field").