Skip to content

Commit 4dfd14f

Browse files
os-zhuangclaude
andauthored
fix(app-shell): remove never-firing record-change option from the flow trigger picker (#3427) (#2812)
The start-node trigger picker offered "Record changed (any)" (`record-change`), but the runtime routes it to the record-change trigger, which maps it to no hook — the flow binds yet never fires, so authoring it produced a silently-dead flow. Removed the option, and dropped `record-change` from the scope resolver's record/previous sets and the zh-CN labels. The create-or-update case is covered by `record-after-write`; a companion @objectstack/lint rule flags any hand-authored `record-change` at `os validate` time. Claude-Session: https://claude.ai/code/session_018939yJ413zG3irLzcTtqaa Co-authored-by: Claude <noreply@anthropic.com>
1 parent c19ac11 commit 4dfd14f

5 files changed

Lines changed: 24 additions & 6 deletions

File tree

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
---
2+
"@object-ui/app-shell": patch
3+
---
4+
5+
fix(app-shell): remove the never-firing `record-change` option from the flow trigger picker (#3427)
6+
7+
The Studio flow designer's start-node trigger picker offered "Record changed
8+
(any)" (`record-change`), but the runtime routes it to the record-change trigger,
9+
which maps it to no ObjectQL hook — so the flow binds yet **never fires**. Authoring
10+
it produced a silently-dead flow. Removed the option (and dropped `record-change`
11+
from the scope resolver's record/previous sets and the zh-CN labels). The common
12+
"created or updated" case is covered by `record-after-write`; a companion
13+
`@objectstack/lint` rule flags any hand-authored `record-change` at `os validate`
14+
time.

packages/app-shell/src/views/metadata-admin/i18n.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3213,7 +3213,6 @@ const FLOW_FIELD_ZH: Record<string, Record<string, FlowFieldZh>> = {
32133213
'record-after-write': '记录创建或更新后',
32143214
'record-before-update': '记录更新前',
32153215
'record-after-delete': '记录删除后',
3216-
'record-change': '记录变更(任意)',
32173216
schedule: '定时(cron)',
32183217
time_relative: '相对时间(日期扫描)',
32193218
manual: '手动 / 自动启动',

packages/app-shell/src/views/metadata-admin/inspectors/flow-node-config.test.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,14 @@ describe('start node trigger-field gating (#5)', () => {
2828
expect(isFieldVisible(condition, node, fields)).toBe(true);
2929
});
3030

31+
it('does NOT offer the never-firing `record-change` bare-noun option (#3427)', () => {
32+
// The runtime routes `record-change` to the record-change trigger, which maps
33+
// it to no hook — it never fires. Removed so the designer can't author a
34+
// silently-dead flow; the `os validate` lint flags any hand-written one.
35+
const triggerType = fields.find((f) => f.id === 'triggerType')!;
36+
expect(triggerType.options?.some((o) => o.value === 'record-change')).toBe(false);
37+
});
38+
3139
it('shows for a schedule trigger too', () => {
3240
const node = { id: 'start', type: 'start', config: { triggerType: 'schedule' } };
3341
expect(isFieldVisible(objectName, node, fields)).toBe(true);

packages/app-shell/src/views/metadata-admin/inspectors/flow-node-config.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,6 @@ const FLOW_NODE_CONFIG: Record<string, FlowConfigField[]> = {
250250
{ value: 'record-after-write', label: 'Record created or updated' },
251251
{ value: 'record-before-update', label: 'Record before update' },
252252
{ value: 'record-after-delete', label: 'Record deleted' },
253-
{ value: 'record-change', label: 'Record changed (any)' },
254253
{ value: 'schedule', label: 'Schedule (cron)' },
255254
{ value: 'time_relative', label: 'Time-relative (date sweep)' },
256255
{ value: 'manual', label: 'Manual / autolaunched' },
@@ -262,12 +261,12 @@ const FLOW_NODE_CONFIG: Record<string, FlowConfigField[]> = {
262261
ref: { kind: 'object' },
263262
placeholder: 'crm_lead',
264263
help: 'Target object for record / scheduled-scan triggers.',
265-
showWhen: { field: 'triggerType', equals: ['record-after-create', 'record-after-update', 'record-after-write', 'record-before-update', 'record-after-delete', 'record-change', 'schedule', 'webhook', 'event'] },
264+
showWhen: { field: 'triggerType', equals: ['record-after-create', 'record-after-update', 'record-after-write', 'record-before-update', 'record-after-delete', 'schedule', 'webhook', 'event'] },
266265
}),
267266
cfg('condition', 'Entry condition', 'expression', {
268267
placeholder: 'status == "qualifying" && previous.status != "qualifying"',
269268
help: 'CEL predicate — the flow runs only when this is true (for time-relative sweeps it gates each matched record). Leave empty to run on every event. On a "created or updated" trigger, `previous == null` selects the create path.',
270-
showWhen: { field: 'triggerType', equals: ['record-after-create', 'record-after-update', 'record-after-write', 'record-before-update', 'record-after-delete', 'record-change', 'schedule', 'time_relative', 'webhook', 'event'] },
269+
showWhen: { field: 'triggerType', equals: ['record-after-create', 'record-after-update', 'record-after-write', 'record-before-update', 'record-after-delete', 'schedule', 'time_relative', 'webhook', 'event'] },
271270
}),
272271
// Schedule descriptor — author the canonical nested `config.schedule` object
273272
// the runtime actually reads (resolveTriggerBinding → normalizeSchedule). This

packages/app-shell/src/views/metadata-admin/inspectors/flow-scope.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,6 @@ const RECORD_TRIGGER_TYPES = new Set([
8686
'record-before-write',
8787
'record-before-update',
8888
'record-after-delete',
89-
'record-change',
9089
]);
9190
/** Trigger types that carry a meaningful `previous` snapshot of the record.
9291
* `record-*-write` fires on update too, so `previous` is offered (empty on the
@@ -96,7 +95,6 @@ const PREVIOUS_TRIGGER_TYPES = new Set([
9695
'record-before-update',
9796
'record-after-write',
9897
'record-before-write',
99-
'record-change',
10098
]);
10199

102100
function asArray(v: unknown): unknown[] {

0 commit comments

Comments
 (0)